如何避免为JSON宏初始阶段的子类定义隐式读/写(将嵌套JSON结构转换为Scala)

如何避免为JSON宏初始阶段的子类定义隐式读/写(将嵌套JSON结构转换为Scala),json,scala,playframework-2.0,scala-macros,Json,Scala,Playframework 2.0,Scala Macros,我有一个要求,即传入的JSON对象是复杂的,并且大部分是嵌套的,例如: "users": { "utype": "PERSON", "language":"en_FR", "credentials": [ { "handle": "xyz@abc.com", "password": "123456", "handle_type": "EMAIL" } ], "person_details": {

我有一个要求,即传入的JSON对象是复杂的,并且大部分是嵌套的,例如:

"users": {
  "utype": "PERSON",
  "language":"en_FR",
  "credentials": [
    {          
      "handle": "xyz@abc.com",
      "password": "123456",
      "handle_type": "EMAIL"
    }
  ],
  "person_details": {
    "primary": "true",
    "names": [
      {
      "name_type": "OFFICIAL",
      "title": "MR",
      "given": "abc",
      "family": "zat",
      "middle": "pqs",
      "suffix":"anathan"
     }
    ],
    "addresses": [
      {
        "ad_type": "HOME",
        "line1": "Residential 2211 North 1st Street",
        "line2": "Bldg 17",
        "city": "test",
        "county": "Shefield",
        "state" : "NY",
        "country_code": "xx",
        "postal_code": "95131"
      }
    ]
  }
}
为了解析这个结构,我使用下面的Case类

case class PersonUser (
    user_type:String,
    language_code:String,
    credentials:List[Credential],
    person_details:PersonDetails
)

case class Credential(handle:String, password:String,handle_type:String)

case class PersonDetails(
    primary_user:Boolean,
    names: List[Name],
    addresses:List[Address]
)

case class Name(
    name_type: String,
    title: String,
    given: String,
    family: String,
    middle: String,
    suffix:String
)

case class Address(
    address_type: String,
    line1: String,
    line2: String,
    city: String,
    county: String,
    state : String,
    country_code: String,
    postal_code: String
)
为了将JSON结构转换为Scala,我使用了JSON Inception:

 implicit val testReads = Json.reads[PersonUser]
此外,我还必须在子类--凭证、个人信息、姓名和地址中指定类似的信息。以下给出了此类实例:

case class Credential(handle:String, password:String,handle_type:String)
object Credential{
   implicit val reads = Json.reads[Credential]
}

现在问题来了,如果我的JSON结构真的很大,有很多子结构,那么我需要定义很多Scala case类。为每个case类定义伴随对象和隐式读取将非常麻烦(例如:如果我有8个case类来完整地表示JSON结构,那么我将不得不再定义8个伴随对象)。有没有办法避免这些额外的工作?

没有,没有办法避免为每个要(反)序列化的类定义一个
格式
实例。

没有,没有办法避免为每个要(反)序列化的类定义一个
格式
实例。

没有,没有办法避免为每个要(反)序列化的类定义一个
格式
实例。

不,没有办法避免为每个要(反)序列化的类定义一个
格式
实例。

您还可以查看其他库,至少不需要定义大量的隐式。默认情况下,上面显示的代码应该与Genson一起使用

import com.owlike.genson.defaultGenson_

val personUser: PersonUser = fromJson[PersonUser](json)
val json = toJson(personUser)

Genson还有许多其他功能,我让您自己来判断。

您也可以查看其他LIB,至少不需要您定义大量的隐式。默认情况下,上面显示的代码应该与Genson一起使用

import com.owlike.genson.defaultGenson_

val personUser: PersonUser = fromJson[PersonUser](json)
val json = toJson(personUser)

Genson还有许多其他功能,我让您自己来判断。

您也可以查看其他LIB,至少不需要您定义大量的隐式。默认情况下,上面显示的代码应该与Genson一起使用

import com.owlike.genson.defaultGenson_

val personUser: PersonUser = fromJson[PersonUser](json)
val json = toJson(personUser)

Genson还有许多其他功能,我让您自己来判断。

您也可以查看其他LIB,至少不需要您定义大量的隐式。默认情况下,上面显示的代码应该与Genson一起使用

import com.owlike.genson.defaultGenson_

val personUser: PersonUser = fromJson[PersonUser](json)
val json = toJson(personUser)

Genson还有很多其他的功能,我让你自己来判断。

这个问题已经得到了回答,但我想我会解释为什么会是这样

  • 如果宏为嵌套的case类生成了必要的读取,则无法为这些嵌套的类定义自己的自定义读取。结果,宏只对最简单的情况有用,需要切换到手动实现整个层次结构的读取,只是为了定义一个深度嵌套的case类的自定义行为。现在宏的实现方式是,您可以轻松地任意更改宏的任何部分
  • 是的,头顶上有一个小样板。但另一方面,编译器会告诉您是否可以反序列化您的结构,这意味着您可以尽早捕获错误,使重构更安全,而且这也意味着没有那么多隐含的魔力,只有阅读文档才能知道它是如何工作的。通过强输入所有内容,没有神奇、没有意外、没有隐含的知识,从而提高了可维护性

  • 这个问题已经得到了回答,但我想我应该解释一下为什么会是这样

  • 如果宏为嵌套的case类生成了必要的读取,则无法为这些嵌套的类定义自己的自定义读取。结果,宏只对最简单的情况有用,需要切换到手动实现整个层次结构的读取,只是为了定义一个深度嵌套的case类的自定义行为。现在宏的实现方式是,您可以轻松地任意更改宏的任何部分
  • 是的,头顶上有一个小样板。但另一方面,编译器会告诉您是否可以反序列化您的结构,这意味着您可以尽早捕获错误,使重构更安全,而且这也意味着没有那么多隐含的魔力,只有阅读文档才能知道它是如何工作的。通过强输入所有内容,没有神奇、没有意外、没有隐含的知识,从而提高了可维护性

  • 这个问题已经得到了回答,但我想我应该解释一下为什么会是这样

  • 如果宏为嵌套的case类生成了必要的读取,则无法为这些嵌套的类定义自己的自定义读取。结果,宏只对最简单的情况有用,需要切换到手动实现整个层次结构的读取,只是为了定义一个深度嵌套的case类的自定义行为。现在宏的实现方式是,您可以轻松地任意更改宏的任何部分
  • 是的,头顶上有一个小样板。但另一方面,编译器会告诉您是否可以反序列化您的结构,这意味着您可以尽早捕获错误,使重构更安全,而且这也意味着没有那么多隐含的魔力,只有阅读文档才能知道它是如何工作的。通过强输入所有内容,没有神奇、没有意外、没有隐含的知识,从而提高了可维护性

  • 这个问题已经得到了回答,但我想我应该解释一下为什么会是这样

  • 如果宏为嵌套的case类生成了必要的读取,则无法为这些嵌套的类定义自己的自定义读取。结果,宏只对最简单的情况有用,需要切换到手动实现整个层次结构的读取,只是为了定义一个深度嵌套的case类的自定义行为。现在宏的实现方式是c