Skip to content
Advertisement

Getting null values while mapping a JSON to POJO

I am trying to map a JSON to POJO using Jackson. However, as this JSON contains a nested map of objects, when i de-serialize it to the POJO, the timeseries information is not converted to the POJO. I am only able to get the metadata part and the date part in the timeseries block. The other fields in the timeseries block such as open, high and low are always null.

It seems like Jackson is not able to match the fields with in the TimeSeries class. Can someone please tell how should I do this or point me in the correct direction. Or if there is some other better way to do this. Thanks!

Here is an example of the JSON

{
"Meta Data": {
    "1. Information": "Daily Prices (open, high, low, close) and Volumes",
    "2. Symbol": "MSFT",
    "3. Last Refreshed": "2019-02-15",
    "4. Output Size": "Compact",
    "5. Time Zone": "US/Eastern"
},
"Time Series (Daily)": {
    "2019-02-15": {
        "1. open": "107.9100",
        "2. high": "108.3000",
        "3. low": "107.3624",
        "4. close": "108.2200",
        "5. volume": "26606886"
    },
    "2019-02-14": {
        "1. open": "106.3100",
        "2. high": "107.2900",
        "3. low": "105.6600",
        "4. close": "106.9000",
        "5. volume": "21784703"
    }
 }
}

Now, in order to map this JSON, I have created these POJO’s

@JsonIgnoreProperties(ignoreUnknown = true)
public class HistoricalStock {
@JsonProperty("Meta Data")
private MetaData metadata;

private Map<String, TimeSeriesInfo> stockDailyData = new HashMap<String, TimeSeriesInfo>();

public HistoricalStock() {
}

public MetaData getMetadata() {
    return metadata;
}

public void setMetadata(MetaData metadata) {
    this.metadata = metadata;
}

@JsonAnyGetter
public Map<String, TimeSeriesInfo> getStockDailyData() {
    return stockDailyData;
}

@JsonAnySetter
public void setStockDailyData(String date, TimeSeriesInfo stockInfo) {
    this.stockDailyData.put(date, stockInfo);
}

@Override
public String toString() {
    return "HistoricalStock [metadata=" + metadata + ", stockDailyData=" + stockDailyData + "]";
}

}

And this is the code to deserialize the JSON using Jackson.

String fooResourceUrl = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=DEMO";
        ResponseEntity<String> response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
        ObjectMapper customMapper = new ObjectMapper();

        try {
            HistoricalStock msft = customMapper.readValue(response.getBody(), HistoricalStock.class);
            System.out.println(msft.getMetadata());
            System.out.println(msft.getStockDailyData().toString());

        } catch (IOException ioException) {
            ioException.printStackTrace();
        }

Here’s the code for TimeSeries Class

@JsonIgnoreProperties(ignoreUnknown = true)
public class TimeSeriesInfo {
@JsonProperty("1. open")
private Double openingPrice;

@JsonProperty("2. high")
private Double highestPrice;

@JsonProperty("3. low")
private Double lowestPrice;

@JsonProperty("4. close")
private Double closingPrice;

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

public TimeSeriesInfo() {
}

public Double getOpeningPrice() {
    return openingPrice;
}

public void setOpeningPrice(Double openingPrice) {
    this.openingPrice = openingPrice;
}

public Double getHighestPrice() {
    return highestPrice;
}

public void setHighestPrice(Double highestPrice) {
    this.highestPrice = highestPrice;
}

public Double getLowestPrice() {
    return lowestPrice;
}

public void setLowestPrice(Double lowestPrice) {
    this.lowestPrice = lowestPrice;
}

public Double getClosingPrice() {
    return closingPrice;
}

public void setClosingPrice(Double closingPrice) {
    this.closingPrice = closingPrice;
}

public Long getVolume() {
    return volume;
}

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

@Override
public String toString() {
    return "TimeSeries [openingPrice=" + openingPrice + ", highestPrice=" + highestPrice + ", lowestPrice="
            + lowestPrice + ", closingPrice=" + closingPrice + ", volume=" + volume + "]";
    }

}

Advertisement

Answer

In this particular example you do not need to use @JsonAnyGetter and @JsonAnySetter annotations. Just create a Map<String, TimeSeriesInfo> property and it should work without a problem. Also, I propose to use BigDecimal instead of Double and Long. Below you can find whole POJOs structure which works properly without any extra annotations:

class DailySeries {

    @JsonProperty("Meta Data")
    private Metadata metadata;

    @JsonProperty("Time Series (Daily)")
    private Map<String, Daily> series;

    public Metadata getMetadata() {
        return metadata;
    }

    public void setMetadata(Metadata metadata) {
        this.metadata = metadata;
    }

    public Map<String, Daily> getSeries() {
        return series;
    }

    public void setSeries(Map<String, Daily> series) {
        this.series = series;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        String lineSeparator = System.lineSeparator();
        sb.append("metadata=").append(metadata).append(lineSeparator);
        series.forEach((k, s) -> sb.append(k).append(" = ").append(s).append(lineSeparator));

        return sb.toString();
    }
}

class Metadata {

    @JsonProperty("1. Information")
    private String information;

    @JsonProperty("2. Symbol")
    private String symbol;

    @JsonProperty("3. Last Refreshed")
    private String lastRefreshed;

    @JsonProperty("4. Output Size")
    private String outputSize;

    @JsonProperty("5. Time Zone")
    private String timeZone;

    public String getInformation() {
        return information;
    }

    public void setInformation(String information) {
        this.information = information;
    }

    public String getSymbol() {
        return symbol;
    }

    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }

    public String getLastRefreshed() {
        return lastRefreshed;
    }

    public void setLastRefreshed(String lastRefreshed) {
        this.lastRefreshed = lastRefreshed;
    }

    public String getOutputSize() {
        return outputSize;
    }

    public void setOutputSize(String outputSize) {
        this.outputSize = outputSize;
    }

    public String getTimeZone() {
        return timeZone;
    }

    public void setTimeZone(String timeZone) {
        this.timeZone = timeZone;
    }

    @Override
    public String toString() {
        return "Metadata{" +
                "information='" + information + ''' +
                ", symbol='" + symbol + ''' +
                ", lastRefreshed='" + lastRefreshed + ''' +
                ", outputSize='" + outputSize + ''' +
                ", timeZone='" + timeZone + ''' +
                '}';
    }
}

class Daily {
    @JsonProperty("1. open")
    private BigDecimal open;

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

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

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

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

    public BigDecimal getOpen() {
        return open;
    }

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

    public BigDecimal getHigh() {
        return high;
    }

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

    public BigDecimal getLow() {
        return low;
    }

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

    public BigDecimal getClose() {
        return close;
    }

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

    public BigDecimal getVolume() {
        return volume;
    }

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

    @Override
    public String toString() {
        return "Daily{" +
                "open=" + open +
                ", high=" + high +
                ", low=" + low +
                ", close=" + close +
                ", volume=" + volume +
                '}';
    }
}

Example usage:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.math.BigDecimal;
import java.util.Map;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper();

        System.out.println(mapper.readValue(jsonFile, DailySeries.class));
    }
}

Above code works:

metadata=Metadata{information='Daily Prices (open, high, low, close) and Volumes', symbol='MSFT', lastRefreshed='2019-02-15', outputSize='Compact', timeZone='US/Eastern'}
2019-02-15 = Daily{open=107.9100, high=108.3000, low=107.3624, close=108.2200, volume=26606886}
2019-02-14 = Daily{open=106.3100, high=107.2900, low=105.6600, close=106.9000, volume=21784703}
2019-02-13 = Daily{open=107.5000, high=107.7800, low=106.7100, close=106.8100, volume=18394869}
2019-02-12 = Daily{open=106.1400, high=107.1400, low=105.4800, close=106.8900, volume=25056595}
2019-02-11 = Daily{open=106.2000, high=106.5800, low=104.9650, close=105.2500, volume=18914123}
2019-02-08 = Daily{open=104.3900, high=105.7800, low=104.2603, close=105.6700, volume=21461093}
2019-02-07 = Daily{open=105.1850, high=105.5900, low=104.2900, close=105.2700, volume=29760697}
2019-02-06 = Daily{open=107.0000, high=107.0000, low=105.5300, close=106.0300, volume=20609759}
2019-02-05 = Daily{open=106.0600, high=107.2700, low=105.9600, close=107.2200, volume=27325365}
2019-02-04 = Daily{open=102.8700, high=105.8000, low=102.7700, close=105.7400, volume=31315282}
2019-02-01 = Daily{open=103.7750, high=104.0999, low=102.3500, close=102.7800, volume=35535690}
2019-01-31 = Daily{open=103.8000, high=105.2200, low=103.1800, close=104.4300, volume=55636391}
2019-01-30 = Daily{open=104.6200, high=106.3800, low=104.3300, close=106.3800, volume=49471866}
2019-01-29 = Daily{open=104.8800, high=104.9700, low=102.1700, close=102.9400, volume=31490547}
2019-01-28 = Daily{open=106.2600, high=106.4800, low=104.6600, close=105.0800, volume=29476719}
2019-01-25 = Daily{open=107.2400, high=107.8800, low=106.5900, close=107.1700, volume=31218193}
2019-01-24 = Daily{open=106.8600, high=107.0000, low=105.3400, close=106.2000, volume=23164838}
2019-01-23 = Daily{open=106.1200, high=107.0400, low=105.3400, close=106.7100, volume=25874294}
2019-01-22 = Daily{open=106.7500, high=107.1000, low=104.8600, close=105.6800, volume=32371253}
2019-01-18 = Daily{open=107.4600, high=107.9000, low=105.9100, close=107.7100, volume=37427587}
2019-01-17 = Daily{open=105.0000, high=106.6250, low=104.7600, close=106.1200, volume=28393015}
2019-01-16 = Daily{open=105.2600, high=106.2550, low=104.9600, close=105.3800, volume=29853865}
2019-01-15 = Daily{open=102.5100, high=105.0500, low=101.8800, close=105.0100, volume=31587616}
2019-01-14 = Daily{open=101.9000, high=102.8716, low=101.2600, close=102.0500, volume=28437079}
2019-01-11 = Daily{open=103.1900, high=103.4400, low=101.6400, close=102.8000, volume=28314202}
2019-01-10 = Daily{open=103.2200, high=103.7500, low=102.3800, close=103.6000, volume=30067556}
2019-01-09 = Daily{open=103.8600, high=104.8800, low=103.2445, close=104.2700, volume=32280840}
2019-01-08 = Daily{open=103.0400, high=103.9700, low=101.7134, close=102.8000, volume=31514415}
2019-01-07 = Daily{open=101.6400, high=103.2681, low=100.9800, close=102.0600, volume=35656136}
2019-01-04 = Daily{open=99.7200, high=102.5100, low=98.9300, close=101.9300, volume=44060620}
2019-01-03 = Daily{open=100.1000, high=100.1850, low=97.2000, close=97.4000, volume=42578410}
2019-01-02 = Daily{open=99.5500, high=101.7500, low=98.9400, close=101.1200, volume=35329345}
2018-12-31 = Daily{open=101.2900, high=102.4000, low=100.4400, close=101.5700, volume=33173765}
2018-12-28 = Daily{open=102.0900, high=102.4100, low=99.5200, close=100.3900, volume=38169312}
2018-12-27 = Daily{open=99.3000, high=101.1900, low=96.4000, close=101.1800, volume=49498509}
2018-12-26 = Daily{open=95.1400, high=100.6900, low=93.9600, close=100.5600, volume=51634793}
2018-12-24 = Daily{open=97.6800, high=97.9700, low=93.9800, close=94.1300, volume=43935192}
2018-12-21 = Daily{open=101.6300, high=103.0000, low=97.4600, close=98.2300, volume=111242070}
2018-12-20 = Daily{open=103.0500, high=104.3100, low=98.7800, close=101.5100, volume=70334184}
2018-12-19 = Daily{open=103.6500, high=106.8800, low=101.3500, close=103.6900, volume=68198186}
2018-12-18 = Daily{open=103.7500, high=104.5100, low=102.5200, close=103.9700, volume=49319196}
2018-12-17 = Daily{open=105.4100, high=105.8000, low=101.7100, close=102.8900, volume=56957314}
2018-12-14 = Daily{open=108.2500, high=109.2600, low=105.5000, close=106.0300, volume=47043136}
2018-12-13 = Daily{open=109.5800, high=110.8700, low=108.6300, close=109.4500, volume=31333362}
2018-12-12 = Daily{open=110.8900, high=111.2700, low=109.0400, close=109.0800, volume=36183020}
2018-12-11 = Daily{open=109.8000, high=110.9500, low=107.4400, close=108.5900, volume=42381947}
2018-12-10 = Daily{open=104.8000, high=107.9800, low=103.8900, close=107.5900, volume=40801525}
2018-12-07 = Daily{open=108.3800, high=109.4500, low=104.3000, close=104.8200, volume=45044937}
2018-12-06 = Daily{open=105.8200, high=109.2400, low=105.0000, close=109.1900, volume=49107431}
2018-12-04 = Daily{open=111.9400, high=112.6373, low=108.2115, close=108.5200, volume=45196984}
2018-12-03 = Daily{open=113.0000, high=113.4200, low=110.7300, close=112.0900, volume=34732772}
2018-11-30 = Daily{open=110.7000, high=110.9700, low=109.3600, close=110.8900, volume=33665624}
2018-11-29 = Daily{open=110.3300, high=111.1150, low=109.0300, close=110.1900, volume=28123195}
2018-11-28 = Daily{open=107.8900, high=111.3300, low=107.8600, close=111.1200, volume=46788461}
2018-11-27 = Daily{open=106.2700, high=107.3300, low=105.3600, close=107.1400, volume=29124486}
2018-11-26 = Daily{open=104.7900, high=106.6300, low=104.5800, close=106.4700, volume=32336165}
2018-11-23 = Daily{open=102.1700, high=103.8099, low=102.0000, close=103.0700, volume=13823099}
2018-11-21 = Daily{open=103.6000, high=104.4300, low=102.2400, close=103.1100, volume=28130621}
2018-11-20 = Daily{open=101.8000, high=102.9700, low=99.3528, close=101.7100, volume=64052457}
2018-11-19 = Daily{open=108.2700, high=108.5600, low=103.5500, close=104.6200, volume=44773899}
2018-11-16 = Daily{open=107.0800, high=108.8800, low=106.8000, close=108.2900, volume=33502121}
2018-11-15 = Daily{open=104.9900, high=107.8000, low=103.9100, close=107.2800, volume=38505165}
2018-11-14 = Daily{open=108.1000, high=108.2600, low=104.4700, close=104.9700, volume=39495141}
2018-11-13 = Daily{open=107.5500, high=108.7400, low=106.6400, close=106.9400, volume=35374583}
2018-11-12 = Daily{open=109.4200, high=109.9600, low=106.1000, close=106.8700, volume=33621807}
2018-11-09 = Daily{open=110.8500, high=111.4500, low=108.7600, close=109.5700, volume=32039223}
2018-11-08 = Daily{open=111.8000, high=112.2100, low=110.9100, close=111.7500, volume=25644105}
2018-11-07 = Daily{open=109.4400, high=112.2400, low=109.4000, close=111.9600, volume=37901704}
2018-11-06 = Daily{open=107.3800, high=108.8400, low=106.2800, close=107.7200, volume=24340248}
2018-11-05 = Daily{open=106.3700, high=107.7400, low=105.9000, close=107.5100, volume=27922144}
2018-11-02 = Daily{open=106.4800, high=107.3200, low=104.9750, close=106.1600, volume=37680194}
2018-11-01 = Daily{open=107.0500, high=107.3200, low=105.5300, close=105.9200, volume=33384201}
2018-10-31 = Daily{open=105.4350, high=108.1400, low=105.3900, close=106.8100, volume=51062383}
2018-10-30 = Daily{open=103.6600, high=104.3800, low=100.1100, close=103.7300, volume=65350878}
2018-10-29 = Daily{open=108.1050, high=108.7000, low=101.6300, close=103.8500, volume=55162001}
2018-10-26 = Daily{open=105.6900, high=108.7500, low=104.7600, close=106.9600, volume=55523104}
2018-10-25 = Daily{open=106.5500, high=109.2700, low=106.1500, close=108.3000, volume=61646819}
2018-10-24 = Daily{open=108.4100, high=108.4900, low=101.5901, close=102.3200, volume=63897759}
2018-10-23 = Daily{open=107.7700, high=108.9700, low=105.1100, close=108.1000, volume=43770429}
2018-10-22 = Daily{open=109.3200, high=110.5400, low=108.2400, close=109.6300, volume=26545607}
2018-10-19 = Daily{open=108.9300, high=110.8600, low=108.2100, close=108.6600, volume=32785475}
2018-10-18 = Daily{open=110.1000, high=110.5300, low=107.8300, close=108.5000, volume=32506192}
2018-10-17 = Daily{open=111.6800, high=111.8100, low=109.5482, close=110.7100, volume=26548243}
2018-10-16 = Daily{open=109.5400, high=111.4100, low=108.9500, close=111.0000, volume=31610164}
2018-10-15 = Daily{open=108.9100, high=109.4800, low=106.9468, close=107.6000, volume=32068103}
2018-10-12 = Daily{open=109.0100, high=111.2400, low=107.1200, close=109.5700, volume=47742109}
2018-10-11 = Daily{open=105.3500, high=108.9300, low=104.2000, close=105.9100, volume=63904282}
2018-10-10 = Daily{open=111.2400, high=111.5000, low=105.7900, close=106.1600, volume=61376300}
2018-10-09 = Daily{open=111.1400, high=113.0800, low=110.8000, close=112.2600, volume=26198594}
2018-10-08 = Daily{open=111.6600, high=112.0300, low=109.3400, close=110.8500, volume=29640588}
2018-10-05 = Daily{open=112.6300, high=113.1700, low=110.6400, close=112.1300, volume=29068859}
2018-10-04 = Daily{open=114.6100, high=114.7588, low=111.6300, close=112.7900, volume=34821717}
2018-10-03 = Daily{open=115.4200, high=116.1800, low=114.9300, close=115.1700, volume=16648018}
2018-10-02 = Daily{open=115.3000, high=115.8400, low=114.4400, close=115.1500, volume=20787239}
2018-10-01 = Daily{open=114.7500, high=115.6800, low=114.7300, close=115.6100, volume=18883079}
2018-09-28 = Daily{open=114.1900, high=114.5700, low=113.6800, close=114.3700, volume=21647811}
2018-09-27 = Daily{open=114.7800, high=114.9100, low=114.2000, close=114.4100, volume=19091299}
2018-09-26 = Daily{open=114.4700, high=115.0550, low=113.7400, close=113.9800, volume=19352025}
2018-09-25 = Daily{open=114.8000, high=115.1000, low=113.7500, close=114.4500, volume=22668014}
2018-09-24 = Daily{open=113.0300, high=114.9000, low=112.2175, close=114.6700, volume=27334460}

Above code was tested using Jackson in version 2.9.8

Advertisement