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

fykwrbwg  于 2023-03-06  发布在  Java
关注(0)|答案(4)|浏览(138)

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

@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);
    }  
}

为聚合对象创建其他自定义序列化程序的想法是基于"special"属性值的不同行为。但是,上面的代码不起作用,因为它进入了无限递归,这并不奇怪。
有没有办法告诉jackson在我设置属性后使用默认的序列化?我不想像许多自定义序列化器那样枚举所有的属性,因为类相当复杂,而且我不想在每次更改类时都要对序列化器进行双重维护。

r7xajy2e

r7xajy2e1#

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

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

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);
    }
}

MyClass创建BeanSerializerModifier

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;
    }
}

注册序列化程序修饰符

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

czfnxgou2#

@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);
        } else {
            provider.defaultSerializeValue(myClass, generator);
        }
    }  
}

如果你只是像平常一样写一个对象,使用上面的代码

km0tfn4u

km0tfn4u3#

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

public class MyClass{

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

}
8e2ybdfx

8e2ybdfx4#

要补充所选答案,串行化器实现可能还必须实现ContextualSerializerResolvableSerializer接口。

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);
    }
}

}
此外,如果您使用的是Sping Boot ,则添加Jackson模块非常简单,方法如下

@Component
public class MyModule extends SimpleModule {

    @Override
    public void setupModule(SetupContext context) {
        context.addBeanSerializerModifier(new MyBeanSerializerModifier());
        super.setupModule(context);
    }
}

相关问题