代码之家  ›  专栏  ›  技术社区  ›  Vincent F

使用Kotlin中的Jackon反序列化嵌套json字段

  •  0
  • Vincent F  · 技术社区  · 6 年前

    我已经在Java中反序列化了一些嵌套字段,下面是 https://www.baeldung.com/jackson-nested-values (第5节):

    @JsonProperty("brand")
    private void unpackNested(Map<String,Object> brand) {
        this.brandName = (String)brand.get("name");
        Map<String,String> owner = (Map<String,String>)brand.get("owner");
        this.ownerName = owner.get("name");
    }
    

    ownerName 是一块豆子里的田地。

    现在,我需要在科特林做一些类似的事情,但我对我目前所拥有的并不满意。假设我有一个 MyPojo 有一个 createdAt 字段,但在表示该字段的JSON中,该字段嵌套在 metadata 属性:

    data class MyPojo(var createdAt: LocalDateTime = LocalDateTime.MIN) {
    
        @JsonProperty("metadata")
        private fun unpackNested(metadata: Map<String, Any>) {
    
            var createdAtAsString = metadata["createdAt"] as String
    
            this.createdAt = LocalDateTime.parse(createdAtAsString,DateTimeFormatter.ISO_DATE_TIME)
        }
    }
    

    我不喜欢这里的一件事是我被迫 创建日期 var ,不是 val .

    有什么科特林的把戏可以让这里的一切变得更好吗?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Willi Mentzel user670265    6 年前

    为了简单起见,我用 Int createdAt .

    你可以这样做:

    class JsonData(createdAt: Int = 0) {
    
        private var _createdAt: Int = createdAt
    
        val createdAt: Int
            get() = _createdAt
    
        @JsonProperty("metadata")
        private fun unpackNested(metadata: Map<String, Any>) {
            _createdAt =  metadata["createdAt"] as Int
        }
    }
    

    创建日期 将是具有默认值的参数。因为数据类的构造函数只能有属性( var / val )你将失去 data class ( toString() 开箱即用等)。

    将此参数指定给 private var _createdAt 当类被实例化时。

    唯一暴露在外部的是一个没有后备字段的属性 createAt (Java术语中的getter)。所以, _createdAt 实例化后无法更改。

    现在有两种情况:

    1. 如果你实例化这个类, _创建日期 将设置为您指定的值。
    2. 如果Jackson实例化类,则 _创建日期 将被 unpackNested 打电话来。

    下面是一个例子:

    val jsonStr = """{
        "metadata": {
            "createdAt": 1
        }
    }
    """.trimIndent()
    
    fun main() {
        val objectMapper = ObjectMapper()
    
        // Jackson does instantiation
        val jsonData = objectMapper.readValue(jsonStr, JsonData::class.java)
    
        // you do it directly
        JsonData(5)
    }