【问题标题】:Kotlin Jackson generation objects from JSON来自 JSON 的 Kotlin Jackson 生成对象
【发布时间】:2017-02-18 23:03:51
【问题描述】:

请帮忙!我正在尝试使用 jackson kotlin 模块从 JSON 生成对象。这里是json源:

{
    "name": "row",
    "type": "layout",
    "subviews": [{
        "type": "horizontal",
        "subviews": [{
            "type": "image",
            "icon": "ic_no_photo",
            "styles": {
                "view": {
                    "gravity": "center"
                }
            }
        }, {
            "type": "vertical",
            "subviews": [{
                "type": "text",
                "fields": {
                    "text": "Some text 1"
                }
            }, {
                "type": "text",
                "fields": {
                    "text": "Some text 2"
                }
            }]
        }, {
            "type": "vertical",
            "subviews": [{
                "type": "text",
                "fields": {
                    "text": "Some text 3"
                }
            }, {
                "type": "text",
                "fields": {
                    "text": "Some text 4"
                }
            }]
        }, {
            "type": "vertical",
            "subviews": [{
                "type": "image",
                "icon": "ic_no_photo"
            }, {
                "type": "text",
                "fields": {
                    "text": "Some text 5"
                }
            }]
        }]
    }]
}

我正在尝试生成 Skeleton 类的实例。

data class Skeleton (val type : String,
                         val name: String,
                         val icon: String,
                         val fields: List<Field>,
                         val styles: Map<String, Map<String, Any>>,
                         val subviews : List<Skeleton>)

data class Field (val type: String, val value: Any)

如您所见,Skeleton 对象内部可以有其他 Skeleton 对象(这些对象内部也可以有其他 Skeleton 对象),Skeleton 也可以有 Field 对象列表

val mapper = jacksonObjectMapper()
val skeleton: Skeleton = mapper.readValue(File(file))

这段代码以异常结束:

com.fasterxml.jackson.databind.JsonMappingException: Instantiation of [simple type, class com.uibuilder.controllers.parser.Skeleton] value failed (java.lang.IllegalArgumentException): Parameter specified as non-null is null: method com.uibuilder.controllers.parser.Skeleton.<init>, parameter name
 at [Source: docs\layout.txt; line: 14, column: 3] (through reference chain: com.uibuilder.controllers.parser.Skeleton["subviews"]->java.util.ArrayList[0]->com.uibuilder.controllers.parser.Skeleton["subviews"]->java.util.ArrayList[0])

【问题讨论】:

    标签: json jackson kotlin


    【解决方案1】:

    我发现关于您的映射有几个问题会阻止杰克逊从 JSON 读取值:

    • Skeleton 类具有非空构造函数参数(例如 val type: String,而不是 String?),如果 JSON 中缺少这些参数的值,Jackson 会将 null 传递给它们。这就是导致您提到的异常的原因:

      指定为非空的参数为空:方法com.uibuilder.controllers.parser.Skeleton.&lt;init&gt;,参数name

      为避免这种情况,您应该将可能缺少值的参数标记为可为空(您的案例中的所有参数):

      data class Skeleton(val type: String?,
                          val name: String?,
                          val icon: String?,
                          val fields: List<Field>?,
                          val styles: Map<String, Map<String, Any>>?,
                          val subviews : List<Skeleton>?)
      
    • Skeleton 中的fields 具有 List&lt;Field&gt; 类型,但在 JSON 中它由单个对象表示,而不是由数组表示。解决方法是将fields 参数类型更改为Field?

      data class Skeleton(...
                          val fields: Field?,
                          ...)
      
    • 另外,您代码中的 Field 类与 JSON 中的对象不匹配:

      "fields": {
          "text": "Some text 1"
      }
      

      您也应该更改Field 类,使其具有text 属性:

      data class Field(val text: String)
      

    完成我列出的更改后,Jackson 可以成功读取相关 JSON。


    另请参阅: "Null Safety" in Kotlin reference

    【讨论】:

    • 如果json字段值为null,有没有办法在反序列化过程中使用构造函数参数的默认值?还保持数据类中的字段不可为空?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    相关资源
    最近更新 更多