Проблема десериализации Джексона с финальными классами на карте

Я использую Джексона в java для десериализации json blob, который состоит из карты объектов. Но, к сожалению, мой код выдает исключение.

У меня есть следующий удар данных, который я хочу десериализовать с помощью Джексона:

"config": {
    "configItem1": {
        "0": {
            "valueBit": false,
            "valueInt": 0,
            "valueFloat": 0,
            "timestamp": "2016-10-05T13:44:04.223Z"
        },
        "1": {
            "valueBit": false,
            "valueInt": 0,
            "valueFloat": 0,
            "timestamp": "2016-10-05T13:44:04.223Z"
        }
    },
    "configItem2": {
        "0": {
            "valueBit": false,
            "valueInt": 0,
            "valueFloat": 0,
            "timestamp": "2018-03-15T11:39:47.550Z"
        }
    }
}

И у меня есть следующий класс модели, в который я пытаюсь сериализовать:

public class VehicleConfigValues {

    private final Boolean valueBit;
    private final Integer valueInt;
    private final Double valueFloat;
    private final DateTime valueDate;
    private final DateTime timestamp;
    private final String changedBy;

    public ConfigValues(Boolean valueBit, Integer valueInt, Double valueFloat, DateTime valueDate, DateTime timestamp, String changedBy) {
        this.valueBit = valueBit;
        this.valueInt = valueInt;
        this.valueFloat = valueFloat;
        this.valueDate = valueDate;
        this.timestamp = timestamp;
        this.changedBy = changedBy;
    }

    final static ConfigValues defaultConfig = new ConfigValues(false, 0, 0.0, null, null, null);

    public Boolean getValueBit() {
        return valueBit;
    }

    public Integer getValueInt() {
        return valueInt;
    }

    public Double getValueFloat() {
        return valueFloat;
    }

    public DateTime getValueDate() {
        return valueDate;
    }

    public DateTime getTimestamp() {
        return timestamp;
    }

    public String getChangedBy() {
        return changedBy;
    }
}

public class Config {

    private Map<String, Map<Integer, ConfigValues>> config;

    public Config() {

    }

    public Config(Map<String, Map<Integer, ConfigValues>> config) {
        this.config = config;
    }

    public Map<String, Map<Integer, ConfigValues>> getConfig() {
        return config;
    }
}

И у меня есть следующий основной метод, вызывающий десериализацию указанного выше блоба в эти классы:

public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        try {

            // Convert JSON string from file to Object
            Config user = mapper.readValue(new File("C:\\mConfig\\config.json"), Config.class);
            System.out.println(user);

        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Но, к сожалению, я получаю следующую ошибку:

org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class ConfigValues]: can not instantiate from JSON object (need to add/enable type information?)
 at [Source: C:\Config\config.json; line: 5, column: 17] (through reference chain: Config["config"])

Кто-нибудь может пролить свет на это? Мне сложно отладить, почему эта десериализация не работает

Сама ошибка возникает из-за того, что класс не определяет конструктор без аргументов ("по умолчанию") ИЛИ конструктор / статический фабричный метод, аннотированный @JsonCreator. В принятом ответе показано, как это сделать, но вы можете в качестве альтернативы добавить конструктор без аргументов private для использования Джексоном: это также будет работать, а затем для присвоения значений будут использоваться методы набора (или поля напрямую).

StaxMan 03.05.2018 01:10
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
752
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете попробовать это:

Map<String, Config> map = mapper.readValue(jsonInput, new TypeReference<HashMap<String, Config>>() {});

Привет, спасибо за помощь. Но даже с этим кодом я все равно получаю сообщение об ошибке: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: нераспознанное поле «configItem1» (конфигурация класса), не отмеченное как игнорируемое в [Источник:; строка: 3, столбец: 28] (через цепочку ссылок: Config ["configItem1"])

user1501171 01.05.2018 17:17
Ответ принят как подходящий

Измените определение бобов, как указано ниже

import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.ext.JodaSerializers.DateTimeSerializer;
import org.joda.time.DateTime;

public class ConfigValues {

    private final Boolean valueBit;
    private final Integer valueInt;
    private final Double valueFloat;
    private final DateTime valueDate;
    private final DateTime timestamp;
    private final String changedBy;

    @JsonCreator
    public ConfigValues(
        @JsonProperty("valueBit") Boolean valueBit,
        @JsonProperty("valueInt") Integer valueInt,
        @JsonProperty("valueFloat") Double valueFloat,
        @JsonSerialize(using = DateTimeSerializer.class) @JsonProperty("valueDate") DateTime valueDate,
        @JsonSerialize(using = DateTimeSerializer.class) @JsonProperty("timestamp") DateTime timestamp,
        @JsonProperty("changedBy") String changedBy) {

    this.valueBit = valueBit;
    this.valueInt = valueInt;
    this.valueFloat = valueFloat;
    this.valueDate = valueDate;
    this.timestamp = timestamp;
    this.changedBy = changedBy;
    }

    final static ConfigValues defaultConfig = new ConfigValues(false, 0, 0.0, null, null, null);

    public Boolean getValueBit() {
    return valueBit;
    }

    public Integer getValueInt() {
    return valueInt;
    }

    public Double getValueFloat() {
    return valueFloat;
    }

    public DateTime getValueDate() {
    return valueDate;
    }

    public DateTime getTimestamp() {
    return timestamp;
    }

    public String getChangedBy() {
    return changedBy;
    }
}

а также

import java.util.Map;

import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;

public class Config {

    private final Map<String, Map<Integer, ConfigValues>> config;


    @JsonCreator
    public Config(@JsonProperty("config") Map<String, Map<Integer, ConfigValues>> config) {
        this.config = config;
    }

    public Map<String, Map<Integer, ConfigValues>> getConfig() {
        return config;
    }
}

Несколько очков:

  • @JsonCreator необходим, если вы хотите сериализовать финальный класс. Его следует использовать в конструкторе, и в этом случае аннотация @JsonProperty является обязательной для параметров.
  • По умолчанию Джексон сериализует только примитивные классы / классы POJO. Если вы хотите выполнить поиск любых пользовательских классов (например, DateTime), вам необходимо использовать пользовательские JsonSerializers / Deserializers. Для joda DateTime в библиотеке codehaus уже есть сериализаторы.
  • Если возможно, переместитесь в Джексон 2.

Спасибо за вашу помощь! К сожалению, даже с этими изменениями я все еще получаю «ошибку нераспознанного поля» в «configitem1». Разве это не идентифицирует эти поля как элементы на карте?

user1501171 01.05.2018 18:31

Выше рабочий код, который я написал в eclipse и запустил с помощью codehaus lib версии 1.8.5. Какую версию библиотеки Джексона вы используете

Pratapi Hemant Patel 01.05.2018 18:36

Привет, я использую библиотеку jackson-all-1.9.0. Стоит ли мне переехать в Джексон 2?

user1501171 01.05.2018 18:42

Я использую эту библиотеку mvnrepository.com/artifact/org.codehaus.jackson/…. Код работает нормально даже с этой версией jar.

Pratapi Hemant Patel 01.05.2018 18:48

Когда я запускаю IntelliJ, все еще выдает ошибку, внесли ли вы какие-либо изменения в большой двоичный объект JSON или основной метод приложения?

user1501171 01.05.2018 18:50

Просто добавил ваш json в фигурные скобки, так как он недействителен. Также отредактировал рассматриваемый json. Основной метод такой же.

Pratapi Hemant Patel 01.05.2018 18:52

Позвольте нам продолжить обсуждение в чате.

Pratapi Hemant Patel 01.05.2018 18:53

Другие вопросы по теме