【问题标题】:Jackson: Serialize an EER specialization杰克逊:序列化 EER 专业化
【发布时间】:2016-09-13 11:04:39
【问题描述】:

我正在使用带有 jackson 的 spring boot 来提供 API。 在我的数据库中有一个泛化/专业化领域。这意味着,我有两个字段:一个值和一个定义值的数据类型的字段。

所以我的实体看起来像这样:

public class Example{
    private String value;
    private String type;

    // getters and setters
}

例如这三个条目:

"1234";"Integer"
"example string";"String"
"true";"Boolean"

Jackson 将其序列化如下:

[{
    "value": "1234",
    "type": "Integer"
},
{
    "value": "example string",
    "type": "String"
},
{
    "value": "true",
    "type": "Boolean"
}]

这是我所期望的,但是,我需要这个:

[{
    "value": 1234,
    "type": "Integer"
},
{
    "value": "example string",
    "type": "String"
},
{
    "value": true,
    "type": "Boolean"
}]

因此,值应该根据“类型”字段的值进行序列化。 我知道我可以将序列化程序附加到“值”字段,但我无法访问那里的“类型”字段以了解如何序列化值。

【问题讨论】:

    标签: java json spring serialization jackson


    【解决方案1】:

    如果可以的话,一个选择是像这样更改您的示例类:

    public static class Example {
        private String value;
        private String type;
    
        @JsonIgnore
        public String getValue() {
            return value;
        }
    
        @JsonProperty("value")
        @JsonRawValue
        public Object getRawValue() {
            if("String" .equals(type)){
                return '"'+ value +'"';
            }
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    }
    

    或者您可以在 Example 类上使用反序列化器

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(Example.class, new MySerializer());
        mapper.registerModule(module);
        System.out.println(mapper.writeValueAsString(list));
    }
    
    private static class MySerializer extends JsonSerializer<Example> {
        @Override
        public void serialize(Example value, JsonGenerator gen, SerializerProvider serializers)
                                                                          throws IOException {
            gen.writeStartObject();
    
            gen.writeFieldName("value");
    
            if (value.getType().equals("String")) {
                gen.writeString( value.getValue());
            } else {
                gen.writeRawValue(value.getValue());
            }
    
            gen.writeStringField("type", value.getType());
            gen.writeEndObject();
        }
    }
    

    结果:

    [{"value":1234,"type":"Integer"},{"value":"example string","type":"String"},{"value":true,"type":"Boolean"}]
    

    更新

    这是您可以使用自定义反序列化器的一种方法,并为每个其他字段使用默认反序列化器:

    private static class MySerializer extends JsonSerializer<Example> {
        private static final ObjectMapper internalMapper = new ObjectMapper();
    
        @Override
        public void serialize(Example value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            ObjectNode node = internalMapper.valueToTree(value);
    
            if (value.getType().equals("String")) {
                node.put("value", value.getValue());
            } else {
                node.putRawValue("value", new RawValue(value.getValue()));
            }
    
            gen.writeObject(node);
        }
    }
    

    您的public String getValue() 中需要有@JsonIgnore

    【讨论】:

    • 嗨!感谢那。是否也可以在不明确定义如何处理每个字段的情况下对“值”期望的所有其他字段使用默认行为?我的实体有很多字段,我不想在多个类中列出/管理所有字段(实体、序列化器和反序列化器......)
    • @Indivon 我用新选项更新了答案,是的,您可以在自定义反序列化器中使用默认反序列化。给我一分钟,我会更新信息
    • @Indivon 更新了我的帖子,看一下,可能还有其他选项你可以尝试
    猜你喜欢
    • 1970-01-01
    • 2011-07-03
    • 2020-12-24
    • 2015-04-07
    • 1970-01-01
    • 2014-10-08
    • 2016-07-16
    • 2012-11-19
    • 2016-10-23
    相关资源
    最近更新 更多