gpt4 book ai didi

java - 如何使用 Jackson JSON 注释来抑制空对象?

转载 作者:行者123 更新时间:2023-11-30 08:12:55 25 4
gpt4 key购买 nike

我正在尝试序列化类似于以下内容的对象:

class Header {
public String title;
public String author;
}
class Document {
public String data;
public Header header = new Header();
}

没有任何注释,jackson 将序列化为:

{"data":null,"header":{"title":null,"author":null}}

HeaderDocument 上使用 @JsonInclude(NOT_NULL)@JsonInclude(NOT_EMPTY),它将序列化为:

{"header":{}}

如果 header 属性为空,我想抑制该属性,但这仅支持集合和字符串。理想情况下,这可以通过注释来解决,因为默认的 BeanSerializer 能够轻松实现这一点。

我可以通过编写自定义序列化器来实现我所需要的,但随后我就失去了默认序列化器内所有高级逻辑的好处。

有人能想出更好的方法来解决这个问题吗?上面的结构只是一个示例,因为我正在寻找通用的解决方案。

最佳答案

这并不是那么容易 - 基本上,bean 序列化程序必须推迟编写属性的字段名称,直到属性序列化程序编写某些内容为止 - 一旦您嵌套了几个这样的内容,这可能会变得特别棘手彼此。

解决此问题的最简单方法是让属性序列化程序将其值序列化到 token 缓冲区,然后如果 token 缓冲区仅包含“{”和“}”,则跳过该属性。但这意味着对象图最终将在每个级别的缓冲区中读入和读出,这违背了流生成器的目的,流生成器不会构建与生成的输出大小成比例的内容。

如果您可以接受缓冲区复制,这将大致满足您的要求:

@Test
public void suppress_empty_objects() throws Exception {
mapper.registerModule(new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
context.addBeanSerializerModifier(new SuppressEmptyBean());
}

class SuppressEmptyBean extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
BeanDescription beanDesc,
List<BeanPropertyWriter> beanProperties) {
// TODO: examine bean description for annotations to enable/disable suppression
ListIterator<BeanPropertyWriter> iter = beanProperties.listIterator();
while (iter.hasNext()) {
BeanPropertyWriter beanPropertyWriter = iter.next();
// TODO: only relevant to suppress properties that are themselves beans
iter.set(new SuppressEmptyPropertyWriter(beanPropertyWriter));
}
return beanProperties;
}
}

class SuppressEmptyPropertyWriter extends BeanPropertyWriter {
private final BeanPropertyWriter underlying;

SuppressEmptyPropertyWriter(BeanPropertyWriter underlying) {
super(underlying);
this.underlying = underlying;
}

@Override
public void serializeAsField(Object bean, JsonGenerator output, SerializerProvider prov)
throws Exception {
TokenBuffer tokenBuffer = new TokenBuffer(output.getCodec(), false);
underlying.serializeAsField(bean, tokenBuffer, prov);
if (!suppress(tokenBuffer, output)) {
tokenBuffer.serialize(output);
}
}

private boolean suppress(TokenBuffer tokenBuffer, JsonGenerator output) throws JsonParseException,
IOException {
if (tokenBuffer.firstToken() != JsonToken.FIELD_NAME) return false; // nope
JsonParser bufferParser = tokenBuffer.asParser();
bufferParser.nextToken(); // on field name
JsonToken valueToken1 = bufferParser.nextToken(); // on start object
if (valueToken1 != JsonToken.START_OBJECT) return false;
JsonToken valueToken2 = bufferParser.nextToken(); // on first thing inside object
return valueToken2 == JsonToken.END_OBJECT;
}
}

});
Document document = new Document();
document.data = "test";
assertThat(mapper.writeValueAsString(document), equivalentTo("{ data: 'test' }"));
document.header = new Header();
assertThat(mapper.writeValueAsString(document), equivalentTo("{ data: 'test' }"));
document.header.title = "the title";
assertThat(mapper.writeValueAsString(document),
equivalentTo("{ data: 'test', header: { title: 'the title' } }"));
}

关于java - 如何使用 Jackson JSON 注释来抑制空对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30109850/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com