杰克逊反序列化问题与Map中的最终类

时间:2018-05-01 15:04:52

标签: java serialization jackson

我在java中使用jackson反序列化由对象映射组成的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;
    }
}

我有以下主要方法将上述blob的反序列化调用到这些类中:

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 :(得分:2)

重新定义您的咖啡豆,如下所示

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)进行searial化,则需要使用自定义JsonSerializers / Deserializers。对于joda DateTime,codehaus库中已有一个序列化器。
  • 如果可能,请转到杰克逊2。

答案 1 :(得分:1)

你可以试试这个:

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