在Json4s中将(非常)复杂的JSON对象转换为带有案例类的Scala对象

时间:2015-10-07 13:20:33

标签: json scala case-class json4s

我有一个非常复杂的JSON文件,如下所示:

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

我试图解析这个结构,并以某种方式从中获取scala对象。

这是我的尝试:

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])

当然,这无法转换数据。它返回一个JNothing。我想知道如何在JArrays中正确表达复杂的JArrays。

任何帮助都会有用

谢谢!

1 个答案:

答案 0 :(得分:2)

您可以为CustomSerializerFacts定义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")}))

如果您将输入的json作为值json,则可以使用以下命令对其进行反序列化:

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))
//   ))
// ))