kotlin 莫希:如何使用固定和动态属性对JSON进行反序列化

aiazj4mn  于 2023-06-24  发布在  Kotlin
关注(0)|答案(1)|浏览(144)

对于这样的JSON,考虑attributes以外的属性是动态的:

"records": [
  {
    "attributes": {
      "type": "...",
      "url": "..."
    },
    "Id": "...",
    "Name": "...",
    "...": "..."
  }
]

我怎样才能反序列化或反编组到这样的数据类中,以便所有的动态键都进入recordBody: Map<String, Any>

@JsonClass(generateAdapter = true)
data class Body(
  val records: List<Record>,
)

@JsonClass(generateAdapter = true)
data class Record(
  val attributes: Attributes,
  val recordBody: Map<String, Any>
)

@JsonClass(generateAdapter = true)
data class Attributes(
  val type: String,
  val url: String
)

我找不到类似于@JsonAnySetter的注解

ds97pgxw

ds97pgxw1#

要将具有动态键的JSON反序列化到Record类中,可以定义一个自定义反序列化器,该反序列化器提取所有动态键值对并将它们放入Map<String,Any>示例中。下面是一个使用Jackson的示例实现:

import com.fasterxml.jackson.annotation.JsonAnySetter
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.annotation.JsonDeserialize

@JsonDeserialize(using = RecordDeserializer::class)
data class Record(
  val attributes: Attributes,
  val recordBody: Map<String, Any>
)

class RecordDeserializer : JsonDeserializer<Record>() {
  override fun deserialize(parser: JsonParser, context: DeserializationContext): Record {
    val node: JsonNode = parser.codec.readTree(parser)
    val attributes = context.readValue(node.get("attributes").traverse(), Attributes::class.java)
    val recordBody = mutableMapOf<String, Any>()
    node.fields()
      .asSequence()
      .filterNot { it.key == "attributes" }
      .forEach { recordBody[it.key] = context.readValue(it.value.traverse()) }
    return Record(attributes, recordBody)
  }

  @JsonAnySetter
  fun setDynamicProperty(name: String, value: Any) {
    // This method is called by Jackson for unmapped dynamic properties, but we don't use it here.
  }
}

在这个实现中,我们定义了一个自定义的RecordDeserializer,它使用JsonParser读取JSON树。我们首先使用context.readValue将attributes字段提取为一个单独的对象,它使用默认的反序列化规则。然后,我们迭代JSON对象中的所有其他字段(使用node.fields()),并将它们的名称和值添加到recordBodyMap中。
请注意,我们还使用@JsonDeserialize(使用= RecordDeserializer::class)注解Record类,以告诉Jackson为该类使用我们的自定义反序列化器。
我希望这对你有帮助!

相关问题