Дублируйте поле JSON с Джексоном

Я использую Jackson для сериализации JSON (de) в сочетании с Spring. Однако в некоторых случаях у меня проблема с полем, который в два раза больше.

У меня есть абстрактный класс:

@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);
        }
    }
}

И конкретный класс расширяет реферат:

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

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

Проблема в том, что когда я сериализую этот 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"
}

Я попытался использовать рекомендацию previous , чтобы использовать аннотацию @JsonAutoDetect, чтобы указать, что следует использовать только поля в классе, а также установить их на ObjectMapper, однако это не устраняет проблему.

Аннотация:

@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);

Ответ 1

Я решил это, используя JsonTypeInfo.As.EXISTING_PROPERTY в аннотации @JsonTypeInfo.

Проект является открытым исходным кодом, посмотрите здесь: ANS.java

Ответ 2

У меня была такая же проблема с дублирующимся выходом. Я нашел решение, которое не связано с другим свойством, и позволило мне не удалять исходное свойство. Во-первых, я установил для видимого флага значение true для JsonTypeInfo. Затем я добавил аннотацию JsonIgnore к объявлению свойства и получателю (но не к настройщику). До сих пор это правильно выводило JSON только с одним ключом для свойства type.

@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;
    }

}

Отметим, что это с помощью quickxml jackson jackson-databind 2.1.1

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

Ответ 3

Это поведение вызвано аннотациями, помещенными в класс 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")
})

@JsonTypeInfo указывает Джексону сериализовать имя логического типа (JsonTypeInfo.Id.NAME) как свойство (JsonTypeInfo.As.PROPERTY) с именем mimeType (property = "mimeType"). С помощью @JsonSubTypes.Type вы назначаете логическое имя application/epub+zip на EpubBookmarkJsonModel.

Когда дело доходит до сериализации, Джексон сериализует логическое имя как свойство mimeType = "application/epub+zip", тогда свойства объекта среди них mimeType, который имеет то же значение, что и логическое имя application/epub+zip (назначено в конструкторе).

Я думаю, что mimeType следует изменить на objectType в аннотации @JsonTypeInfo или даже лучше удалить поле mimeType, так как Джексон позаботится об этом через сериализацию информации типа.