我有一个带有多个实现类的通用接口(interface),我需要通过 Json 对其进行序列化和反序列化。我正在尝试开始使用 Jackson,使用完整的数据绑定(bind),但运气不佳。
示例代码说明了问题:
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.type.JavaType;
public class Test {
interface Result<T> {}
static class Success<T> implements Result<T> {
T value;
T getValue() {return value;}
Success(T value) {this.value = value;}
}
public static void main(String[] args) {
Result<String> result = new Success<String>("test");
JavaType type = TypeFactory.defaultInstance().constructParametricType(Result.class, String.class);
ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
ObjectWriter writer = mapper.writerWithType(type);
ObjectReader reader = mapper.reader(type);
try {
String json = writer.writeValueAsString(result);
Result<String> result2 = reader.readValue(json);
Success<String> success = (Success<String>)result2;
} catch (Throwable ex) {
System.out.print(ex);
}
}
}
调用 writeValueAsString
导致以下异常:
org.codehaus.jackson.map.JsonMappingException:未找到类 Test$Success 的序列化器,也未发现创建 BeanSerializer 的属性(为避免异常,禁用 SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))
为什么 Jackson 希望我注册一个序列化器——我虽然完全数据绑定(bind)的目的是我不需要这样做?
上述做法是否正确?
最佳答案
首先,您需要使用工厂方法 TypeFactory.constructSpecializedType
注册专用类型以将其用于 Jackson。然后,专用类型应该是一个 bean(它应该有一个默认构造函数、getter 和 setter)来反序列化它。
看看这些测试说明。
@Test
public void canSerializeParametricInterface() throws IOException {
final ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
final JavaType baseInterface = TypeFactory.defaultInstance().constructParametricType(Result.class, String.class);
final JavaType subType = TypeFactory.defaultInstance().constructSpecializedType(baseInterface, Success.class);
final ObjectWriter writer = mapper.writerWithType(subType);
final String json = writer.writeValueAsString(Success.create("test"));
Assert.assertEquals("{\"value\":\"test\"}", json);
}
@Test
public void canDeserializeParametricInterface() throws IOException {
final ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
final JavaType baseInterface = TypeFactory.defaultInstance().constructParametricType(Result.class, String.class);
final JavaType subType = TypeFactory.defaultInstance().constructSpecializedType(baseInterface, Success.class);
final ObjectReader reader = mapper.reader(subType);
final Success<String> success = reader.readValue("{\"value\":\"test\"}");
Assert.assertEquals("test", success.getValue());
}
public static interface Result<T> {
}
public static class Success<T> implements Result<T> {
private T value;
public static <T> Success<T> create(T value) {
final Success<T> success = new Success<T>();
success.value = value;
return success;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
关于java - 使用 Jackson 序列化通用接口(interface)子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14761800/