3

I've downloaded a large amount of historic crypto market data via an API. It is formatted like this:

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

I take that to be an array of arrays, the inner one containing heterogeneous types (always the same types in the same order). As an intermediate step I've saved it to text files but I'd like to read it back and map it onto an array of objects of this type:

    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;
//...
}

I'm using the Spring Framework and the jackson library for json mapping. Is it doable with that or should I manually parse the text somehow?

jilipop
  • 53
  • 5

3 Answers3

1

I would do this in two steps:

  1. Read the JSON content into a list of List<Object> with Jackson.
  2. Convert each List<Object> into a MinuteCandle object and collect these objects into a list of 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));
        }
    }
}

The conversion from List<Object> to MinuteCandle (step 2 from above) could be achieved by adding a static method in your MinuteCandle class.

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;
}
Thomas Fritsch
  • 9,639
  • 33
  • 37
  • 49
  • This worked like a charm, thanks. `new TypeReference>>()` can be replaced with `new TypeReference<>()`. I might end up using an array instead of an arraylist, as it will never need to change size and I'll be running costly calculations. – jilipop Jan 07 '21 at 22:57
1

Use JsonFormat and annotate your class with it where you specify shape as an ARRAY:

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

Also, consider to use BigDecimal instead of double if you want to store a price.

See also:

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • 1
    Wow, this works, too, and is simpler than Thomas' solution. I didn't think Jackson would know which fields to map to but obviously it simply does that from top to bottom. Also, thanks for recommending BigDecimal for prices. I'll look into it. – jilipop Jan 07 '21 at 23:11
0

Assuming the text stored in the file is valid JSON, similar to the solution in How to Read JSON data from txt file in Java? one can use com.google.gson.Gson as follows :

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);
        }
    }
}
Harsh Verma
  • 529
  • 6
  • 10
  • Thanks but I doubt it could be that simple. Tried it, though, and got "java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3 path $[0]" – jilipop Jan 07 '21 at 22:33