Джексон десериализует нули в пустой список без доступа к сущности - PullRequest
0 голосов
/ 07 ноября 2018

Чего я пытаюсь достичь:

для десериализации пустых значений в пустые списки

Примечание : я не могу изменить / аннотировать объекты, потому что они происходят из банки.

У меня есть следующий код:

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);
}

Источник для этого кода от здесь . Правильно ли я что-то истолковал из кода Kotlin, предоставленного shyiko ?

* Примечание. Я также пытался напрямую использовать 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>

Что мне не хватает?

Есть ли другие возможности, которые я пропустил?

Этот ответ звучит многообещающе, но у вас нет доступа к objectMapperBuilder из-за защищенного доступа.

...