Hum*_*jät 14 java json jackson
我目前正在将一些代码从Jackson 1.x迁移到Jackson 2.5 json mapper,这是一个长期存在的问题,在1.x中没有.
这是设置(见下面的代码):
问题: 如果我序列化Dog的一个实例,它按预期工作(杰克逊也将类型信息添加到json字符串).但是当我序列化Human类的一个实例时,会抛出一个异常:
com.fasterxml.jackson.databind.JsonMappingException:未为类型com.pet.Dog实现的类型id处理(通过引用链:com.Human ["pet"])
CustomPetSerializer类的serialize(...)方法未被调用(使用断点测试).
代码:
IPet实现:
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type")
@JsonSubTypes({
@JsonSubTypes.Type(value=Dog.class, name="dog")
//,@JsonSubTypes.Type(value=Cat.class, name="cat")
//more subtypes here...
})
public interface IPet
{
public Long getId();
public String getPetMakes();
}
Run Code Online (Sandbox Code Playgroud)
狗实施:
public class Dog implements IPet
{
@Override
public String getPetMakes()
{
return "Wuff!";
}
@Override
public Long getId()
{
return 777L;
}
}
Run Code Online (Sandbox Code Playgroud)
拥有狗的人:
public class Human
{
private IPet pet = new Dog();
@JsonSerialize(using=CustomPetSerializer.class)
public IPet getPet()
{
return pet;
}
}
Run Code Online (Sandbox Code Playgroud)
CustomPetSerializer实现:
public class CustomPetSerializer extends JsonSerializer<IPet>
{
@Override
public void serialize(IPet value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException
{
if(value != null && value.getId() != null)
{
Map<String,Object> style = new HashMap<String,Object>();
style.put("age", "7");
gen.writeObject(style);
}
}
}
Run Code Online (Sandbox Code Playgroud)
JUnit测试方法:
@Test
public void testPet() throws JsonProcessingException
{
ObjectMapper mapper = new ObjectMapper();
Human human = new Human();
//works as expcected
String json = mapper.writeValueAsString(human.getPet());
Assert.assertNotNull(json);
Assert.assertTrue(json.equals("{\"type\":\"dog\",\"id\":777,\"petMakes\":\"Wuff!\"}"));
//throws exception: Type id handling not implemented for type com.pet.Dog (through reference chain: com.Human["pet"])
json = mapper.writeValueAsString(human); //exception is thrown here
Assert.assertNotNull(json);
Assert.assertTrue(json.contains("\"age\":\"7\""));
}
Run Code Online (Sandbox Code Playgroud)
edi*_*edi 20
你需要serializeWithType
在你内部进行额外覆盖,CustomPetSerializer
因为它IPet
是多态的.这也是serialize
没有被召唤的原因.检查这个相关的SO问题,详细解释何时serializeWithType
被调用.例如,您的serializeWithType
实现可能如下所示:
@Override
public void serializeWithType(IPet value, JsonGenerator gen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
typeSer.writeTypePrefixForObject(value, gen);
serialize(value, gen, provider); // call your customized serialize method
typeSer.writeTypeSuffixForObject(value, gen);
}
Run Code Online (Sandbox Code Playgroud)
这将打印{"pet":{"type":"dog":{"age":"7"}}}
为您的Human
实例.
dan*_*ton 11
由于杰克逊2.9 writeTypePrefixForObject()
和writeTypeSuffixForObject()
已过时(我不清楚为什么).现在似乎在新的方法下:
@Override
public void serializeWithType(IPet value, JsonGenerator gen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
WritableTypeId typeId = typeSerializer.typeId(value, START_OBJECT);
typeSer.writeTypePrefix(gen, typeId);
serialize(value, gen, provider); // call your customized serialize method
typeSer.writeTypeSuffix(gen, typeId);
}
Run Code Online (Sandbox Code Playgroud)
所以现在是一条额外的线,所以不确定为什么它向前迈进了一步,也许重用typeId
对象更有效率.
资料来源: Jackson 目前掌握的ObjectNode课程.不是最好的来源,但没有看到任何升级文档解释该怎么做.
归档时间: |
|
查看次数: |
11238 次 |
最近记录: |