我有以下课程:
public class Container{
String description;
Element1 element1;
Element2 element2;
}
public class Element1{
String f11;
String f12;
}
public class Element2{
String f21;
String f22;
}
我将Container序列化为json格式。 对于json序列化我使用Jackson。
现在我希望如果f11,f12和f21,f22,f22,则不要将element1和element2包含到json中。
正如我所说,我应该编写cistom序列化程序,但我不明白哪个实体。 Element或Container? 如何 ?
附:
我的问题不是使用Jackson忽略JSON对象上的新字段
本主题解释了如何忽略Container内的空值。 我的问题是如何忽略Container里面只有空值的对象
这可能会有所帮助(stackoverflow.com/questions/25603581/…)。
可能重复的Jackson序列化:忽略空值(或null)
@Raman Shrivastava请阅读更新。 我的问题不同
受StaxMan答案启发的另一个想法是实现一个"空元素模块",它将Container的所有覆盖封装到Container中的不同元素中。例如,模块看起来像这样:
public class EmptyElementModule extends SimpleModule {
private static final String NAME ="EmptyElementModule";
public EmptyElementModule() {
super(NAME);
setSerializerModifier(new EmptyElementSerializerModifier());
}
public static class EmptyElementSerializerModifier extends BeanSerializerModifier {
@Override
public JsonSerializer< ? > modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer< ? > serializer) {
Class< ? > beanClass = beanDesc.getBeanClass();
if (beanClass == Element1.class) {
return new EmptyElement1Serializer((JsonSerializer) serializer);
} else if (beanClass == Element2.class) {
// return element 2 serializer
}
return serializer;
}
}
public static class EmptyElement1Serializer extends JsonSerializer {
private final JsonSerializer defaultSerializer;
public EmptyElement1Serializer(JsonSerializer defaultSerializer) {
this.defaultSerializer = checkNotNull(defaultSerializer);
}
@Override
public void serialize(Element1 value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
defaultSerializer.serialize(value, gen, serializers);
}
@Override
public boolean isEmpty(SerializerProvider provider, Element1 value) {
return value.f11 == null && value.f12 == null;
}
}
}
非常好 - 谢谢你写出来。
它也可以在不扩展SimpleModule的情况下工作
虽然您可能确实需要自定义序列化程序,但是需要覆盖的方法是isEmpty(...);然后指定属性的包含策略,如下所示:
@JsonInclude(JsonInclude.Include.NON_EMPTY)
这将让"拥有"对象确定要避免序列化:否则将调用自定义序列化程序并且它必须写一个值 - 当然你可以编写null,但自定义序列化程序本身不能拒绝写任何东西,因为属性名称已由调用者编写。
请提供更多详情
不知道isEmpty(...)方法。与重新定义序列化(...)相比,这是一个更清洁的解决方案。
当我从JsonSerializer扩展时,我应该重写serialize方法,因为它是抽象的
请告知我应该扩展哪个类只覆盖isEmpty方法
我认为这种方法的缺点是你需要为每种元素类型定义一个自定义序列化器。 OP在评论中提到他们在这个容器中有10多个元素类型。我认为无论你是在为每个元素编写特定的配置,除非它们碰巧都扩展了一个共同的基础。
我在这里添加了一个答案,我认为这与StaxMan推荐的一致(在此示例中为您的容器添加@JsonInclude):stackoverflow.com/a/31034525/1756430
@gstackoverflow是的,您还必须实现实际的序列化,而不仅仅是isEmpty()。
要忽略容器中只有空/空成员(容器的成员,成员)的元素,您可以为Container创建自定义序列化程序。自定义序列化程序非常棒,因为它们可以最终控制对象的编写方式,但这也会导致代码难以维护。我之所以这么说是因为有了杰克逊,你可以用自定义的de / serializer完成任何事情,但对于大多数问题,通常都有一种更简洁的方式(例如通过注释)。为此,OP请求编写自定义序列化程序的指导,我不知道一种更简单的方法来完成所需的行为。
创建Module和自定义序列化程序
Jackson Module用于封装单个对象的反序列化器和序列化器。对于此示例,仅需要序列化程序,但如果要为Container添加解串器,则可以将其与ContainerModule内的序列化程序一起添加。以下代码定义Container的序列化程序,如果其成员中至少有一个非空,则只写element1和element2:
public class ContainerModule extends SimpleModule {
private static final String NAME ="ContainerModule";
public ContainerModule() {
super(NAME);
addSerializer(Container.class, new ContainerSerializer());
}
public static class ContainerSerializer extends JsonSerializer {
@Override
public void serialize(Container container, JsonGenerator jg, SerializerProvider serializers) throws IOException {
if (container != null) {
// start object and write description
jg.writeStartObject();
jg.writeStringField("description", container.description);
// only write Element1 if one of its members exist
Element1 element1 = container.element1;
if (element1 != null) {
if (!Strings.isNullOrEmpty(element1.f11)
&& !Strings.isNullOrEmpty(element1.f12)) {
jg.writeFieldName("element1");
jg.writeObject(element1);
}
}
// only write Element2 if one of its members exist
Element2 element2 = container.element2;
if (element2 != null) {
if (!Strings.isNullOrEmpty(element2.f21)
&& !Strings.isNullOrEmpty(element2.f22)) {
jg.writeFieldName("element2");
jg.writeObject(element2);
}
}
// close the Container object
jg.writeEndObject();
}
}
}
}
注册自定义序列化程序
可以使用@JsonDeserialize在ObjectMapper或类上全局注册序列化程序。
ObjectMapper注册
ObjectMapper om = new ObjectMapper()
.registerModule(new ContainerModule());
班级注册
@JsonSerialize(using = ContainerModule.ContainerSerializer.class)
public class Container {
String description;
Element1 element1;
Element2 element2;
}
这应该产生以下结果:
// Full container
{
"description" :"an awesome description",
"element1" : {
"f11" :"f11 value",
"f12" :"f12 value"
},
"element2" : {
"f21" :"f21 value",
"f22" :"f22 value"
}
}
// Null Element1 properties
{
"description" :"an awesome description",
"element2" : {
"f21" :"f21 value",
"f22" :"f22 value"
}
}
// Null Element2 properties
{
"description" :"an awesome description",
"element1" : {
"f11" :"f11 value",
"f12" :"f12 value"
}
}
// Null Element1 and 2 properties
{
"description" :"an awesome description"
}
我有100多个字符串字段到容器和10+元素的问题,每个元素有4..10字符串字段。
我想只为元素编写代码
@gstackoverflow见StaxMan的建议。如果可能,定义isEmpty应优先于序列化(...)。
在这种情况下我应该延长另一堂课吗?
如果你使用注释,这应该工作正常:
public class Container{
String description;
@JsonIgnore
Element1 element1;
@JsonIgnore
Element2 element2;
}
所以杰克逊忽略了@JsonIgnore注释的这两个
仅当f11和f12为空时我才需要忽略element1
stackoverflow.com/questions/11757487/…看一看
如果element1为null,则此主题相关