杰克逊将空值反序列化为空列表,无法访问实体

时间:2018-11-07 13:43:52

标签: java json jackson deserialization jackson-databind

我要实现的目标:

将空值反序列化为空列表

注意:我无法更改/注释实体,因为它们确实来自罐子。

我有以下代码:

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

public class MyJsonMapperList extends ObjectMapper{

private static final MyJsonMapperList jsonMapper = new MyJsonMapperList();

public MyJsonMapperList() {
    SimpleModule sm =  new SimpleModule();
    sm.addDeserializer(List.class, new NullToEmptyListDeserializer());
    super.registerModule(sm);
    // setSerializationInclusion(JsonInclude.Include.NON_NULL);
    // disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}

private static class NullToEmptyListDeserializer extends JsonDeserializer<List> {

    @Override
    public List deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));
        mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
        mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY, Nulls.AS_EMPTY));
        return mapper.readValue(jsonParser, new TypeReference<List>(){});
    }

    @Override
    public List getNullValue(DeserializationContext ctx) {
        return Collections.emptyList();
    }
}

public static <T> T fromJson(String json, Class<T> tClass) throws IOException {
    if (json == null) { return null; }
    return  jsonMapper.readerFor(tClass).readValue(json);

}

public static String toJson(Object bean) throws JsonProcessingException {
    if (bean == null) { return null; }
    return jsonMapper.writer().writeValueAsString(bean);
}

此代码的来源来自here。 我是否从 shyiko 提供的Kotlin代码中误解了某些内容?

*请注意,我也直接尝试过使用 setDeserializerModifier ,例如:

 public MyJsonMapperList () {
        SimpleModule sm = new SimpleModule();
        // sm.addDeserializer(CollectionType.class, new NullToEmptyListDeserializer ());
        sm.setDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public JsonDeserializer<?> modifyCollectionDeserializer(DeserializationConfig config, CollectionType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
                deserializer = new JsonDeserializer<List<?>>() {
                    @Override
                    public List<?> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                        ObjectMapper mapper = new ObjectMapper();
                        return mapper.readValue(jsonParser, new TypeReference<List>(){});
                    }
                    @Override
                    public List getNullValue(DeserializationContext ctx) {
                        return Collections.emptyList();
                    }
                };
                return deserializer;
            }
        });
        super.registerModule(sm);
//        setSerializationInclusion(JsonInclude.Include.NON_NULL);
//        disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

    }

我得到的错误:

java.lang.IllegalArgumentException: Cannot handle managed/back reference 'defaultReference': type: value deserializer of type MyJsonMapperList$NullToEmptyListDeserializer does not support them

    at com.fasterxml.jackson.databind.JsonDeserializer.findBackReference(JsonDeserializer.java:365)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase._resolveManagedReferenceProperty(BeanDeserializerBase.java:764)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:474)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
    at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477)
    at com.fasterxml.jackson.databind.ObjectReader._prefetchRootDeserializer(ObjectReader.java:1935)
    at com.fasterxml.jackson.databind.ObjectReader.<init>(ObjectReader.java:189)
    at com.fasterxml.jackson.databind.ObjectMapper._newReader(ObjectMapper.java:658)
    at com.fasterxml.jackson.databind.ObjectMapper.readerFor(ObjectMapper.java:3517)
    at ...MyJsonMapperList.fromJson(MyJsonMapperList.java:47)

实体没有任何@JsonManagedReference和@JsonBackReference注释(即使有,也无法对其进行修改)

杰克逊依赖性:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.0</version>
    </dependency>

我想念什么?

我还有其他可能性吗?

This answer听起来很有前途,但是由于受保护的访问,您无法访问objectMapperBuilder。

0 个答案:

没有答案