使用 @JsonUnwrapped 并拥有自定义序列化程序 (StdSerializer<T>)

问题描述

我需要为我的实体“Payment”之一编写自定义序列化程序,我必须通过扩展 StdSerializer 来实现它:

class Payment {
}

class PaymentSerializer extends StdSerializer<Payment> {

    public PaymentSerializer() {
        this(null);
    }

    public PaymentSerializer(Class<Payment> t) {
        super(t);
    }

    @Override
    public void serialize(Payment value,JsonGenerator gen,SerializerProvider provider) throws IOException {
        // some logics
    }

}

因为我使用 Spring,所以我注册了这个 Serializer 以便 Spring 可以识别它:

@Bean
public Jackson2ObjectMapperBuilder serializersObjectMapperBuilder() {
    SimpleModule module = new SimpleModule();
    module.addSerializer(Payment.class,applicationContext.getBean(PaymentSerializer.class));
    return new Jackson2ObjectMapperBuilder().modules(module);
}

现在我有一个控制器将数据返回给客户端,它使用这个序列化程序没有任何问题:

@RestController
@RequestMapping("/payment")
class PaymentController {

    @GetMapping
    public List<Payment> getAll() {
        return Arrays.asList(new Payment());
    }

}

从现在开始,我的序列化程序运行良好,一切正常。

问题出在另一个实体“Order”上,该实体将 Payment 作为属性使用 @JsonUnwrapped

class Order {

    @JsonUnwrapped
    private Payment payment;

}

我需要解开 Payment 中的 Order 并且我想使用相同的 PaymentSerializer 但问题是当我使用这个自定义序列化程序时,{{1 }} 注释将被忽略,输出将是这样的:

@JsonUnwrapped

正如我所提到的,我想消除“付款”字段并将其打开。 我知道要为自定义序列化程序模拟 { "payment": { ..... } } ,我需要扩展 @JsonUnwrapped 类,但正如我最初提到的,我也需要标准序列化程序。

改变我的实体模型不是我的选择。

有没有办法做到这一点?

我使用 UnwrappingBeanSerializer,我认为它使用了 Spring Boot 2.1.3.RELEASE

解决方法

我提出以下解决问题的方法: 我们可以在单个自定义序列化程序中组合两个 StdSerializer

@Component
class PaymentSerializer extends StdSerializer<Payment> {

    private final JsonSerializer<Payment> delegate = new UnwrappingPaymentSerializer(NameTransformer.NOP);

    public PaymentSerializer() {
        this(null);
    }

    public PaymentSerializer(Class<Payment> t) {
        super(t);
    }

    @Override
    public void serialize(Payment value,JsonGenerator generator,SerializerProvider provider) throws IOException {
        generator.writeStartObject();
        this.delegate.serialize(value,generator,provider);
        generator.writeEndObject();
    }

    @Override
    public JsonSerializer<Payment> unwrappingSerializer(final NameTransformer nameTransformer) {
        return new UnwrappingPaymentSerializer(nameTransformer);
    }

}

并展开:

public class UnwrappingPaymentSerializer extends JsonSerializer<Payment> {

    private NameTransformer transformer;

    public UnwrappingPaymentSerializer(NameTransformer transformer) {
        this.transformer = transformer;
    }

    @Override
    public void serialize(Payment value,SerializerProvider provider) throws IOException {
        // some logics
    }

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

因此,您只有一个用于序列化和解包的序列化程序。 有关详细信息,请参阅:https://michael-simons.github.io/simple-meetup/unwrapping-custom-jackson-serializer

如果解决方案不适用,请告诉我,我会根据项目要求尝试提出其他方法。