Java 使用 Jackson 复制 JSON 字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18237222/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:38:09  来源:igfitidea点击:

Duplicate JSON Field with Hymanson

javajsonHymanson

提问by

I am using Hymanson for JSON (de)serialization in conjunction with Spring. However I am having an issue with a field being twice in some cases.

我正在使用 Hymanson 与 Spring 结合进行 JSON(反)序列化。但是,在某些情况下,我遇到了一个字段是两次的问题。

I have an abstract class:

我有一个抽象类:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "mimeType")
@JsonSubTypes({
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"),
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip")
})
public abstract class AbstractBookmarkJsonModel extends AbstractJsonModel {
    protected String mimeType;
    // Removed other fields for brevity

    public String getMimeType() {
        return mimeType;
    }

    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

    @Override
    public String toString() {
        ObjectMapper mapper = new ObjectMapper();

        try {
            return mapper.writeValueAsString(this);
        } catch (IOException e) {
            throw new IllegalStateException("Cannot convert object of type " + this.getClass().toString() + " to JSON", e);
        }
    }
}

And a concrete class extend the abstract:

一个具体的类扩展了抽象:

public class EpubBookmarkJsonModel extends AbstractBookmarkJsonModel {
    private static final long serialVersionUID = 1L;
    // Removed other fields for brevity

    public EpubBookmarkJsonModel() {
        this.mimeType = "application/epub+zip";
    }
}

The problem is that when I serialize this JSON, I get a duplicate mimeTypefield:

问题是当我序列化这个 JSON 时,我得到一个重复的mimeType字段:

{
  "mimeType": "application/epub+zip",
  "mimeType": "application/epub+zip",
  "userId": 24,
  "acid": "ACID-000000000029087",
  "added": "2013-08-14T12:02:17Z",
  "epubBookmarkId": 34,
  "cfi": "epubcfi(/6/4!/2/68)",
  "context": "CONTEXT"
}

I have tried using the recommendation of previousanswersto use the @JsonAutoDetectannotation to specify that only fields on a class should be used as well as setting the same on the ObjectMapper, however this does not fix the problem.

我曾尝试使用先前答案的建议来使用@JsonAutoDetect注释来指定只应使用类上的字段以及在 上设置相同的字段ObjectMapper,但这并不能解决问题。

Annotation:

注解:

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
        setterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE,
        isGetterVisibility = JsonAutoDetect.Visibility.NONE)

ObjectMapper:

对象映射器:

    ObjectMapper mapper = new ObjectMapper();
    mapper.getSerializationConfig().getDefaultVisibilityChecker()
            .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
            .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
            .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
            .withCreatorVisibility(JsonAutoDetect.Visibility.NONE);

回答by Katona

This behaviour is caused by the annotations placed on class AbstractBookmarkJsonModel:

此行为是由放置在 class 上的注释引起的AbstractBookmarkJsonModel

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "mimeType")
@JsonSubTypes({
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"),
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip")
})

@JsonTypeInfotells Hymanson to serialize the logical type name (JsonTypeInfo.Id.NAME) as a property (JsonTypeInfo.As.PROPERTY) with name mimeType(property = "mimeType"). With @JsonSubTypes.Typeyou assign the logical name application/epub+zipto EpubBookmarkJsonModel.

@JsonTypeInfo告诉Hyman逊序列化的逻辑类型名称(JsonTypeInfo.Id.NAME)作为属性(JsonTypeInfo.As.PROPERTY)与名称mimeTypeproperty = "mimeType")。随着@JsonSubTypes.Type分配的逻辑名称application/epub+zipEpubBookmarkJsonModel

When it comes to serialization, Hymanson serializes the logical name as a property mimeType = "application/epub+zip"then the properties of the object among them mimeTypewhich happens to have the same value as the logical name application/epub+zip(assigned in the constructor).

在序列化方面,Hymanson 将逻辑名称序列化为一个属性,mimeType = "application/epub+zip"然后将mimeType其中的对象的属性 序列化为与逻辑名称application/epub+zip(在构造函数中分配)相同的值。

I think mimeTypeshould be changed to objectTypein the @JsonTypeInfoannotation or even better to remove the mimeTypefield since Hymanson will take care of that through type info serialization.

我认为mimeType应该objectType@JsonTypeInfo注释中更改为,甚至更好地删除该mimeType字段,因为 Hymanson 将通过类型信息序列化来处理该问题。

回答by ZacharyP

I was having this exact same problem with the duplicate output. I found a solution that did not involve another property, and allowed me to not remove the original property. First, I set the visible flag to true for JsonTypeInfo. Then, I added a JsonIgnore annotation to the property declaration and the getter (but not the setter). This is so far outputting the JSON correctly with only one key for the type property.

我在重复输出时遇到了完全相同的问题。我找到了一个不涉及其他属性的解决方案,并且允许我不删除原始属性。首先,我将 JsonTypeInfo 的可见标志设置为 true。然后,我在属性声明和 getter(但不是 setter)中添加了 JsonIgnore 注释。到目前为止,只有一个用于 type 属性的键才能正确输出 JSON。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "mimeType")
@JsonSubTypes({
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"),
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip")
})
public abstract class AbstractBookmarkJsonModel extends AbstractJsonModel {
    @JsonIgnore
    @JsonProperty("mimeType")
    protected String mimeType;

    @JsonIgnore
    @JsonProperty("mimeType")
    public String getMimeType() {
        return mimeType;
    }

    @JsonProperty("mimeType")
    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

}

To note, this is with fasterxml Hymanson Hymanson-databind 2.1.1

请注意,这是使用 fastxml Hymanson Hymanson-databind 2.1.1

<dependency>
    <groupId>com.fasterxml.Hymanson.core</groupId>
    <artifactId>Hymanson-databind</artifactId>
    <version>2.1.1</version>
</dependency>

回答by Thomas Vaughan

I solved this by using the JsonTypeInfo.As.EXISTING_PROPERTYin the @JsonTypeInfo annotation.

我通过JsonTypeInfo.As.EXISTING_PROPERTY在 @JsonTypeInfo 注释中使用 解决了这个问题。

The project is open source, check it out here: ANS.java

该项目是开源的,在这里查看:ANS.java