【问题标题】:Is JSON formatting not enough for parsing case class having > 22 fields?JSON 格式是否不足以解析具有 > 22 个字段的案例类?
【发布时间】:2017-03-09 10:56:24
【问题描述】:

我的案例类有 30 个字段。为简单起见,我使用了 4 个字段,

case class Person(id: Long, name: String, age: Int, sex: Sex)

val personFormat1: OFormat[(Long, String)] = ((__ \ "id").format[Long] ~ (__ \ "name").format[String]).tupled
val personFormat2: OFormat[(Int, Sex)] = ((__ \ "age").format[Int] ~ (__ \ "sex").format[Sex]).tupled
implicit val personFormat: Format[Person] = (personFormat1 ~ personFormat2)({
  case ((id, name), (age, sex)) => new Person(id, name, age, sex)
}, (person: Format) => ((person.id, person.name), (person.age, person.sex)))

但是,即使在使用 format1 作为一组 22 个字段和 format2 作为一组 8 个字段编写格式化程序之后,我在尝试解析这个案例类的 json 时也会出错。

错误是 没有为 Person 类型找到作为 JsObject 的 Json 序列化程序。尝试为此类型实现隐式 OWrites 或 OFormat。

如何编写隐式 Owrite 或 OFormat?或者如何解决这个问题?

【问题讨论】:

    标签: json scala playframework


    【解决方案1】:

    我使用 Play-Json 扩展 库来处理超过 22 个字段的 JSON:https://github.com/xdotai/play-json-extensions

    libraryDependencies += "ai.x" %% "play-json-extensions" % "0.8.0"
    

    【讨论】:

    • 谢谢。但我试过这个。在 play-json-extensions 中没有用于反序列化的写入/读取方法。如何做到这一点?如果您能指出这一点,这将非常有帮助。
    • 你只能使用默认格式,好吧,你可以对一个字段做一些转换,比如用SingletonEncoder做大写左右,但没有更多。
    • "dīvide et īmpera" 我想这里是最好的策略。刚开始玩play的时候就开始用play-json-extensions了,但是上次我很久以前用过,没有遇到一个任务,它不能把JSON分成较小的部分。
    【解决方案2】:

    您需要一个隐式编写器来执行此操作。像这样的

    implicit val person= Json.format[Person]
    

    此外,如果您使用自定义数据类型,例如您的案例 Sex,您需要指定读取器和写入器。对于 Int、Long、String 等原始类型,您不需要这样做。

      def enumReads[T <: Enum[T]](mkEnum: String => T) = new Reads[T] {
        override def reads(json: JsValue): JsResult[T] =
          json match {
            case JsString(s) => try {
              JsSuccess(mkEnum(s))
            }
            catch {
              case e: IllegalArgumentException =>
                JsError("Not a valid enum value: " + s)
            }
            case v => JsError("Can't convert to enum: " + v)
          }
      }
    
      implicit val enumWrites = new Writes[Enum[_]] {
        def writes(e: Enum[_]) = JsString(e.toString)
      }
    
      implicit val sex = enumReads(Sex.valueOf)
    

    另外,升级到 scala 2.11 或更高版本以避免案例类中 22 个字段的限制。更多信息请看这里:How to get around the Scala case class limit of 22 fields?

    【讨论】:

    • 我想,你误解了我的问题。我的案例类有 30 个字段,超过 22 个字段。因此,我编写了一个自定义格式化程序,您可以在相关示例中看到它。因此,即使在使用此自定义格式化程序之后,我也会收到没有 json 序列化程序的错误。
    【解决方案3】:

    我用谷歌找到了这个,这对我很有用

    // https://mvnrepository.com/artifact/com.chuusai/shapeless_2.11
    libraryDependencies += "com.chuusai" % "shapeless_2.11" % "2.3.2"
    
    // https://mvnrepository.com/artifact/org.julienrf/play-json-derived-codecs_2.11
    libraryDependencies += "org.julienrf" % "play-json-derived-codecs_2.11" % "3.2"
    

    【讨论】:

      猜你喜欢
      • 2015-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-25
      • 2013-07-13
      相关资源
      最近更新 更多