Зная, что первый дочерний элемент myDocument
является переменным элементом, и что вам нужны только attr1
и attr2
дочерние элементы myDocument
s, вы можете сделать следующее:
import io.circe.Decoder
import io.circe._
import io.circe.jawn._
val in2 =
"""
|[
| {
| "myDocument": {
| "firstUnknown": {
| "attr1": "val1",
| "ignored": "not_important",
| "attr2": "val2"
| }
| }
| },
| {
| "myDocument": {
| "secondUnknown": {
| "also_ignored": "not_important",
| "attr1": "val3",
| "attr2": "val4"
| }
| }
| },
| {
| "myDocument": {
| "thirdUnknown": {
| "attr1": "val5",
| "ignored2": "not_important",
| "attr2": "val6",
| "again_ignored": "not_important"
| }
| }
| }
|]
""".stripMargin
case class MyDocument(attr1 : String, attr2 : String)
object MyDocument{
implicit val decoder : Decoder[MyDocument] = Decoder.instance{hCursor =>
val firstChildKey = hCursor.downField("myDocument").keys.flatMap(_.headOption)
firstChildKey.map{key =>
for{
attr1 <- hCursor.downField("myDocument").downField(key).downField("attr1").as[String]
attr2 <- hCursor.downField("myDocument").downField(key).downField("attr2").as[String]
} yield MyDocument(attr1,attr2)
}.getOrElse(Left(DecodingFailure("Element is not a Json object or it's empty.",List())))
}
}
val docs = parse(in2).flatMap(_.as[Vector[MyDocument]])
Идея состоит в том, что, как только мы переместим курсор на элемент myDocument
, мы получим все keys
, содержащиеся в объекте json, возьмем первый (который будет ключом элемента переменной, которым мы являемся).в), а затем используйте его, чтобы переместить курсор в нужную позицию для чтения attr1
и attr2
.
Результат последней строки будет:
Right(Vector(MyDocument(val1,val2), MyDocument(val3,val4), MyDocument(val5,val6)))