Json使用自定义JsonSerializer展开行为

Json使用自定义JsonSerializer展开行为

本文介绍了杰克逊@Json使用自定义JsonSerializer展开行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个这样的班级:

public class A {
    String aProp = "aProp";

    public String getAProp() {
        return aProp;
    }
}

public class B {
    String bProp = "bProp";
    A a = new A();

    @JsonProperty("bProp")
    public String getBProp() {
        return bProp;
    }

    @JsonSerialize(using = CustomSerializer.class)
    public A getA() {
        return a;
    }
}

我期望得到这样的JSON:

I'm expecting to get JSON like this:

{
    "bProp": "bProp",         // just serizlised bProp
    "sProp1": "sProp1_aProp", // computed using aProp
    "sProp2": "sProp2_aProp"  // computed another way
}

所以我这样写了自定义JsonSerializer:

So I wrote custom JsonSerializer like this:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class CustomSerializer extends JsonSerializer<A> {
    @Override
    public void serialize(A a, JsonGenerator json, SerializerProvider provider) throws IOException {
        json.writeStringField("sProp1", "sProp1_" + a.getAProp());
        json.writeStringField("sProp2", "sProp2_" + a.getAProp());
    }
}

但是我不断收到错误消息:

But I keep getting an error:

com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value

除非我将json.writeStartObject();json.writeEndObject();放在序列化方法中(这样它会产生错误的JSON).

Unless I put json.writeStartObject(); and json.writeEndObject(); in serialize method (so it produces wrong JSON).

所以我正在寻找像@JsonUnwrapped这样的解决方案以与自定义JsonSerializer一起使用.

So I'm looking for a solution like @JsonUnwrapped to use with custom JsonSerializer.

推荐答案

我了解您的问题,您需要的是UnwrappingBeanSerializer.您可以看到另一个相关的SO帖子:使用自定义json序列化程序时,不同的JSON输出在Spring Data Rest中

I understand your problem and the thing that you need is UnwrappingBeanSerializer. You can see another related SO post:Different JSON output when using custom json serializer in Spring Data Rest

问题是您不能在一个字段中同时包含注释@JacksonUnwrapped@JsonSerialize,因为当您拥有@JsonSerializer时,杰克逊将总是写字段名称.

The problem is that you cannot have both annotations @JacksonUnwrapped and @JsonSerialize in one field because when you have @JsonSerializer Jackson will always write field name.

这是完整的解决方案:

public class CustomSerializer  extends UnwrappingBeanSerializer {
    public CustomSerializer(BeanSerializerBase src, NameTransformer transformer) {
        super(src, transformer);
    }

    @Override
    public JsonSerializer<Object> unwrappingSerializer(NameTransformer transformer) {
        return new CustomSerializer(this, transformer);
    }

    @Override
    protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
        A a = (A) bean;
        jgen.writeStringField("custom", a.getAProp());
        jgen.writeStringField("custom3", a.getAProp());
    }

    @Override
    public boolean isUnwrappingSerializer() {
        return true;
    }

}

测试用例,您应该使用自定义配置重新定义对象映射器,或者研究其他方法.

Test case, you should redefine your object mapper with custom configuration or research for other method .

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = Application.class)
public class ColorsTest {

    ObjectMapper mapper = new ObjectMapper();

    @Before
    public void setUp(){
        mapper.registerModule(new Module() {
            @Override
            public String getModuleName() {
                return "my.module";
            }

            @Override
            public Version version() {
                return Version.unknownVersion();
            }

            @Override
            public void setupModule(SetupContext context) {

                context.addBeanSerializerModifier(new BeanSerializerModifier() {
                    @Override
                    public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
                        if(beanDesc.getBeanClass().equals(A.class)) {
                            return new CustomSerializer((BeanSerializerBase) serializer, NameTransformer.NOP);
                        }
                        return serializer;
                    }
                });

            }
        });
    }
    @Test
    public void testSerializer() throws JsonProcessingException {
        System.out.println(mapper.writeValueAsString(new B()));
    }
}

B级:

public class B {

        @JsonProperty("bProp")
        public String getBProp() {
            return "bProp";
        }


    @JsonUnwrapped
        public A getA() {
            return new A();
        }
}

这篇关于杰克逊@Json使用自定义JsonSerializer展开行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 10:45