Как получить доступ к сериализации Джексона по умолчанию в пользовательском сериализаторе


Я хочу создать пользовательский сериализатор, который выполняет крошечную часть работы, а затем оставляет остальное для сериализации по умолчанию.

Например:

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

С идеей создания других пользовательских сериализаторов для агрегированных объектов, которые ведут себя по-разному на основе значения атрибута' speical'. Однако приведенный выше код не работает, так как он неудивительно переходит в бесконечную рекурсию.

Есть ли способ сказать Джексону, чтобы он использовал сериализацию по умолчанию, как только я установил атрибут? Я действительно не хочу перечислять все свойства, как многие пользовательские сериализаторы, поскольку класс довольно сложен, и я не хочу делать двойное обслуживание с сериализатором каждый раз, когда я изменяю класс.

3 14

3 ответа:

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

Создайте BeanSerializerModifier для MyClass

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

Если вы просто пишете объект как обычно, используйте выше

Вы можете использовать @JsonGetter вместо пользовательского сериализатора, если это единственное изменение, которое вы хотите сделать.

public class MyClass{

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

}