我想使用com.fasterxml.jackson.databind.ObjectMapper序列化和反序列化不可变对象。
不可变类如下所示(只有3个内部属性,获取器和构造函数):
public final class ImportResultItemImpl implements ImportResultItem { private final ImportResultItemType resultType; private final String message; private final String name; public ImportResultItemImpl(String name, ImportResultItemType resultType, String message) { super(); this.resultType = resultType; this.message = message; this.name = name; } public ImportResultItemImpl(String name, ImportResultItemType resultType) { super(); this.resultType = resultType; this.name = name; this.message = null; } @Override public ImportResultItemType getResultType() { return this.resultType; } @Override public String getMessage() { return this.message; } @Override public String getName() { return this.name; } }
但是,当我运行此单元测试时:
@Test public void testObjectMapper() throws Exception { ImportResultItemImpl originalItem = new ImportResultItemImpl("Name1", ImportResultItemType.SUCCESS); String serialized = new ObjectMapper().writeValueAsString((ImportResultItemImpl) originalItem); System.out.println("serialized: " + serialized); //this line will throw exception ImportResultItemImpl deserialized = new ObjectMapper().readValue(serialized, ImportResultItemImpl.class); }
我得到这个例外:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class eu.ibacz.pdkd.core.service.importcommon.ImportResultItemImpl]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?) at [Source: {"resultType":"SUCCESS","message":null,"name":"Name1"}; line: 1, column: 2] at ... nothing interesting here
这个异常要求我创建一个默认的构造函数,但这是一个不可变的对象,所以我不想拥有它。它将如何设置内部属性?这会完全混淆API的用户。
所以我的问题是: 我可以在没有默认构造函数的情况下以某种方式反序列化不可变对象吗?
要让Jackson知道如何创建对象以进行反序列化,请为您的构造函数使用@JsonCreator和@JsonProperty注释,如下所示:
@JsonCreator
@JsonProperty
@JsonCreator public ImportResultItemImpl(@JsonProperty("name") String name, @JsonProperty("resultType") ImportResultItemType resultType, @JsonProperty("message") String message) { super(); this.resultType = resultType; this.message = message; this.name = name; }