2

I'm trying to parse a JSON that used the date as the array name and is therefore variable. How do I do this using Java / Spring?

"Time Series (Daily)": {
    "2018-08-21": {
        "1. open": "106.9200",
        "2. high": "107.2500",
        "3. low": "106.8100",
        "4. close": "107.0650",
        "5. volume": "1156207"
    },
    "2018-08-20": {
        "1. open": "107.5100",
        "2. high": "107.9000",
        "3. low": "106.4800",
        "4. close": "106.8700",
        "5. volume": "17914201"
    },

To get time series (Daily) I'm using:

@JsonProperty("Time Series (Daily)")
TimeSeries timeSeries;

But what do do with the TimeSeries object as

@JsonProperty("2018-08-21")
Date date;

would only get the first one?

co ting
  • 125
  • 1
  • 8
  • 1
    FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now legacy, supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). You want `LocalDate` class for a date-only value. – Basil Bourque Aug 21 '18 at 18:51
  • See [*Java 8 LocalDate Jackson format*](https://stackoverflow.com/q/28802544/642706) – Basil Bourque Aug 21 '18 at 18:53
  • If deserialising to a POJO with Jackson you may be able to use jsonanysetter / jsonanygetter if trying to resolve the changing key challenge. Some further information here https://tech.willhaben.at/deserializing-dynamic-json-documents-jackson-objectmapper-on-steroids-9eab587436e2 – Rich Ackroyd Aug 22 '18 at 05:07

1 Answers1

0

Found a solution by writing a custom deserializer.

Time series class:

@JsonDeserialize(using = AvTimeSeriesDeserializer.class)
public class AvTimeSeries {

        List<AvDay> avDays;

    public List<AvDay> getAvDays() {
        return avDays;
    }

    public void setAvDays(List<AvDay> avDays) {
        this.avDays = avDays;
    }

}

Deserializer:

public class AvTimeSeriesDeserializer extends StdDeserializer<AvTimeSeries> {

/**
 * 
 */
private static final long serialVersionUID = 1L;

public AvTimeSeriesDeserializer() {
    this(null);
}

public AvTimeSeriesDeserializer(Class<?> vc) {
    super(vc);
}

@Override
public AvTimeSeries deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {

List<AvDay> avDays = new ArrayList<>();

    JsonNode node = jp.getCodec().readTree(jp);
    Iterator<Entry<String, JsonNode>> hello = node.fields();
    hello.forEachRemaining(nodeA -> {
        String date = nodeA.getKey();
        JsonNode kappes = nodeA.getValue();
        double open = kappes.get("1. open").asDouble();
        double high = kappes.get("2. high").asDouble();
        double low = kappes.get("3. low").asDouble();
        double close = kappes.get("4. close").asDouble();
        long volume = kappes.get("5. volume").asLong();
        AvDay avDay = new AvDay(date, open, high, low, close, volume);
        avDays.add(avDay);
    });

    AvTimeSeries result = new AvTimeSeries();
    result.setAvDays(avDays);
    return result;
}

}

This can probably still be optimized but it's working.

co ting
  • 125
  • 1
  • 8