Jackson - 使用 Builder 反序列化而不带注释
Jackson - deserialize using Builder without annotation
是否可以使用 Jackson 反序列化一个只有全参数构造函数和生成器的值 class(最终值,无 setter)?我无法使用 JsonDeserialize
和 JsonPOJOBuilder
,因为我正在尝试反序列化客户端库中定义的模型,所以我无法添加注释。我可以指定构建器使用其他方式吗?
您可以尝试使用 MixIn。
我已经为您的用例创建了一个示例:
原文class:
final class Sample {
final int id;
Sample(int id) {
this.id = id;
}
}
MixIn(提供具有相同参数的非参数构造函数):
@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
abstract class SampleMixin {
@JsonCreator
public SampleMixin(@JsonProperty("id") int id) {
}
}
反序列化:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Sample.class, SampleMixin.class);
Sample sample = mapper.readValue(json, Sample.class);
可以。生成器必须满足某些要求。例如,它的字段方法必须有特定的前缀,如 "with" 或 "set".
这是 DTO class 及其构建器,没有任何 jackson 注释:
public class DtoBuilderWithFinalFieldsWithoutJackson {
public final String stringValue;
private DtoBuilderWithFinalFieldsWithoutJackson(final String stringValue){
this.stringValue = stringValue;
}
public static Builder builder(){
return new Builder();
}
public static class Builder {
private String stringValue;
public Builder withStringValue(String stringValue) {
this.stringValue = stringValue;
return this;
}
public DtoBuilderWithFinalFieldsWithoutJackson build() {
return new DtoBuilderWithFinalFieldsWithoutJackson(stringValue);
}
}
}
无需对默认自定义对象进行任何额外操作,您就可以序列化此 dto 对象。您负责创建实例。杰克逊只需要访问字段。在我们的例子中,这是一个 public 字段。
如果使用DTO反序列化,需要自定义对象:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector(){
@Override
public Class<?> findPOJOBuilder(AnnotatedClass ac) {
//set analogue of: @JsonDeserialize(builder = DtoBuilderWithFinalFieldsWithoutJackson.Builder.class)
if (DtoBuilderWithFinalFieldsWithoutJackson.class.equals(ac.getRawType())) {
return DtoBuilderWithFinalFieldsWithoutJackson.Builder.class;
} else {
return super.findPOJOBuilder(ac);
}
}
@Override
public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) {
if (DtoBuilderWithFinalFieldsWithoutJackson.class.equals(ac.getRawType())) {
//both build and with - are default in this case:
//set analogue of @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "with")
return new JsonPOJOBuilder.Value("build", "with");
} else {
return super.findPOJOBuilderConfig(ac);
}
}
});
并在您的实施中使用此自定义的 CustomObject。这是一个测试,完整的例子可以在这里找到:DtoBuilderWithFinalFieldsWithoutJackson test
是否可以使用 Jackson 反序列化一个只有全参数构造函数和生成器的值 class(最终值,无 setter)?我无法使用 JsonDeserialize
和 JsonPOJOBuilder
,因为我正在尝试反序列化客户端库中定义的模型,所以我无法添加注释。我可以指定构建器使用其他方式吗?
您可以尝试使用 MixIn。
我已经为您的用例创建了一个示例:
原文class:
final class Sample {
final int id;
Sample(int id) {
this.id = id;
}
}
MixIn(提供具有相同参数的非参数构造函数):
@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
abstract class SampleMixin {
@JsonCreator
public SampleMixin(@JsonProperty("id") int id) {
}
}
反序列化:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Sample.class, SampleMixin.class);
Sample sample = mapper.readValue(json, Sample.class);
可以。生成器必须满足某些要求。例如,它的字段方法必须有特定的前缀,如 "with" 或 "set".
这是 DTO class 及其构建器,没有任何 jackson 注释:
public class DtoBuilderWithFinalFieldsWithoutJackson {
public final String stringValue;
private DtoBuilderWithFinalFieldsWithoutJackson(final String stringValue){
this.stringValue = stringValue;
}
public static Builder builder(){
return new Builder();
}
public static class Builder {
private String stringValue;
public Builder withStringValue(String stringValue) {
this.stringValue = stringValue;
return this;
}
public DtoBuilderWithFinalFieldsWithoutJackson build() {
return new DtoBuilderWithFinalFieldsWithoutJackson(stringValue);
}
}
}
无需对默认自定义对象进行任何额外操作,您就可以序列化此 dto 对象。您负责创建实例。杰克逊只需要访问字段。在我们的例子中,这是一个 public 字段。
如果使用DTO反序列化,需要自定义对象:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector(){
@Override
public Class<?> findPOJOBuilder(AnnotatedClass ac) {
//set analogue of: @JsonDeserialize(builder = DtoBuilderWithFinalFieldsWithoutJackson.Builder.class)
if (DtoBuilderWithFinalFieldsWithoutJackson.class.equals(ac.getRawType())) {
return DtoBuilderWithFinalFieldsWithoutJackson.Builder.class;
} else {
return super.findPOJOBuilder(ac);
}
}
@Override
public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) {
if (DtoBuilderWithFinalFieldsWithoutJackson.class.equals(ac.getRawType())) {
//both build and with - are default in this case:
//set analogue of @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "with")
return new JsonPOJOBuilder.Value("build", "with");
} else {
return super.findPOJOBuilderConfig(ac);
}
}
});
并在您的实施中使用此自定义的 CustomObject。这是一个测试,完整的例子可以在这里找到:DtoBuilderWithFinalFieldsWithoutJackson test