杰克逊:向地图序列化添加动态字段

类似于简化版本的@JsonAppend


public class Bean {


    @JsonAppend(key = [...], value = [...])

    public Map<?, ?> map = new HashMap<>();

}

那就太好了 - 任何简单的方法来实现这一目标?

但发现没有任何东西符合我的需求。

我提出请求的原因是,无法区分某些给定的JSON是否源自Map或POJO序列化。如果这是必要的(在极少数情况下),在地图上添加一个神奇的额外字段将是实现这一目标的简单方法。


慕容3067478
浏览 71回答 1
1回答

梵蒂冈之花

好问题!是的,这是(以某种方式)可能的。以下公开的方法维护标准序列化行为,同时在其上添加注释定义的键值对。创建自定义批注。我来称呼它MapAppender@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface MapAppender {&nbsp; &nbsp; String[] keys();&nbsp; &nbsp; String[] values();}如您所见,我们定义了键值数组,这些数组将按索引匹配。我们被迫使用字段而不是更通用的 ,但这是每个注释设计。StringObject创建自定义 .我来称呼它JsonSerializer<Map>MapAppenderSerializerpublic class MapAppenderSerializer&nbsp; &nbsp; &nbsp; &nbsp; extends StdSerializer<Map>&nbsp; &nbsp; &nbsp; &nbsp; implements ContextualSerializer {&nbsp; &nbsp; private static final long serialVersionUID = 1L;&nbsp; &nbsp; private final String[] keys;&nbsp; &nbsp; private final String[] values;&nbsp; &nbsp; // No-arg constructor required for Jackson&nbsp; &nbsp; MapAppenderSerializer() {&nbsp; &nbsp; &nbsp; &nbsp; super(Map.class);&nbsp; &nbsp; &nbsp; &nbsp; keys = new String[0];&nbsp; &nbsp; &nbsp; &nbsp; values = new String[0];&nbsp; &nbsp; }&nbsp; &nbsp; MapAppenderSerializer(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final String[] keys,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final String[] values) {&nbsp; &nbsp; &nbsp; &nbsp; super(Map.class);&nbsp; &nbsp; &nbsp; &nbsp; this.keys = keys;&nbsp; &nbsp; &nbsp; &nbsp; this.values = values;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public void serialize(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final Map value,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final JsonGenerator jsonGenerator,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final SerializerProvider serializerProvider) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; // Create a copy Map to avoid touching the original one&nbsp; &nbsp; &nbsp; &nbsp; final Map hashMap = new HashMap<>(value);&nbsp; &nbsp; &nbsp; &nbsp; // Add the annotation-specified key-value pairs&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < keys.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hashMap.put(keys[i], values[i]);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // Serialize the new Map&nbsp; &nbsp; &nbsp; &nbsp; serializerProvider.defaultSerializeValue(hashMap, jsonGenerator);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public JsonSerializer<?> createContextual(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final SerializerProvider serializerProvider,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final BeanProperty property) {&nbsp; &nbsp; &nbsp; &nbsp; MapAppender annotation = null;&nbsp; &nbsp; &nbsp; &nbsp; if (property != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; annotation = property.getAnnotation(MapAppender.class);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (annotation != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new MapAppenderSerializer(annotation.keys(), annotation.values());&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; throw new UnsupportedOperationException("...");&nbsp; &nbsp; }}现在,使用您的类示例,使用注释字段并定义自定义序列化程序BeanMap@MapAppender@JsonSerializepublic class Bean {&nbsp; &nbsp; public String simpleField;&nbsp; &nbsp; @MapAppender(keys = {"test1", "test2"}, values = {"value1", "value2"})&nbsp; &nbsp; @JsonSerialize(using = MapAppenderSerializer.class)&nbsp; &nbsp; public Map<Object, Object> simpleMap = new HashMap<>();}就是这样。序列化 的实例Beanfinal ObjectMapper objectMapper = new ObjectMapper();final String string = objectMapper.writeValueAsString(new Bean());结果{"simpleField":null,"simpleMap":{"test2":"value2","test1":"value1"}}另一个示例,在序列化之前用值填充Mapfinal ObjectMapper objectMapper = new ObjectMapper();final Bean value = new Bean();value.simpleMap.put("myKey", "myValue");final String string = objectMapper.writeValueAsString(value);结果{"simpleField":null,"simpleMap":{"test1":"value1","test2":"value2","myKey":"myValue"}}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java