使用Jackson(JSON / Object映射器),让我们说我有以下接口和类:
@JsonTypeInfo(defaultImpl = Duck.class, use = JsonTypeInfo.Id.CLASS)
public interface Animal {
}
public class Duck implements Animal {
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
public class Park {
private Animal animal;
public Animal getAnimal() { return animal; }
public void setAnimal(Animal animal) { this.animal = animal; }
}
我尝试阅读(反序列化)这段JSON:
{
"animal": {
"name": "Quacky"
}
}
使用:
Park park = objectMapper.readValue(json, Park.class);
有效!即使没有任何类型信息(@class或@type),它也可以构造Duck
,因为我为defaultImpl
接口指定了Animal
。
现在我希望在反过来做同样的行为。
String json = objectMapper.writeValueAsString(park);
但我得到了这个JSON:
{
"animal": {
"@class": "com.example.Duck"
"name": "Quacky"
}
}
序列化时似乎不尊重defaultImpl
!我想要" @ class"属性从输出文件中消失。有没有人知道如何告诉杰克逊不要添加" @ class"我Duck
的属性?
答案 0 :(得分:5)
您需要告诉Jackson不要包含实现类的类信息。根据文档,
更细粒度(和更强大)的方式来定义要添加的类型信息,以及在哪里使用@JsonTypeInfo注释(可能还有几个相关的注释)。例如,我们可以按如下方式注释Animal:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,include = JsonTypeInfo.As.PROPERTY,property =“@ class”) class Animal {} (顺便提一下,它等同于输入的默认设置)。
这是什么意思?
- 带注释类型的所有实例及其子类型都使用这些设置(除非被其他注释覆盖)
- 要使用的“类型标识符”是完全限定的Java类名(如“org.codehaus.jackson.sample.Animal”)
- 类型标识符将作为(meta-)属性包含在内,以及常规数据属性;使用名称“@class”(默认使用的名称取决于类型if:对于类,它将是“@class”)
- 使用默认类型解析器(未添加@JsonTypeResolver);以及默认类型ID解析器(没有@JsonTypeIdResolver)
通过向Duck添加注释来完成此操作。
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public class Duck implements Animal {
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
如果失败,请添加
SimpleModule simpleModule = new SimpleModule("SimpleModule", new Version(1,0,0,null));
simpleModule.addSerializer(new JsonSerializer< Duck > {
@Override
public void serialize(Duck duck, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("name", duck.getName());
jgen.writeEndObject();
}
});
mapper.registerModule(simpleModule);