使用com.jackson从JSON字符串获取Java对象的最佳方法。

时间:2018-09-12 22:02:32

标签: java jackson

具体来说,我正在处理一个JSON字符串,它表示一个包含数字和其他数字数组的数组-这些字符串的格式为String string = "[0, [1, 2], [3, 4]]"。它表示格式为[ channelID, [price, amount], [price, amount] ... [price, amount]]的数据;重复数据的长度可以变化。

我的最终目标是将该字符串转换为ChannelObject { channel: 0, data: [PriceObject { price: 1, amount: 2 }, PriceObject { price: 3, amount: 4 }] }形式的对象。

Jackson的本机objectMapper在尝试向类读取未封装的JSON数组的值时引发错误,而我发现的唯一解决方案是为ObjectMapper解析器提供字符串{ "data": %s },并替换为原始字符串。 JSON,并使用具有属性@JsonProperty ArrayNode data的类,但就性能而言,这恐怕是一种低效的方法。

写“反” JSON数组的反序列化器是最聪明的方法吗?有没有更简单的解决方案,我错过了?

非常感谢您答复。

其他信息:

ObjectMapper不起作用。

public static void main(String args[]) {
    String input = "[17847,[5391.9,0,-1]";
    ObjectMapper mapper = new ObjectMapper();
    List<ChannelData> list = mapper.readValue(input, ChannelData[].class);
}

public class ChannelData {
    private int channel;

    private List<Data> data;

    public ChannelData(int channel, List<Data> data) {
        this.channel = channel;
        this.data = data;
    }

    public int getChannel() {
        return channel;
    }

    public void setChannel(int channel) {
        this.channel = channel;
    }

    public List<Data> getData() {
        return data;
    }

    public void setData(List<Data> data) {
        this.data = data;
    }
}

public class Data {
    private BigDecimal price;

    private int count;

    private BigDecimal amount;

    public Data() {
    }

    public Data(BigDecimal price, int count, BigDecimal amount) {
        this.price = price;
        this.count = count;
        this.amount = amount;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }
}

错误:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `co.myproject.Application$ChannelData` (no Creators, like default construct, exist): no int/Int-argument constructor/factory method to deserialize from Number value (17847)
 at [Source: (String)"[17847,[5391.9,0,-1]]"; line: 1, column: 2] (through reference chain: java.lang.Object[][0])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027)
    at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromInt(ValueInstantiator.java:262)
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromInt(StdValueInstantiator.java:356)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromNumber(BeanDeserializerBase.java:1324)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:173)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
    at co.myproject.Application.run(Application.java:27)
    at co.myproject.Application.main(Application.java:39)

Process finished with exit code 1

1 个答案:

答案 0 :(得分:2)

错误消息明确指出ChannelData类中没有默认构造函数(这不是参数构造器),在ChannelData类中没有创建参数构造器。

自从您声明了public ChannelData(int channel, List<Data> data) ChannelData参数构造函数以来,您就必须声明不声明任何参数构造函数

public class ChannelData {
      public ChannelData() { // no arg constructor }