如何不将组合对象包含到json中?

时间:2015-06-23 17:44:06

标签: java json serialization jackson

我有以下课程:

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。

现在,如果element1element2f11f12非常谨慎,我希望不要将f21f22包含在json中是空白的。

正如我所说,我应该写cistom序列化器,但我不了解哪个实体。 ElementContainer?怎么样?

P.S。

我的问题与Ignoring new fields on JSON objects using Jackson

不重复

本主题介绍如何忽略Container内的空值。我的问题是如何忽略Container内的对象,其中

中只有空值

4 个答案:

答案 0 :(得分:3)

StaxMan's answer启发的另一个想法是实现一个"空元素模块"它将isEmpty中的所有覆盖封装为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<Object>) serializer);
            } else if (beanClass == Element2.class) {
                // return element 2 serializer
            }
            return serializer;
        }
    }

    public static class EmptyElement1Serializer extends JsonSerializer<Element1> {
        private final JsonSerializer<Object> defaultSerializer;

        public EmptyElement1Serializer(JsonSerializer<Object> 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;
        }
    }
}

答案 1 :(得分:2)

虽然您可能确实需要自定义序列化程序,但您需要覆盖的方法是isEmpty(...);然后指定属性的包含策略,如下所示:

@JsonInclude(JsonInclude.Include.NON_EMPTY)

这将让“拥有”对象确定要避免序列化:否则将调用自定义序列化程序并且它必须写一个值 - 当然你可以编写null,但自定义序列化程序本身不能只是拒绝写任何东西,因为属性名已经由来电者写了。

答案 2 :(得分:0)

如果使用注释,这应该可以正常工作:

public class Container{
    String description;
    @JsonIgnore
    Element1 element1;
    @JsonIgnore
    Element2 element2;
}

所以杰克逊忽略了@JsonIgnore注释的这两个

答案 3 :(得分:0)

要忽略容器中只有空/空成员(容器的成员,成员)的元素,您可以为Container创建自定义序列化程序。自定义序列化程序非常棒,因为它们可以最终控制对象的编写方式,但这也会导致代码难以维护。我之所以这么说是因为有了杰克逊,你可以用自定义的de / serializer完成任何事情,但对于大多数问题,通常都有一种更简洁的方式(例如通过注释)。为此,OP请求编写自定义序列化程序的指导,我不知道一种更简单的方法来实现所需的行为。

创建Module和自定义序列化程序

Jackson Module用于封装单个对象的反序列化器和序列化器。对于此示例,只需要一个序列化程序,但如果您想为Container添加解串器,则可以将其与ContainerModule内的序列化程序一起添加。以下代码定义了Container的序列化程序,如果其成员中至少有一个非空,则只编写element1element2

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

注册自定义序列化程序

可以使用ObjectMapper@JsonDeserialize或类上全局注册序列化程序。

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"
}