7

我正在编写一个需要从 JSON 序列化和反序列化的 Scala 应用程序。一些 JSON 对象有超过 22 个字段,所以我不能使用案例类(我也不能更改格式)。我能够找到的所有 Scala JSON 库都只能(很容易地)使用案例类,而不是普通类。

鉴于此,将大型 JSON 对象(具有超过 22 个字段)反序列化为 Scala 非案例类的最简单方法是什么?它不必是完全自动的,但理想情况下,我正在寻找比反序列化为 Map[String, Any] 并手动执行所有操作更痛苦的方法。

4

3 回答 3

4

更新:幸运的是,现在可以使用 Json4s 和 Jackson 使用字段序列化器执行我想要的操作,如下所示:

implicit val formats = DefaultFormats + FieldSerializer[MyNonCaseClass]()

val myNonCaseClassObject = Serialization.read[MyNonCaseClass](jsonString)

根据下面的要求,这是一个更完整的示例:

import org.json4s.jackson.Serialization
import org.json4s._
import scala.util.Try

object JSONUtil {

implicit val formats = DefaultFormats + FieldSerializer[MyNonCaseClass]() + FieldSerializer[MyOtherNonCaseClass](ignore("someUnwantedFieldName") orElse ignore("anotherFieldToIgnore")) + ...

def toJSON(objectToWrite: AnyRef): String = Serialization.write(objectToWrite)

def fromJSONOption[T](jsonString: String)(implicit mf: Manifest[T]): Option[T] = Try(Serialization.read(jsonString)).toOption

}

那么用法是:

val jsonString = JSONUtil.toJSON(myObject)
val myNewObject: Option[MyClass] = JSONUtil.fromJSONOption[MyClass](aJsonString)

对于要序列化的每个非案例类,您都需要一个 FieldSerializer。此外,在定义类时,JSON 中可能缺少的所有内容都需要定义为选项。

SBT:

"org.json4s" %% "json4s-jackson" % "3.2.6"
于 2013-06-26T00:19:46.050 回答
3

可以在没有案例类的情况下使用带有泛型的 Play JSON 库来做到这一点

当我喝着咖啡什么都不做的时候。我冒昧地为您编写了一个示例。完整的解决方案如下:

首先,这是你的课:

import play.api.libs.json._
import play.api.libs.json.Json._


    class TestJSON(
      val field1: String,
      val field2: String,
      val field3: String,
      val field4: String,
      val field5: String,
      val field6: String,
      val field7: String,
      val field8: String,
      val field9: String,
      val field10: String,
      val field11: String,
      val field12: String,
      val field13: String,
      val field14: String,
      val field15: String,
      val field16: String,
      val field17: String,
      val field18: String,
      val field19: String,
      val field20: String,
      val field21: String,
      val field22: String,
      val field23: String) {

    }

    object TestJSON {
      //
      // JSON BINDING/UNBINDING
      //

      implicit def modalityReads: Reads[TestJSON] = new Reads[TestJSON] {
        def reads(json: JsValue): TestJSON =
          new TestJSON(
            field1 = (json \ "field1").as[String],
            field2 = (json \ "field2").as[String],
            field3 = (json \ "field3").as[String],
            field4 = (json \ "field4").as[String],
            field5 = (json \ "field5").as[String],
            field6 = (json \ "field6").as[String],
            field7 = (json \ "field7").as[String],
            field8 = (json \ "field8").as[String],
            field9 = (json \ "field9").as[String],
            field10 = (json \ "field10").as[String],
            field11 = (json \ "field11").as[String],
            field12 = (json \ "field12").as[String],
            field13 = (json \ "field13").as[String],
            field14 = (json \ "field14").as[String],
            field15 = (json \ "field15").as[String],
            field16 = (json \ "field16").as[String],
            field17 = (json \ "field17").as[String],
            field18 = (json \ "field18").as[String],
            field19 = (json \ "field19").as[String],
            field20 = (json \ "field20").as[String],
            field21 = (json \ "field21").as[String],
            field22 = (json \ "field22").as[String],
            field23 = (json \ "field22").as[String])
      }

      implicit def modalityWrites: Writes[TestJSON] = new Writes[TestJSON] {
        def writes(ts: TestJSON) = JsObject(Seq(
          "field1" -> JsString(ts.field1),
          "field2" -> JsString(ts.field2),
          "field3" -> JsString(ts.field3),
          "field4" -> JsString(ts.field4),
          "field5" -> JsString(ts.field5),
          "field6" -> JsString(ts.field6),
          "field7" -> JsString(ts.field7),
          "field8" -> JsString(ts.field8),
          "field9" -> JsString(ts.field9),
          "field10" -> JsString(ts.field10),
          "field11" -> JsString(ts.field11),
          "field12" -> JsString(ts.field12),
          "field13" -> JsString(ts.field13),
          "field14" -> JsString(ts.field14),
          "field15" -> JsString(ts.field15),
          "field16" -> JsString(ts.field16),
          "field17" -> JsString(ts.field17),
          "field18" -> JsString(ts.field18),
          "field19" -> JsString(ts.field19),
          "field20" -> JsString(ts.field20),
          "field21" -> JsString(ts.field21),
          "field22" -> JsString(ts.field22),
          "field23" -> JsString(ts.field23)))
      }
    }

您的控制器应如下所示:

import play.api._
import play.api.mvc._
import play.api.libs.json.Json._
import play.api.Play.current
import models.TestJSON

object Application extends Controller  {

  def getJson = Action {
    implicit request =>
      Ok(
        toJson(
          Seq(
            toJson(
              new TestJSON(
                "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
                "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23")),
              toJson(new TestJSON(
                "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
                "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23")))))
  }

}

您的路由文件(只需路由操作):

GET     /getJson                             controllers.Application.getJson

而现在,关键时刻……

curl localhost:9000/getJson
[{"field1":"1","field2":"2","field3":"3","field4":"4","field5":"5","field6":"6",
"field7":"7","field8":"8","field9":"9","field10":"10","field11":"11","field12":"
12","field13":"13","field14":"14","field15":"15","field16":"16","field17":"17","
field18":"18","field19":"19","field20":"20","field21":"21","field22":"22","field
23":"23"},{"field1":"1","field2":"2","field3":"3","field4":"4","field5":"5","fie
ld6":"6","field7":"7","field8":"8","field9":"9","field10":"10","field11":"11","f
ield12":"12","field13":"13","field14":"14","field15":"15","field16":"16","field1
7":"17","field18":"18","field19":"19","field20":"20","field21":"21","field22":"2
2","field23":"23"}]

它也应该反过来工作。我目前正在一个项目中使用它来组装和拆卸大树,所以它应该适合你。让我知道。

干杯!

PS:别担心,我花了大约 10 分钟来生成代码。我刚刚映射了一个 List.range(1,24) 并“foreached”它来打印代码。

于 2012-12-18T03:42:29.020 回答
1

查看Lift JSON API

关键是所有被解析的东西都作为JValue. 像这样的对象

{
  "a": [1, 2],
  "b": "hello"
}

将被解析为

JObject(List(
  JField("a", JArray(List(JInt(1), JInt(2)))),
  JField("b", JString("hello"))
))

Lift API 提供了一些有用的方法,例如\让您可以访问Map. 还有一种extractOpt[A]方法会尽力将解析后的 JSON 转换为A您想要的任何内容。和他们一起玩,感受一下。

于 2012-12-18T03:53:24.153 回答