杰克逊 - 使用没有注释的Builder反序列化

时间:2017-10-24 06:35:59

标签: java json jackson lombok

是否可以使用Jackson反序列化只有all args构造函数和Builder的值类(final,no setters)?我无法使用JsonDeserializeJsonPOJOBuilder,因为我正在尝试反序列化在客户端库中定义的模型,因此我无法添加注释。我可以指定构建器以另一种方式使用吗?

2 个答案:

答案 0 :(得分:1)

您可以尝试使用MixIn。

我为您的用例创建了一个示例:

原班级:

final class Sample {

    final int id;

    Sample(int id) {
        this.id = id;
    }
}

MixIn(提供具有相同args的非args构造函数):

@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
abstract class SampleMixin {
    @JsonCreator
    public SampleMixin(@JsonProperty("id") int id) {
    }
}

Deserilaization:

ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Sample.class, SampleMixin.class);
Sample sample = mapper.readValue(json, Sample.class);

答案 1 :(得分:0)

可以。生成器必须满足某些要求。例如,其字段方法必须具有特定的前缀,例如“ with”或“ set”。

这是DTO类及其构建器,没有任何杰克逊注释:

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对象。您负责创建实例。杰克逊只需要访问字段。在我们的情况下,这是一个公共领域。

如果将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