【问题标题】:Converting (Very) Complicated JSON objects to Scala Objects With Case Classes In Json4s使用 Json4s 中的案例类将(非常)复杂的 JSON 对象转换为 Scala 对象
【发布时间】:2026-02-15 05:20:02
【问题描述】:

我有一个非常复杂的 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。

任何帮助都会很有用

谢谢!

【问题讨论】:

    标签: json scala case-class json4s


    【解决方案1】:

    您可以为FactsAnimalType 定义CustomSerializers。

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

    【讨论】:

    • 这太完美了!非常感谢!
    最近更新 更多