我需要创建一个自定义序列化程序,有条件地跳过字段。与使用jackson序列化时有条件跳过对象中描述的情况不同,我的类包含一个POJO成员。PersonalInfo有一个成员地址。如果地址被隐藏,结果JSON仍然有“Address”标记,但没有值。我想不出怎么解决这个问题。
在ObjectMapper上创建自定义序列化程序(参见3. athttp://www.baeldung.com/jackson-custom-serialization)会导致完全相同的结果。
以下是参考问题中显示问题的改编代码:
public class JacksonHide {
@JsonIgnoreProperties("hidden")
public static interface IHideable {
boolean isHidden();
}
public static class Address implements IHideable {
public final String city;
public final String street;
public final boolean hidden;
public Address(String city, String street, boolean hidden) {
this.city = city;
this.street = street;
this.hidden = hidden;
}
@Override
public boolean isHidden() {
return hidden;
}
}
public static class PersonalInfo implements IHideable {
public final String name;
public final int age;
public final Address address;
public final boolean hidden;
public PersonalInfo(String name, int age, Address address, boolean hidden) {
this.name = name;
this.age = age;
this.address = address;
this.hidden = hidden;
}
@Override
public boolean isHidden() {
return hidden;
}
}
private static class MyBeanSerializerModifier extends BeanSerializerModifier {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
if (IHideable.class.isAssignableFrom(beanDesc.getBeanClass())) {
return new MyIHideableJsonSerializer((JsonSerializer<IHideable>) serializer);
}
return super.modifySerializer(config, beanDesc, serializer);
}
private static class MyIHideableJsonSerializer extends JsonSerializer<IHideable> {
private final JsonSerializer<IHideable> serializer;
public MyIHideableJsonSerializer(JsonSerializer<IHideable> serializer) {
this.serializer = serializer;
}
@Override
public void serialize(IHideable value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
if (!value.isHidden()) {
serializer.serialize(value, jgen, provider);
}
}
}
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.setSerializerModifier(new MyBeanSerializerModifier());
mapper.registerModule(module);
PersonalInfo p1 = new PersonalInfo("John", 30, new Address("A", "B", false), false);
PersonalInfo p2 = new PersonalInfo("Ivan", 20, new Address("C", "D", true), true);
PersonalInfo p3 = new PersonalInfo("Mary", 40, new Address("C", "D", true), false);
Address a1 = new Address("A", "B", false);
Address a2 = new Address("C", "D", true);
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(Arrays.asList(p1, p2, p3, a1, a2)));
}
}
更新:感谢反馈,我现在有一个基于@JSONFilter的版本,给我至少有效的JSON。不幸的是,节点仍然存在,但现在是空的({})。我怎样才能彻底摆脱他们?
public class JacksonFilterHide {
@JsonFilter("HiddenFilter")
@JsonIgnoreProperties("hidden")
public static interface IHideable {
boolean isHidden();
}
public static class Address implements IHideable {
public final String city;
public final String street;
public final boolean hidden;
public Address(String city, String street, boolean hidden) {
this.city = city;
this.street = street;
this.hidden = hidden;
}
@Override
public boolean isHidden() {
return hidden;
}
}
public static class PersonalInfo implements IHideable {
public final String name;
public final int age;
public final Address address;
public final boolean hidden;
public PersonalInfo(String name, int age, Address address, boolean hidden) {
this.name = name;
this.age = age;
this.address = address;
this.hidden = hidden;
}
@Override
public boolean isHidden() {
return hidden;
}
}
static final PropertyFilter hiddenFilter = new SimpleBeanPropertyFilter() {
@Override
public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception {
if (include(writer)) {
if (pojo instanceof IHideable && ((IHideable) pojo).isHidden()) {
return;
} else {
writer.serializeAsField(pojo, jgen, provider);
return;
}
} else if (!jgen.canOmitFields()) { // since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
};
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
// ObjectMapper mapper = UserInteractionModel.getMapper();
FilterProvider filters = new SimpleFilterProvider().addFilter("HiddenFilter", hiddenFilter);
mapper.setFilters(filters);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
PersonalInfo p1 = new PersonalInfo("John", 30, new Address("A", "B", false), false);
PersonalInfo p2 = new PersonalInfo("Ivan", 20, new Address("C", "D", true), true);
PersonalInfo p3 = new PersonalInfo("Mary", 40, new Address("C", "D", true), false);
Address a1 = new Address("A", "B", false);
Address a2 = new Address("C", "D", true);
System.out.println(mapper.writeValueAsString(Arrays.asList(p1, p2, p3, a1, a2)));
}
}
现在的输出是:
[{姓名:约翰,年龄:30,地址:{城市:A,街道:B" } }, { }, { "姓名:玛丽,年龄:40,地址": { } }, { "城市:A,“街道”:“B" }, { } ]
预期:
[{姓名:约翰,年龄:30,地址:{城市:A,街道:B" } }, { "姓名:玛丽,年龄:40, }, { "城市:A,街道:B}]
Update2通过遍历树并删除空节点进行临时修复。很丑,但现在管用。仍在寻找更好的答案。
private void removeEmptyNodes(JSONObject json) {
Iterator<String> iter = json.keys();
while (iter.hasNext()) {
String key = iter.next();
JSONObject node;
try {
node = json.getJSONObject(key);
} catch (JSONException e) {
continue;
}
if (node.length() == 0) {
iter.remove();
} else {
removeEmptyNodes(node);
}
}
}
受这个问题启发的解决方案:如何使用Jackson删除Java中的空json节点?
序列化程序已损坏:如果请求,它无法选择不写入值。在写入属性值的情况下,调用方已经写出了属性名,所以不写入该值确实会中断输出。这要么导致抛出异常(理想情况下),要么导致输出中断(不理想情况下);不管怎样,JsonSerializer
都不允许尝试决定是否正在写入值。
要排除正在序列化的属性,有效选项包括:
@JsonIgnore
和@JsonIgnoreProperties
下面的代码再现了这个问题: 上面的代码不做其他注册“自定义”序列化程序的事情(只是委托回原始序列化程序),但它生成的JSON没有null属性: {“第一个”:“鲍勃”,“最后一个”:“巴克”} 我读过许多看似相关的SO文章,但没有一篇能让我找到解决方案。我尝试在序列化时显式地将映射器设置为,但没有成功。 我唯一的线索是JavaDoc for JsonSerializer中的一条注释: 注意:永远不
情况如下:我已经设法让Jackson反序列化以下通用 作为HTTP客户端,并使用exchange
我想将包含另一个空值POJO的POJO序列化为JSON。 例如,给定: 连载之后,它看起来会是这样的 如果类的所有字段也为空,是否可以排除空对象?理想情况下,全局适用于每个对象,而无需编写自定义代码。
如果类的所有字段也为空,是否可以排除空对象?理想情况下,全局地用于每个对象,而无需编写自定义代码。
我试图创建会影响序列化值的自定义jackson注释。 意思是: 现在序列化对象X(10)将导致: 我怎样才能做到这一点?
我尝试在包含带有注释的对象列表的列表上应用自定义序列化程序。如果未授予用户权限(角色与用户不同),我想删除这些属性。当属性不是列表时,它工作得很好(https://www.baeldung.com/jackson-serialize-field-custom-criteria) **更新** 我的第一个方法是为mapper注册一个新模块 和我的自定义序列化程序 但我无法访问列表中包含的对象。我想定