繁体   English   中英

Jackson Custom序列化程序,用于某些字段的自定义行为,同时具有其余字段的默认行为

[英]Jackson Custom serializer for custom behaviour of some fields while having default behaviour for rest of the fields

例如,我有一个如下定义的POJO,其中jackson-corejackson-databind (版本2.8.3)注释省略了getter和setter以简洁起见。

class Sample {
     private String foo;
     private String bar;
     private Map<String, Map<String, Object>> data;
}

我想编写一个自定义序列化程序,它采用上面的POJO并生成

{
     "foo":"val",
     "bar":"val2",
     "data_1": {
          "someInt":1
     },
     "data_2": {
          "someBoolean":true
     }
}

这里data_1data_2是主Map键,它们的内部属性由它们的子映射(嵌套映射)组成。 此外,实际的属性数据根本不应出现在生成的JSON中。

请注意,foo和bar是字段的示例,实际上pojo有15个以上的字段。

请更正您的类变量数据 ,它应该是这样的

private Map<String,Map<String, Object>> data; 

然后编写一个序列化的方法,如下所示

public static void serializeSample() {
    ObjectMapper mapper = new ObjectMapper();
    Sample sample=new Sample();
    sample.setBar("val2");
    sample.setFoo("val");
    Map<String, Map<String, Object>> sampleData=new HashMap<>();
    Map<String, Object> data_3=new HashMap<>();
    Map<String, Object> data_4=new HashMap<>();
    data_3.put("someInt", 1);
    data_4.put("someBoolean", Boolean.TRUE);

    sampleData.put("data_1", data_3);
    sampleData.put("data_2", data_4);
    sample.setData(sampleData);

    try {
        mapper.writeValue(new File("log.txt"), sample);
    } catch (JsonGenerationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JsonMappingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }



}

这应该可以正常工作我想

您将需要一个自定义序列化程序,它迭代父Map 对于每个嵌套的Map您只需使用带有键的writeObjectField ,value作为字段名称和值。

您还需要自动序列化所有其他字段。 您可以仅在字段上设置自定义序列化程序,但仍然可以在JSON中获取data字段。 实际上,你想,让他们看起来像场以提升数据的内容Sample和需要自定义序列Sample 我可以想到的唯一方法是自动序列化除data字段之外的所有其他内容是使用反射

以下序列化程序将在您的问题中生成JSON:

class SampleSerializer extends StdSerializer<Sample> {
    private static final List<Field> sampleFields;

    public SampleSerializer() { this(null); }
    private SampleSerializer(Class<Sample> t) { super(t); }

    static {
        sampleFields = Arrays.stream(Sample.class.getDeclaredFields())
                .filter(f -> !("data".equals(f.getName())))
                .collect(toList());
    }

    @Override
    public void serialize(Sample sample, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        jgen.writeStartObject();
        for (Field field : sampleFields) {
            try {
                field.setAccessible(true);
                jgen.writeObjectField(field.getName(), field.get(sample));
            } catch (IllegalAccessException ignored) {
            }
        }
        for (Entry<String, Map<String, Object>> entry : sample.getData().entrySet()) {
            jgen.writeObjectField(entry.getKey(), entry.getValue());
        }
        jgen.writeEndObject();
    }
}

您还必须指定SampleSerializer将用于Sample ,例如通过注释该类:

@JsonSerialize(using = SampleSerializer.class)
class Sample {

我想出了一种更简单的方法,可以在不使用自定义序列化器的情况下完成此操作; 这是@JsonAnyGetter和@JsonAnySetter。 这是一个完整的例子。 我正在粘贴关于粘贴在这里的样本的答案,因为它可能对其他人有用。

class Sample {
     private String foo;
     private String bar;

     private Map<String, Map<String, Object>> data = new LinkedHashMap<>();

     @JsonAnyGetter
     public Map<String, Map<String, Object>> getData() {
          return data;
     }

     @JsonAnySetter
     public void set(String key, Map<String, Object>) {
          data.put(key, object);
     }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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