Jackson:将各种不存在的列表反序列化为空列表

问题描述 投票:0回答:1

给出以下 SampleTestClass,我尝试将 JSON 解析为 Java:

class EmptyListDeserializerTest {

final ObjectMapper objectMapper = new ObjectMapper();

{
    objectMapper.configOverride(List.class)
            .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY, Nulls.AS_EMPTY));
}

@Test
void test2() throws JsonProcessingException {
    final var result = objectMapper.readValue("null", new TypeReference<List<MyClass>>() {});

    assertThat(result).isEmpty();
}

@Test
void test3() throws JsonProcessingException {
    final var json = """
            [{
               "name": "John Doe",
               "address": null
             }]
            """;
    final var result = objectMapper.readValue(json, new TypeReference<List<MyComplexClass>>() {});

    assertThat(result.get(0).address).isEmpty();
}

@Test
void test4() throws JsonProcessingException {
    final var json = """
            [{
               "name": "John Doe"
             }]
            """;
    final var result = objectMapper.readValue(json, new TypeReference<List<MyComplexClass>>() {});

    assertThat(result.get(0).address).isEmpty();
}

public static class MyClass {

    public MyClass() {
    }

    private String name;

    public MyClass(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }
}

public static class MyComplexClass {

    public MyComplexClass() {
    }

    private String name;
    private List<String> address;

    public MyComplexClass(final String name, final List<String> address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public List<String> getAddress() {
        return address;
    }

    public void setAddress(final List<String> address) {
        this.address = address;
    }
}

}

我想实现将所有类型的不存在列表映射到空列表。 调整实体本身并不是解决方案。 只有 ObjectMapper 具有适应性。

我尝试了各种可能的解决方案,但只设法让test3通过,所有其他都失败了。

我还尝试了 CustomerDeserializer,但它从未被调用,即使已注册:

public List<?> deserialize(JsonParser p, DeserializationContext ctxt)

那么,我错过了什么?

--- 编辑 ---

改用此配置:

    {
    objectMapper.configOverride(List.class)
            .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY, Nulls.AS_EMPTY));
    SimpleModule module = new SimpleModule();
    module.addDeserializer(List.class, new EmptyListDeserializer());
    this.objectMapper.registerModule(module);
    }

并稍微修改 test2 (添加转义双引号):

@Test
void test2() throws JsonProcessingException {
    final var result = objectMapper.readValue("\"null\"", new TypeReference<List<MyClass>>() {});

    assertThat(result).isEmpty();
}

测试 2 通过,但测试 3 失败。

CustomDeserializer 看起来像这样:

public class EmptyListDeserializer extends JsonDeserializer<List<?>> {

@Override
public List<?> deserialize(JsonParser p, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
    // Check for null or 'null' string value
    if (p.getCurrentToken() == JsonToken.VALUE_NULL
            || p.getCurrentToken().isScalarValue()
            || (p.getCurrentToken() == JsonToken.VALUE_STRING && "null".equals(p.getText()))) {
        return Collections.emptyList();
    }
    // Otherwise, proceed with default deserialization
    return p.readValueAs(List.class);
}
java jackson objectmapper
1个回答
0
投票

test4
没有解决方案。 Jackson 通过 json 属性进行迭代,并且从不触及 json 中未提及的属性。

我在这里看到两个选项:

  1. 添加自定义实例化器并使用默认值填充列表。
  2. 后处理反序列化对象并用空列表替换
    null

test2
也不起作用。只需检查结果并将
null
替换为所需值即可。

© www.soinside.com 2019 - 2024. All rights reserved.