【问题标题】:spray json in scala: deserializing json with unknown fields without losing them在scala中喷洒json:反序列化具有未知字段的json而不会丢失它们
【发布时间】:2021-03-19 04:20:24
【问题描述】:

我正在寻找this 的解决方案,但对于 json spray,我的搜索和尝试使用 json spray 的工作到目前为止都失败了。

如果我有以下 json:

{
  "personalData": {
    "person": {
        "first": "first_name",
        "last": "last_name"
    },
    "contact": {
        "phone": "1111111",
        "address": {
            "line": "123 Main St",
            "city": "New York"
        }
    },
    "xx": "yy", // unknown in advanced
    "zz": { // unknown in advanced
        "aa": "aa",
        "bb": "bb",
        "cc": {
            "dd": "dd",
            "ee": "ee"
        }
    }
  }
}

我们确定 json 将包含人员和联系人,但我们不知道上游可能会创建哪些我们不关心/不使用的其他字段。

我想将此 JSON 序列化为包含人员和联系人的案例类,但另一方面,我不想丢失其他字段(将它们保存在地图中,这样该类将被反序列化为与收到)。

这是我已经做到的程度:

case class Address(
                    line:        String,
                    city:        String,
                    postalCode:  Option[String]
                  )

case class Contact(
                    phone:       String,
                    address:     Address
                  )

case class Person(
                   first:      String,
                   last:      String
                 )

case class PersonalData(
                         person:      Person,
                         contact:     Contact,
                         extra:       Map[String, JsValue]
                       )

implicit val personFormat = jsonFormat2(Person)
implicit val addressFormat = jsonFormat3(Address)
implicit val contactFormat = jsonFormat2(Contact)

implicit val personalDataFormat = new RootJsonFormat[PersonalData] {
  def write(personalData: PersonalData): JsValue = {
    JsObject(
      "person" -> personalData.person.toJson,
      "contact" -> personalData.contact.toJson,
      // NOT SURE HOW TO REPRESENT extra input
    )
  }

  def read(value: JsValue): CAERequestBEP = ???
}

有人可以帮我用 spray.json 而不是玩吗?我花了很长时间试图做到这一点,但似乎无法让它发挥作用。

【问题讨论】:

    标签: json scala spray spray-json


    【解决方案1】:

    为此,您需要为PersonalDataFormat 编写自己的格式化程序:

    case class Person(first: String, last: String)
    case class Address(line: String, city: String)
    case class Contact(phone: String, address: Address)
    case class PersonalData(person: Person, contact: Contact, extra: Map[String, JsValue])
    case class Entity(personalData: PersonalData)
    
    implicit val personFormat = jsonFormat2(Person)
    implicit val addressFormat = jsonFormat2(Address)
    implicit val contactFormat = jsonFormat2(Contact)
    implicit object PersonalDataFormat extends RootJsonFormat[PersonalData] {
      override def read(json: JsValue): PersonalData = {
        val fields = json.asJsObject.fields
        val person = fields.get("person").map(_.convertTo[Person]).getOrElse(???) // Do error handling instead of ???
        val contact = fields.get("contact").map(_.convertTo[Contact]).getOrElse(???) // Do error handling instead of ???
        PersonalData(person, contact, fields - "person" - "contact")
      }
    
      override def write(personalData: PersonalData): JsValue = {
        JsObject(personalData.extra ++ ("person" -> personalData.person.toJson, "contact" -> personalData.contact.toJson))
      }
    }
    
    implicit val entityFormat = jsonFormat1(Entity)
    
    val jsonResult = jsonString.parseJson.convertTo[Entity]
    

    结果是:

    Entity(PersonalData(Person(first_name,last_name),Contact(1111111,Address(123 Main St,New York)),Map(xx -> "yy", zz -> {"aa":"aa","bb":"bb","cc":{}})))
    

    (假设json不完全是上面的json,而是一个有效的类似的)

    代码在Scastie中运行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-24
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      相关资源
      最近更新 更多