Проблема десериализации Джексона с финальными классами в Map - PullRequest
0 голосов
/ 01 мая 2018

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

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

"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"])

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

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Переопределите ваши бобы, как указано ниже

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), вам нужно использовать пользовательские JsonSerializer / Deserializer. Для joda DateTime в библиотеке Codehaus уже был сериализатор.
  • Переходите к Джексону 2, если это возможно.
0 голосов
/ 01 мая 2018

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

Map<String, Config> map = mapper.readValue(jsonInput, new TypeReference<HashMap<String, Config>>() {});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...