使用Private Builder的不可变类使用Jackson

2020年6月26日 29点热度 0条评论

我正在尝试使用Jackson来对DynamoDB V2 AttributeValue类进行序列化/反序列化。
它使用构建器设置为不可变的类,并且该构建器具有私有(private)构造函数。为了创建一个构建器,您需要调用AttributeValue.builder()
我无法控制此类,因此我想使用Jackson混合器。
我使用了@JsonDeserialize(builder = AttributeValue.Builder::class)并注册了mixin:

@JsonDeserialize(builder = AttributeValue.Builder::class)
interface AttributeValueMixin {
}

private val mapper = jacksonObjectMapper()
    .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)
    .addMixIn(AttributeValue::class.java, AttributeValueMixin::class.java)

但是, jackson (Jackson)试图使用
AttributeValue.Builder的默认构造函数,但由于它没有一个,所以不能使用。

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of software.amazon.awssdk.services.dynamodb.model.AttributeValue$Builder (no Creators, like default construct, exist)

我如何让Jackson使用
AttributeValue.builder()工厂功能?或关于如何使用Jackson对该
AttributeValue类进行序列化/反序列化的任何其他想法?

解决方案如下:

确实很棘手。我可以想到两种解决方案:

  • 在原始构建器周围创建包装器:
  • class BuilderDelegate {
    
        var field1 : String? = null
        var field2 : String? = null
        ...
    
        fun build() = AttributeValue.builder().also {
            it.field1 = field1
            it.field2 = field2
            ...
        }.build()
    }
    
    @JsonDeserialize(builder = BuilderDelegate::class)
    interface AttributeValueMixin {
    }
    
  • 如果您直接调用对象映射器,则可以尝试以下方法:
  • val builder = mapper.readerForUpdating(AttributeValue.builder())
    val value = builder.readValue<AttributeValue.Builder>(jsonData).build()