java 如何在自定义序列化程序中访问默认 jackson 序列化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31056215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 18:00:41  来源:igfitidea点击:

How to access default Hymanson serialization in a custom serializer

javajsonHymanson

提问by DavidA

I want to create a custom serializer which does a tiny bit of work and then leaves the rest for default serialization.

我想创建一个自定义序列化程序,它只做一点工作,然后将其余部分留给默认序列化。

For example:

例如:

@JsonSerialize(using = MyClassSerializer.class)
public class MyClass {
  ...
}

public class MyClassSerializer extends JsonSerializer<MyClass> {
    @Override
    public void serialize(MyClass myClass, JsonGenerator generator, 
                          SerializerProvider provider) 
            throws JsonGenerationException, IOException {
        if (myClass.getSomeProperty() == someCalculationResult) {
            provider.setAttribute("special", true);
        }
        generator.writeObject(myClass);
    }  
}

With the idea of creating other custom serializers for aggregated objects which behave differently based on the 'special' attribute value. However, the above code does not work, as it unsurprisingly goes into an infinite recursion.

本着为聚合对象创建其他自定义序列化程序的想法,这些对象的行为基于“特殊”属性值而有所不同。但是,上面的代码不起作用,因为它毫不奇怪地进入了无限递归。

Is there a way to tell Hymanson to use default serialization once I have set the attribute? I don't really want enumerate all the properties like many custom serializers as the class is fairly complex and I don't want to have to do dual maintenance with the serializer every time I change the class.

一旦我设置了属性,有没有办法告诉 Hymanson 使用默认序列化?我真的不想像许多自定义序列化程序一样枚举所有属性,因为该类相当复杂,而且我不想每次更改类时都必须对序列化程序进行双重维护。

回答by Sam Berry

A BeanSerializerModifierwill provide you access to the default serialization.

ABeanSerializerModifier将为您提供对默认序列化的访问。

Inject a default serializer into the custom serializer

将默认序列化程序注入自定义序列化程序

public class MyClassSerializer extends JsonSerializer<MyClass> {
    private final JsonSerializer<Object> defaultSerializer;

    public MyClassSerializer(JsonSerializer<Object> defaultSerializer) {
        this.defaultSerializer = checkNotNull(defaultSerializer);
    }

    @Override
    public void serialize(MyClass myclass, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (myclass.getSomeProperty() == true) {
            provider.setAttribute("special", true);
        }
        defaultSerializer.serialize(myclass, gen, provider);
    }
}

Create a BeanSerializerModifierfor MyClass

创建BeanSerializerModifierMyClass

public class MyClassSerializerModifier extends BeanSerializerModifier {
    @Override
    public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
        if (beanDesc.getBeanClass() == MySpecificClass.class) {
            return new MyClassSerializer((JsonSerializer<Object>) serializer);
        }
        return serializer;
    }
}

Register the serializer modifier

注册序列化器修饰符

ObjectMapper om = new ObjectMapper()
        .registerModule(new SimpleModule()
                .setSerializerModifier(new MyClassSerializerModifier()));

回答by LawrenceMouarkach

@JsonSerialize(using = MyClassSerializer.class)
public class MyClass {
...
}

public class MyClassSerializer extends JsonSerializer<MyClass> {
    @Override
     public void serialize(MyClass myClass, JsonGenerator generator, 
                      SerializerProvider provider) 
        throws JsonGenerationException, IOException {
        if (myClass.getSomeProperty() == someCalculationResult) {
            provider.setAttribute("special", true);
        } 
        provider.defaultSerializeValue(myClass, generator);

    }  
}

if you are just writing an object as normal use the above

如果您只是像往常一样编写对象,请使用上述内容

回答by Alex Block

You can use @JsonGetter instead of using a custom serializer if that's the only change you want to make.

如果这是您想要进行的唯一更改,您可以使用 @JsonGetter 而不是使用自定义序列化程序。

public class MyClass{

    @JsonGetter("special")
    protected boolean getSpecialForHymanson() {
        return myClass.getSomeProperty() == someCalculationResult;
    }

}

回答by Pawel Zieminski

To add to the chosen answer, the serializer implementation may also have to implement ContextualSerializerand ResolvableSerializerinterfaces. Please take a look at a related issue here https://github.com/FasterXML/Hymanson-dataformat-xml/issues/259

要添加到所选答案中,序列化器实现可能还必须实现ContextualSerializerResolvableSerializer接口。请在此处查看相关问题 https://github.com/FasterXML/Hymanson-dataformat-xml/issues/259

public class MyClassSerializer extends JsonSerializer<MyClass>
    implements ContextualSerializer, ResolvableSerializer {
private final JsonSerializer<Object> defaultSerializer;

public MyClassSerializer(JsonSerializer<Object> defaultSerializer) {
    this.defaultSerializer = checkNotNull(defaultSerializer);
}

@Override
public void serialize(MyClass myclass, JsonGenerator gen, SerializerProvider provider)
        throws IOException {
    if (myclass.getSomeProperty() == true) {
        provider.setAttribute("special", true);
    }
    defaultSerializer.serialize(myclass, gen, provider);
}

@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
        throws JsonMappingException {
    if (defaultSerializer instanceof ContextualSerializer) {
        JsonSerializer<?> contextual = ((ContextualSerializer)defaultSerializer).createContextual(prov, property);
        return new MyClassSerializer((JsonSerializer<Object>)contextual);
    }
    return new MyClassSerializer(defaultSerializer);
}

@Override
public void resolve(SerializerProvider provider) throws JsonMappingException {
    if (defaultSerializer instanceof ResolvableSerializer) {
        ((ResolvableSerializer)defaultSerializer).resolve(provider);
    }
}

}

}