我有以下课程:
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。
现在,如果element1
,element2
和f11
,f12
非常谨慎,我希望不要将f21
和f22
包含在json中是空白的。
正如我所说,我应该写cistom序列化器,但我不了解哪个实体。 Element
或Container
?怎么样?
P.S。
我的问题与Ignoring new fields on JSON objects using Jackson
不重复本主题介绍如何忽略Container内的空值。我的问题是如何忽略Container内的对象,其中
中只有空值答案 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
的序列化程序,如果其成员中至少有一个非空,则只编写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<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"
}