如何将一个异构JSON数组映射到Java对象?

3

我通过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框架和jackson库进行JSON映射。这是否可行,还是我应该手动解析文本?

3个回答

1
我会分两步来完成:
  1. 使用Jackson将JSON内容读入List<Object>列表中。
  2. 将每个List<Object>转换为一个MinuteCandle对象,并将这些对象收集到MinuteCandle列表中。
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<Object>转换为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<List<List<Object>>>() 可以替换为 new TypeReference<>()。我可能会使用数组而不是ArrayList,因为它永远不需要改变大小,而且我将运行昂贵的计算。 - jilipop

1

1
哇,这也可以工作,并且比Thomas的解决方案更简单。我没想到Jackson会知道要映射哪些字段,但显然它只是从上到下简单地执行。此外,感谢您推荐BigDecimal用于价格。我会研究一下。 - jilipop

0
假设文件中存储的文本是有效的JSON,类似于如何在Java中从txt文件读取JSON数据?中的解决方案,可以使用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]”的错误。 - jilipop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接