Converting (Very) Complicated JSON objects to Scala Objects With Case Classes In Json4s

吃可爱长大的小学妹 提交于 2019-12-13 05:45:50

问题


I have a very complicated JSON file that looks like this:

       {
            "Animals": [
                [
                    100,
                    "Mammals",
                    [
                        1,
                        "Cat",
                        50,
                        45,
                        57,
                        -1
                    ],
                    [
                        2,
                        "Dog",
                        31,
                        44,
                        18,
                        -1
                    ]
                ],
    [
                159,
                "Reptiles",
                [
                    1,
                    "Lizard",
                    11,
                    12,
                    9,
                    -1
                ]
            ]
]
    }

I am attempting to parse this structure and somehow get scala objects out of it.

Here was my attempt:

case class Facts(number: Int, subTypeOfAnimal: String, data: List[Int])

case class Animaltype(value: Int, typeOfAnimal: String, characteristics: List[Facts])

case class Animal(rows: List[Animaltype])

This, of course, fails to convert the data. It returns a JNothing. I am wondering how I can express complex JArrays within JArrays of this kind properly.

Any help would be useful

Thanks!


回答1:


You can define CustomSerializers for Facts and AnimalType.

import scala.util.Try

import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._
import org.json4s.native.Serialization

case class Facts(number: Int, subTypeOfAnimal: String, data: List[Int])
case class AnimalType(value: Int, typeOfAnimal: String, characteristics: List[Facts])
case class Animal(Animals: List[AnimalType])

implicit val formats = Serialization.formats(NoTypeHints) + 
  new AnimalTypeSerializer + new FactsSerializer

class FactsSerializer extends CustomSerializer[Facts](format => ( {
  case JArray(JInt(nr) :: JString(subType) :: data) => 
    Facts(nr.toInt, subType, data.collect{ case JInt(i) => i.toInt})
}, { case _ => throw new RuntimeException("No serializing")}))

class AnimalTypeSerializer extends CustomSerializer[AnimalType](format => ( {
  case JArray(JInt(value) :: JString(typeAnimal) :: factsArrays) => 
    val facts = factsArrays.collect { case facts: JArray => 
      Try(facts.extract[Facts]).toOption
    }.flatten
    AnimalType(value.toInt, typeAnimal, facts)
}, { case _ => throw new RuntimeException("No serializing")}))

If you take your input json as the value json you can deserialize it with :

parse(json).extract[Animal]
// Animal = Animal(List(
//   AnimalType(100,Mammals,List(
//     Facts(1,Cat,List(50, 45, 57, -1)), Facts(2,Dog,List(31, 44, 18, -1))
//   )),
//   AnimalType(159,Reptiles,List(
//     Facts(1,Lizard,List(11, 12, 9, -1))
//   ))
// ))


来源:https://stackoverflow.com/questions/32993338/converting-very-complicated-json-objects-to-scala-objects-with-case-classes-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!