Nano Hash - криптовалюты, майнинг, программирование

ДжексонПолиморфикДесериализация: JsonMappingException

Я предположил, что у меня есть родительский класс Parameter, который имеет 2 подкласса ComboParameter и IntegerParameter.

@JsonSubTypes({
    @JsonSubTypes.Type(value = IntegerParameter.class, name = "integerParam"),
    @JsonSubTypes.Type(value = ComboParameter.class, name = "comboParam")
})
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.WRAPPER_OBJECT)
 public abstract class Parameter {
String regEx;
}


@JsonTypeName("integerParam")
public class IntegerParameter extends Parameter {
}

@JsonTypeName("comboParam")
public class ComboParameter extends Parameter {
List<String> values;
}

И у меня есть класс с параметром атрибута

class A {
@JsonUnwrapped
Parameter parameter;
}

Сериализация объекта A вызывает исключение

com.fasterxml.jackson.databind.JsonMappingException: свойство Unwrapped требует использования информации о типе: невозможно сериализовать без отключения SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS

И если я удалю аннотацию @JsonUnwrapped, у меня будет такой json

{
     parameter:{
          integerParam:{
               regEx: regExVal
          }
     }
}

И мне нужен такой json:

{
     integerParam:{
           regEx: regExVal
     }
}

Примечание Я использую Jackson 2.4.4.


  • найдите полиморфную десериализацию Джексона 12.03.2015
  • вы можете найти пример здесь 12.03.2015
  • Я отредактировал вопрос, чтобы быть более ясным 12.03.2015
  • к, в чем проблема? Как вы хотите, чтобы результат был? 14.03.2015
  • Мне нужен такой результат: { integerParam:{ regEx: regExVal } } 16.03.2015
  • удалите include = As.WRAPPER_OBJECT из класса Parmeter и попробуйте. 16.03.2015
  • Та же проблема осталась... 16.03.2015

Ответы:


1

Не думайте, что есть простое и чистое решение этой проблемы. Но вот некоторые мысли, как вы можете это решить (Gist demo для обоих случаев):

Вариант 1. Добавьте свойство @JsonIgnore выше и свойство @JsonAnyGetter в компонент верхнего уровня. Легко реализовать, но неудобно иметь статический ObjectMapper в bean-компоненте, и вам придется копировать этот код для каждого, имеющего свойство Parameter.

public class A {

    @JsonIgnore
    Parameter parameter;

    // can put ObjectMapper and most of this code in util class
    // and just use JacksonUtils.toMap(parameter) as return of JsonAnyGetter

    private static ObjectMapper mapper = new ObjectMapper();

    /************************ Serialization ************************/

    @JsonAnyGetter
    private Map<String, Object> parameterAsMap(){
        return mapper.convertValue(parameter, Map.class); 
    }

    /************************ Deserialization **********************/

    @JsonAnySetter
    private void parameterFromMap(String key, JsonNode value)  {
        try {
            parameter =  mapper.readValue(String.format("{\"%s\":%s}", key,value), 
                    Parameter.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Вариант 2: свойство @JsonIgnore и регистрация настраиваемого сериализатора/десериализатора для корневого класса A

SimpleModule module = new SimpleModule();
module.addSerializer(A.class, new ASerializer());
module.addDeserializer(A.class, new ADeserializer());
mapper.registerModule(module);

Невозможно использовать @JsonSerialize выше класса A, потому что сериализаторы и десериализаторы внутреннего ObjectMapper также будут использовать эту аннотацию, но вам нужно настроить ее на использование сериализатора/десериализатора по умолчанию, а не рекурсивно. Или вы можете реализовать что-то вроде https://stackoverflow.com/a/18405958/1032167, если вам действительно нужна аннотация

И сериализатор + десериализатор будет выглядеть примерно так (Неоптимизированный и просто доказательство концепции):

    /************************ Serialization ************************/

public static class ASerializer extends JsonSerializer<A> {
    private static ObjectMapper m = new ObjectMapper();

    @Override
    public void serialize(A value, JsonGenerator gen,
                          SerializerProvider serializers) throws IOException {
        Map defaults = m.convertValue(value, Map.class);
        Map params = m.convertValue(value.getParameter(), Map.class);
        defaults.putAll(params);
        gen.writeObject(defaults);
    }

}

    /************************ Deserialization **********************/

public static class ADeserializer extends JsonDeserializer<A> {
    private static ObjectMapper m = new ObjectMapper();
    private static String[] subtipes = {"integerParam", "comboParam"};

    public ADeserializer() {
        m.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    @Override
    public A deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException {

        TreeNode node = m.readTree(p);

        A a = m.convertValue(node, A.class);

        // hardcoded , probably can be done dynamically
        // with annotations inspection
        for (String key : subtipes) {
            TreeNode value = node.get(key);
            if (value != null) {
                String json = String.format("{\"%s\":%s}", key, value);
                a.setParameter(m.readValue(json, Parameter.class));
                break;
            }
        }

        return a;
    }
}

Общий десериализатор было бы довольно сложно написать. Но этот вопрос в любом случае касается сериализации в соответствии с телом вопроса.

17.10.2017
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..