简体   繁体   中英

How to deserialize extra properties of json document into a map or other field with jackson?

I have a class/interface pair defined like this in Kotlin:

@JsonDeserialize(`as` = SimpleEvent::class)
interface Event {
    val organizationId: UUID
    val userId: UUID
    val eventTime: LocalDateTime
    val eventId: UUID
    @get:JsonAnyGetter
    @get:JsonAnySetter
    val details: Map<String, JsonNode>
}

data class SimpleEvent(
    override val organizationId: UUID,
    override val userId: UUID,
    override val eventTime: LocalDateTime,
    override val eventId: UUID,
    override val details: Map<String, JsonNode>
) : Event

My goal is to turn any extra fields from the json document as entries in the details map. The @JsonAnyGetter and @JsonAnySetter annotations are promising, but I can't find a way to make @JsonAnySetter work with immutable constructor parameters. @JsonAnyGetter works as intended, but @JsonAndSetter appears to be ignored.

I had a similar issue and this worked for me:

data class MyDataClass(
  val field1: Int,
  val field2: String,
  @JsonAnySetter
  @get:JsonAnyGetter
  val otherFields: Map<String, Any> = hashMapOf()
)

@JsonAnySetter tells Jackson to use the otherFields Map as a "catch all" for any name-value pairs it encounters during deserialization that can't be mapped to any of the explicit fields.

Conversely @JsonAnyGetter tells Jackson that otherFields is a source of other fields to be serialized, apart from the fields explicitly declared in the class.

I didn't get what the get: was for at first, but it turns out that it's a use-site target that tells the compiler to apply the JsonAnyGetter annotation to the Java getter generated from the Kotlin element (the constructor parameter). Without it the compiler complains that @JsonAnyGetter "cannot be applied to the target value parameter".

Use @JsonAnySetter on a mutable property. It is not yet supported for constructor parameters, although there is a request to add that:

https://github.com/FasterXML/jackson-databind/issues/562

As workaround, this works:

@JsonAnySetter
@get:JsonAnyGetter
        val others:Map<String,JsonNode> = LinkedHashMap()  /* workaround!*/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM