3

I am currently building an application that uses RestTemplate to structure API requests to the Alpha Vantage API. Here is a sample response excluding unnecessary metadata:

{
  "Time Series (Daily)": {
    "2017-11-10": {
      "1. open": "83.7900",
      "2. high": "84.1000",
      "3. low": "83.2300",
      "4. close": "83.8700",
      "5. volume": "19340435"
    },
    "2017-11-09": {
      "1. open": "84.1100",
      "2. high": "84.2700",
      "3. low": "82.9000",
      "4. close": "84.0900",
      "5. volume": "20924172"
    },
    "2017-11-08": {
      "1. open": "84.1400",
      "2. high": "84.6100",
      "3. low": "83.8300",
      "4. close": "84.5600",
      "5. volume": "18034170"
    },
    "2017-11-07": {
      "1. open": "84.7700",
      "2. high": "84.9000",
      "3. low": "83.9300",
      "4. close": "84.2700",
      "5. volume": "17152583"
    },
    "2017-11-06": {
      "1. open": "84.2000",
      "2. high": "84.7000",
      "3. low": "84.0800",
      "4. close": "84.4700",
      "5. volume": "19039847"
    },
    "2017-11-03": {
      "1. open": "84.0800",
      "2. high": "84.5400",
      "3. low": "83.4000",
      "4. close": "84.1400",
      "5. volume": "17569120"
    }
  }
}

I am building out my Data Transfer Object layer and it consists as such:

Top Layer:

public class Stock extends Dto{

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

    public TimeSeries getTimeSeries() {
        return timeSeries;
    }

    public void setTimeSeries(TimeSeries timeSeries) {
        this.timeSeries = timeSeries;
    }
}

Middle Layer:

public class TimeSeries extends Dto{

    private List<Day> days;

    public List<Day> getDays() {
        return days;
    }

    public void setDays(List<Day> days) {
        this.days = days;
    }
}

Final Layer (where data pans out):

@JsonIgnoreProperties(ignoreUnknown = true)
public class Day extends Dto{

    @JsonProperty("1. open")
    private double open;

    @JsonProperty("2. high")
    private double high;

    @JsonProperty("3. low")
    private double low;

    @JsonProperty("4. close")
    private double close;

    @JsonProperty("5. volume")
    private double volume;

    public double getOpen() {
        return open;
    }

    public void setOpen(double open) {
        this.open = open;
    }

    public double getHigh() {
        return high;
    }

    public void setHigh(double high) {
        this.high = high;
    }

    public double getLow() {
        return low;
    }

    public void setLow(double low) {
        this.low = low;
    }

    public double getClose() {
        return close;
    }

    public void setClose(double close) {
        this.close = close;
    }

    public double getVolume() {
        return volume;
    }

    public void setVolume(double volume) {
        this.volume = volume;
    }
}

What Happens When I Run My Application: When I run the application the top layer (Stock.java) gets populated with a Time Series object but then the next layer (TimeSeries.java) does not contain an array of (Day.java) objects as I expect and it is null. I have tried:

@JSONProperty("2017-11-10") 
private Day day;

And that does work and bridges the gap in the middle layer to the final layer and data comes through fine...but that's not what I'm after.

What I Expected To Happen/Want To Happen: I am trying to get an array of all of the dates (in TimeSeries.java) in the List of days but it won't work and I believe it is because the JSON response doesn't give them as an array of JavaScript objects but rather as an actual key and pair so I can't just make a list of them but have to directly drill down to the final object...which isn't what I want.

Threads I Have Read Regarding This Topic

Parse JSON array with resttemplate

Parsing JSON with Jackson

Parsing JSON with Jackson Java

Unable to consume JSON array using Spring RestTemplate

How to use query parameter represented as JSON with Spring RestTemplate?

How to deserialize an array of objects using Jackson or any other api?

desrialize JSON with child array using Jackson annotations?

Jackson Mapping List of String or simple String

Where should I get the object to represent what is passed (Json) in a RESTful api

If anyone knows how I can get that middle step to work and actually store the objects in the key "Time Series (Daily)" as Days then access their values that'd be awesome.

NOTE: Also if you are going to down-vote this please comment why you have done so below. I have researched this for the past 5 hours so I believe I've done due diligence to be able to ask here and I've been as thorough as possible...c'mon.

Benyam Ephrem
  • 448
  • 6
  • 20

1 Answers1

3

You don't have Json array in your json. You actually have json object with multiple fields, so your java data structure should be represented with Map and not List. If your want to keep current classes structure, then you should understand, that you loose the date part of timeseries. And i don't think you want this.


Option 1. Use HashMap<String, Day> timeSeries

public class Stock {

    @JsonProperty("Time Series (Daily)")
    private HashMap<String, Day> timeSeries;

    public HashMap<String, Day> getTimeSeries() {
        return timeSeries;
    }

    public void setTimeSeries(HashMap<String, Day> timeSeries) {
        this.timeSeries = timeSeries;
    }
}

Option 2. Change TimeSeries code

public class TimeSeries {

    // TreeMap because it preserves sorting order
    @JsonIgnore
    private Map<String, Day> days = new TreeMap<>();

    @JsonAnySetter
    public void setDays(String time, Day value){
        days.put(time,value);
    }

    @JsonAnyGetter
    public Map<String, Day> getData() {
        return days;
    }

    // add getDays() if you need only values
    // and if you need list, can use new ArrayList(days.values()) 
    @JsonIgnore
    public Collection<Day> getDays(){
        return days.values();
    }
}
varren
  • 14,551
  • 2
  • 41
  • 72