[英]Jackson - combine @JsonValue and @JsonSerialize
我正在嘗試@JsonValue
和@JsonSerialize
的組合。 讓我們從我當前的容器類開始:
public class Container {
private final Map<SomeKey, Object> data;
@JsonValue
@JsonSerialize(keyUsing = SomeKeySerializer.class)
public Map<SomeKey, Object> data() {
return data;
}
}
在這種情況下,不使用自定義序列化程序SomeKeySerializer
。
如果我按如下所示更改容器,則會調用序列化程序:
public class Container {
@JsonSerialize(keyUsing = SomeKeySerializer.class)
private final Map<SomeKey, Object> data;
}
但是,這不是我想要的,因為這會在輸出JSON中引入另一個“數據”級別。
是否有可能以某種方式組合@JsonValue
和@JsonSerialize
?
我總是可以為Container
編寫另一個自定義序列化程序,它或多或少與@JsonValue
背后的功能相同。 在我看來,這或多或少都是黑客攻擊。
傑克遜版本:2.6.2
這個組合似乎可以做你想要的:創建一個Converter從Container中提取Map,並將@JsonValue添加到SomeKey本身來序列化它:
@JsonSerialize(converter = ContainerToMap.class)
public class ContainerWithFieldData {
private final Map<SomeKey, Object> data;
public ContainerWithFieldData(Map<SomeKey, Object> data) {
this.data = data;
}
}
public static final class SomeKey {
public final String key;
public SomeKey(String key) {
this.key = key;
}
@JsonValue
public String toJsonValue() {
return "key:" + key;
}
@Override
public String toString() {
return "SomeKey:" + key;
}
}
public static final class ContainerToMap extends StdConverter<ContainerWithFieldData, Map<SomeKey, Object>> {
@Override
public Map<SomeKey, Object> convert(ContainerWithFieldData value) {
return value.data;
}
}
@Test
public void serialize_container_with_custom_keys_in_field_map() throws Exception {
ObjectMapper mapper = new ObjectMapper();
assertThat(
mapper.writeValueAsString(new ContainerWithFieldData(ImmutableMap.of(new SomeKey("key1"), "value1"))),
equivalentTo("{ 'key:key1' : 'value1' }"));
}
我根本無法輕易地將容器的訪問器方法注釋到DTRT,而不是與@JsonValue結合使用。 鑒於容器上的@JsonValue基本上都指定了一個轉換器(通過調用帶注釋的方法實現),這實際上是你所追求的,雖然不像它應該的那樣令人愉快。 (嘗試過Jackson 2.6.2)
(我從中學到了一些東西:關鍵序列化器不像普通的序列化器,即使它們實現JsonSerializer也是一樣的。例如,它們需要在JsonGenerator上調用writeFieldName,而不是writeString。在反序列化方面,JsonDeserializer和KeyDeserializer是拼寫出來的,但不是在序列化方面。你可以使用@JsonValue從SomeKey創建一個關鍵的序列化器,但不能用@JsonSerialize(使用= ...)注釋SomeKey,這讓我感到驚訝。
您是否嘗試過使用@JsonSerialize(using = SomeKeySerializer.class)
而不是keyUsing
?
用於序列化關聯值的Serializer類。
...對於keyUsing,你得到:
用於序列化帶注釋屬性的Map鍵的Serializer類
自己測試了它,它的工作原理......
public class Demo {
public static class Container {
private final Map<String, String> data = new HashMap<>();
@JsonValue
@JsonSerialize(using = SomeKeySerializer.class)
public Map<String, String> data() {
return data;
}
}
public static class SomeKeySerializer extends JsonSerializer<Map> {
@Override
public void serialize(Map value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeObjectField("aKeyInTheMap", "theValueForThatKey");
jgen.writeEndObject();
}
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
String s = objectMapper.writeValueAsString(new Container());
System.out.println(s);
}
}
這是我不使用com.fasterxml.jackson.annotation.JsonValue
時的輸出
{
"data" : {
"aKeyInTheMap" : "theValueForThatKey"
}
}
當我使用com.fasterxml.jackson.annotation.JsonValue
時,這是輸出
{
"aKeyInTheMap" : "theValueForThatKey"
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.