Java 使用Jackson和json视图排除json中的字段
我正在根据需要创建一个动态json,这是一个很棒的库,我现在正在使用这个库一段时间。 最近,我的一个用例遇到了一个问题,让我把代码放在第一位 用户类 屏幕InfoPojo类 运行代码 预期结果 问题 在我的用例中,我有一个类Screen InfoPoJo,它与parentScreen引用同一个类, 我正在尝试获取父对象的特定字段(“parentScreen.id”)instate我正在获取在子对象/目标对象(“id”、“name”、“createdBy.name”、“lastUpdatedBy.mobileNo”、“parentScreen.id”)上定义的所有字段,并且父对象响应再次是递归的!我注意到只有在类有自己的引用的情况下才会发生这种情况,我将User类引用放置为两个不同的字段createdBy和lastedby,并尝试获取“name”和“mobileNo”,分别工作正常 任何解决这个问题的建议都会非常有用Java 使用Jackson和json视图排除json中的字段,java,json,jackson,json-view,Java,Json,Jackson,Json View,我正在根据需要创建一个动态json,这是一个很棒的库,我现在正在使用这个库一段时间。 最近,我的一个用例遇到了一个问题,让我把代码放在第一位 用户类 屏幕InfoPojo类 运行代码 预期结果 问题 在我的用例中,我有一个类Screen InfoPoJo,它与parentScreen引用同一个类, 我正在尝试获取父对象的特定字段(“parentScreen.id”)instate我正在获取在子对象/目标对象(“id”、“name”、“createdBy.name”、“lastUpdatedBy.
感谢序列化对象最灵活的方法是编写自定义序列化程序 如果我正确理解了您的需求,以下序列化程序可能会工作:
public class CustomScreenInfoSerializer extends JsonSerializer<ScreenInfoPojo> {
@Override
public void serialize(ScreenInfoPojo value, JsonGenerator gen, SerializerProvider serializers)
throws IOException, JsonProcessingException {
gen.writeStartObject();
gen.writeNumberField("id", value.getId());
gen.writeStringField("name", value.getName());
gen.writeFieldName("createdBy");
gen.writeStartObject();
gen.writeStringField("name", value.getCreatedBy().getName());
gen.writeEndObject();
gen.writeFieldName("lastUpdatedBy");
gen.writeStartObject();
gen.writeStringField("mobileNo", value.getLastUpdatedBy().getMobileNo());
gen.writeEndObject();
if (value.getParentScreen() == null) {
gen.writeNullField("parentScreen");
}
else {
gen.writeFieldName("parentScreen");
gen.writeStartObject();
gen.writeNumberField("id", value.getParentScreen().getId());
gen.writeEndObject();
}
gen.writeEndObject();
}
}
产生
[
{
"id": 1,
"name": "Screen1",
"createdBy": {
"name": "ABC"
},
"lastUpdatedBy": {
"mobileNo": "123456789"
},
"parentScreen": null
},
{
"id": 2,
"name": "Screen2",
"createdBy": {
"name": "ABC"
},
"lastUpdatedBy": {
"mobileNo": "123456789"
},
"parentScreen": {
"id": 1
}
},
{
"id": 3,
"name": "Screen3",
"createdBy": {
"name": "ABC"
},
"lastUpdatedBy": {
"mobileNo": "123456789"
},
"parentScreen": {
"id": 2
}
},
{
"id": 4,
"name": "Screen4",
"createdBy": {
"name": "ABC"
},
"lastUpdatedBy": {
"mobileNo": "123456789"
},
"parentScreen": {
"id": 3
}
}
]
对。Include子句不适用于对同一类的引用 你能做到吗 根据github指令从源代码编译 允许更新函数JsonViewSerializer.JsonWriter.field 查找: 和注释else子句
if(match == null) {
match = this.currentMatch;
} else {
//prefix = "";
}
你会得到预期的结果。但是我不知道它将如何影响其他过滤器
若要获得更多控制权,可以向JsonView类添加属性
例如:
在JsonView中添加:
private boolean ignorePathIfClassRegistered = true;
public boolean isIgnorePathIfClassRegistered() {
return ignorePathIfClassRegistered;
}
public JsonView1<T> setIgnorePathIfClassRegistered(boolean ignorePathIfClassRegistered) {
this.ignorePathIfClassRegistered = ignorePathIfClassRegistered;
return this;
}
您可以在示例中使用它,如:
JsonView<List<ScreenInfoPojo>> viwevedObject = JsonView
.with(screens)
.onClass(ScreenInfoPojo.class,
Match.match()
.exclude("*")
.include("id","name")
.include("createdBy.name")
.include("lastUpdatedBy.mobileNo")
.include("parentScreen.id"))
.setIgnorePathIfClassRegistered(false);
ObjectMapper mapper = new ObjectMapper().registerModule(new JsonViewModule());
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
String json = mapper.writeValueAsString(viwevedObject);
JsonView-viwevedObject=JsonView
.带(屏幕)
.onClass(屏幕InfoPoJo.class,
Match.Match()
.不包括(“*”)
.包括(“身份证”、“姓名”)
.include(“createdBy.name”)
.include(“lastdupdateby.mobileNo”)
.include(“parentScreen.id”))
.setIgnorePathIfClassRegistered(假);
ObjectMapper mapper=新的ObjectMapper().registerModule(新的JsonViewModule());
configure(SerializationFeature.INDENT_输出,true);
字符串json=mapper.writeValueAsString(viwevedObject);
您只需在json响应中不需要的字段上使用jackson annotation@jsonignore
我不知道您是否可以在代码上使用任何注释。如果是这样的话,这是没有用的 你能简单地用
id
属性创建另一个POJO并将其分配给parentScreen
属性吗?不,我做不到为什么?从我的角度来看,它是一个独特的实体,有点像ScreenRefPojo
。我的应用程序有多个类(pojo),并且在运行时应用了匹配,这意味着根据客户机的要求,它将使用属性(使用ajax),因此创建一个不同的类将增加额外的开销。我看到您在json视图中打开了一个问题(我同意您的代码应该按预期运行),但您是否至少尝试过排除parentScreen.*
和/或parentScreen.name,parentScreen.createdBy…
?感谢您的回答,如果我必须在一个或两个类中处理此问题,我可以应用此解决方案,但遗憾的是,我有许多类(实体)面对这个问题和这个json属性,我对同一api的不同请求进行了更改,因此我不能对实体类使用自定义序列化程序,我必须使其成为动态的。是的,使用这种方法,他只需添加一个带有父id的额外字段,以使代码重构的引用仍然最少。看起来非常简单。感谢您宝贵的回答,事实上我已经做了,我不想修改库源代码,但似乎没有其他方法可以接受这项工作。感谢您花费宝贵的时间。
public class CustomScreenInfoSerializer extends JsonSerializer<ScreenInfoPojo> {
@Override
public void serialize(ScreenInfoPojo value, JsonGenerator gen, SerializerProvider serializers)
throws IOException, JsonProcessingException {
gen.writeStartObject();
gen.writeNumberField("id", value.getId());
gen.writeStringField("name", value.getName());
gen.writeFieldName("createdBy");
gen.writeStartObject();
gen.writeStringField("name", value.getCreatedBy().getName());
gen.writeEndObject();
gen.writeFieldName("lastUpdatedBy");
gen.writeStartObject();
gen.writeStringField("mobileNo", value.getLastUpdatedBy().getMobileNo());
gen.writeEndObject();
if (value.getParentScreen() == null) {
gen.writeNullField("parentScreen");
}
else {
gen.writeFieldName("parentScreen");
gen.writeStartObject();
gen.writeNumberField("id", value.getParentScreen().getId());
gen.writeEndObject();
}
gen.writeEndObject();
}
}
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(ScreenInfoPojo.class, new CustomScreenInfoSerializer());
mapper.registerModule(module);
String json = mapper.writeValueAsString(screens);
System.out.println(json);
[
{
"id": 1,
"name": "Screen1",
"createdBy": {
"name": "ABC"
},
"lastUpdatedBy": {
"mobileNo": "123456789"
},
"parentScreen": null
},
{
"id": 2,
"name": "Screen2",
"createdBy": {
"name": "ABC"
},
"lastUpdatedBy": {
"mobileNo": "123456789"
},
"parentScreen": {
"id": 1
}
},
{
"id": 3,
"name": "Screen3",
"createdBy": {
"name": "ABC"
},
"lastUpdatedBy": {
"mobileNo": "123456789"
},
"parentScreen": {
"id": 2
}
},
{
"id": 4,
"name": "Screen4",
"createdBy": {
"name": "ABC"
},
"lastUpdatedBy": {
"mobileNo": "123456789"
},
"parentScreen": {
"id": 3
}
}
]
if(match == null) {
match = this.currentMatch;
} else {
prefix = "";
}
if(match == null) {
match = this.currentMatch;
} else {
//prefix = "";
}
private boolean ignorePathIfClassRegistered = true;
public boolean isIgnorePathIfClassRegistered() {
return ignorePathIfClassRegistered;
}
public JsonView1<T> setIgnorePathIfClassRegistered(boolean ignorePathIfClassRegistered) {
this.ignorePathIfClassRegistered = ignorePathIfClassRegistered;
return this;
}
if(match == null) {
match = this.currentMatch;
} else {
if (result.isIgnorePathIfClassRegistered())
prefix = "";
}
JsonView<List<ScreenInfoPojo>> viwevedObject = JsonView
.with(screens)
.onClass(ScreenInfoPojo.class,
Match.match()
.exclude("*")
.include("id","name")
.include("createdBy.name")
.include("lastUpdatedBy.mobileNo")
.include("parentScreen.id"))
.setIgnorePathIfClassRegistered(false);
ObjectMapper mapper = new ObjectMapper().registerModule(new JsonViewModule());
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
String json = mapper.writeValueAsString(viwevedObject);