我正在使用Jackson与Spring一起进行JSON(de)序列化.但是,在某些情况下,我遇到了两次字段的问题.
我有一个抽象类:
@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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
一个具体的类扩展了抽象:
public class EpubBookmarkJsonModel extends AbstractBookmarkJsonModel {
private static final long serialVersionUID = 1L;
// Removed other fields for brevity
public EpubBookmarkJsonModel() {
this.mimeType = "application/epub+zip";
}
}
Run Code Online (Sandbox Code Playgroud)
问题是当我序列化这个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"
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试使用先前 答案的建议来使用@JsonAutoDetect注释来指定只应使用类上的字段以及设置相同的字段ObjectMapper,但这不能解决问题.
注解:
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
setterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
Run Code Online (Sandbox Code Playgroud)
ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE);
Run Code Online (Sandbox Code Playgroud)
此行为是由类上的注释引起的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")
})
Run Code Online (Sandbox Code Playgroud)
@JsonTypeInfo告诉Jackson将逻辑类型name(JsonTypeInfo.Id.NAME)序列化为JsonTypeInfo.As.PROPERTY带有name mimeType(property = "mimeType")的property ().随着@JsonSubTypes.Type分配的逻辑名称application/epub+zip 来EpubBookmarkJsonModel.
在序列化方面,Jackson将逻辑名称序列化为属性,mimeType = "application/epub+zip"然后将mimeType其中的对象属性序列化,这些属性
恰好与逻辑名称application/epub+zip(在构造函数中分配)具有相同的值.
我认为mimeType应该objectType在@JsonTypeInfo注释中更改或甚至更好地删除该mimeType字段,因为杰克逊将通过类型信息序列化来处理.
重复输出我遇到了同样的问题.我找到了一个不涉及其他财产的解决方案,并允许我不删除原始财产.首先,我将JsonTypeInfo的visible标志设置为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;
}
}
Run Code Online (Sandbox Code Playgroud)
需要注意的是,这是使用fastxml jackson jackson-databind 2.1.1
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.1.1</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)