【问题标题】:@class getting added even though it's the defaultImpl@class 被添加,即使它是 defaultImpl
【发布时间】:2014-02-14 08:48:30
【问题描述】:

使用 Jackson(JSON/对象映射器),假设我有以下接口和类:

@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,因为我为Animal 接口指定了defaultImpl

现在我希望反过来做同样的行为。

String json = objectMapper.writeValueAsString(park);

但是我得到了这个 JSON:

{
    "animal": {
        "@class": "com.example.Duck",
        "name": "Quacky"
    }
}

序列化时似乎不尊重defaultImpl!我希望从输出文件中删除“@class”属性。有谁知道我如何告诉杰克逊不要为我的Duck 添加“@class”属性?

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    您需要告诉 Jackson 不要包含实现类的类信息。根据文档,

    定义要添加什么类型信息以及在哪里添加的更精细(和强大)的方法是使用@JsonTypeInfo 注释(可能还有几个相关的注释)。例如,我们可以将 Animal 注释如下:

    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") 类动物{} (顺便说一下,这相当于打字的默认设置)。

    这是什么意思?

    • 注解类型及其子类型的所有实例都使用这些设置(除非被另一个注解覆盖)
    • 要使用的“类型标识符”是完全限定的 Java 类名(如“org.codehaus.jackson.sample.Animal”)
    • 类型标识符将作为(元)属性与常规数据属性一起包含在内;使用名称“@class”(使用的默认名称取决于类型,如果:对于类,它将是“@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);
    

    【讨论】:

    • 感谢您的精彩回答!不幸的是,您的解决方案对我不起作用。注释似乎被忽略了。也许它被超类(动物)上的@JsonTypeInfo 否决了?
    • 我查看了源代码,这应该可以工作。我将在我的答案中添加一个自定义序列化程序。
    • 谢谢!也许我使用的是旧版本的杰克逊之类的。
    • 您能否将自定义序列化程序添加到您的答案中?
    • 抱歉,我查看的是旧版本的页面。感谢您添加序列化程序示例!我稍后会尝试。
    【解决方案2】:

    制作 Duck 工具JsonSerializable.

    public class Duck implements Animal, JsonSerializable {
        private String name;
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
    
        @Override
        public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException {
            // Serialize Duck object
        }
    
        @Override
        public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer)
                throws IOException {
            serialize(gen, serializers);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多