【问题标题】:How do I map a heterogeneous JSON array to a Java object?如何将异构 JSON 数组映射到 Java 对象?
【发布时间】:2021-01-07 16:55:44
【问题描述】:

我通过 API 下载了大量的历史加密市场数据。它的格式如下:

[
[1601510400000,"4.15540000","4.16450000","4.15010000","4.15030000","4483.01000000",1601510459999,"18646.50051400",50,"2943.27000000","12241.83706500","0"],
...
[1609490340000,"4.94020000","4.95970000","4.93880000","4.94950000","5307.62000000",1609490399999,"26280.03711000",98,"3751.46000000","18574.22402400","0"]
]

我认为它是一个数组数组,内部数组包含异构类型(始终以相同的顺序排列相同的类型)。作为中间步骤,我已将其保存到文本文件中,但我想将其读回并将其映射到此类对象的数组中:

    public class MinuteCandle {
        private long openTime;
        private double openValue;
        private double highValue;
        private double lowValue;
        private double closeValue;
        private double volume;
        private long closeTime;
        private double quoteAssetVolume;
        private int numberOfTrades;
        private double takerBuyBaseAssetVolume;
        private double takerBuyQuoteAssetVolume;
        private double someGarbageData;
//...
}

我正在使用 Spring Framework 和 jackson 库进行 json 映射。这样做可行还是我应该以某种方式手动解析文本?

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    使用JsonFormat 并在您将形状指定为ARRAY 的地方用它注释您的类:

    @JsonFormat(shape = JsonFormat.Shape.ARRAY)
    class MinuteCandle
    

    另外,如果您想存储价格,请考虑使用BigDecimal 而不是double

    另见:

    【讨论】:

    • 哇,这也有效,而且比 Thomas 的解决方案更简单。我不认为杰克逊会知道映射到哪些字段,但显然它只是从上到下做到这一点。另外,感谢您推荐 BigDecimal 的价格。我会调查的。
    【解决方案2】:

    我会分两步完成:

    1. 使用 Jackson 将 JSON 内容读入List<Object> 列表。
    2. 将每个List<Object> 转换为MinuteCandle 对象 并将这些对象收集到MinuteCandles 列表中。
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class Main {
    
        public static void main(String[] args) throws Exception {
            ObjectMapper objectMapper = new ObjectMapper();
            File file = new File("example.json");
            List<List<Object>> lists = objectMapper.readValue(file, new TypeReference<List<List<Object>>>() {});
            List<MinuteCandle> minuteCandles = new ArrayList<>();
            for (List<Object> list : lists) {
                minuteCandles.add(MinuteCandle.createFromList(list));
            }
        }
    }
    

    List&lt;Object&gt;MinuteCandle 的转换(上面的第2 步) 可以通过在 MinuteCandle 类中添加静态方法来实现。

    public static MinuteCandle createFromList(List<Object> list) {
        MinuteCandle m = new MinuteCandle();
        m.openTime = (Long) list.get(0);
        m.openValue = Double.parseDouble((String) list.get(1));
        m.highValue = Double.parseDouble((String) list.get(2));
        m.lowValue = Double.parseDouble((String) list.get(3));
        m.closeValue = Double.parseDouble((String) list.get(4));
        m.volume = Double.parseDouble((String) list.get(5));
        m.closeTime = (Long) list.get(6);
        m.quoteAssetVolume = Double.parseDouble((String) list.get(7));
        m.numberOfTrades = (Integer) list.get(8);
        m.takerBuyBaseAssetVolume = Double.parseDouble((String) list.get(9));
        m.takerBuyQuoteAssetVolume = Double.parseDouble((String) list.get(10));
        m.someGarbageData = Double.parseDouble((String) list.get(11));
        return m;
    }
    

    【讨论】:

    • 这就像一个魅力,谢谢。 new TypeReference&lt;List&lt;List&lt;Object&gt;&gt;&gt;() 可以替换为 new TypeReference&lt;&gt;()。我最终可能会使用数组而不是数组列表,因为它永远不需要更改大小,而且我将运行昂贵的计算。
    【解决方案3】:

    假设文件中存储的文本是有效的JSON,类似How to Read JSON data from txt file in Java?中的解决方案可以使用com.google.gson.Gson如下:

    import com.google.gson.Gson;
    import java.io.FileReader;
    import java.io.Reader;
    
    public class Main {
        public static void main(String[] args) throws Exception {
            try (Reader reader = new FileReader("somefile.txt")) {
                Gson gson = new Gson();
                MinuteCandle[] features = gson.fromJson(reader, MinuteCandle[].class);
            }
        }
    }
    

    【讨论】:

    • 谢谢,但我怀疑它可能这么简单。不过尝试了一下,得到“java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3 path $[0]”
    猜你喜欢
    • 1970-01-01
    • 2019-03-21
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 2023-03-17
    • 2014-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多