简体   繁体   English

将 JSON 映射到 POJO 时获取空值

[英]Getting null values while mapping a JSON to POJO

I am trying to map a JSON to POJO using Jackson.我正在尝试使用 Jackson 将 JSON 映射到 POJO。 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.但是,由于此 JSON 包含对象的嵌套映射,因此当我将其反序列化为 POJO 时,时间序列信息不会转换为 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.似乎 Jackson 无法匹配 TimeSeries 类中的字段。 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这是 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现在,为了映射这个 JSON,我创建了这些 POJO

@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.这是使用 Jackson 反序列化 JSON 的代码。

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这是 TimeSeries 类的代码

@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 + "]";
    }

}

In this particular example you do not need to use @JsonAnyGetter and @JsonAnySetter annotations.在此特定示例中,您不需要使用@JsonAnyGetter@JsonAnySetter注释。 Just create a Map<String, TimeSeriesInfo> property and it should work without a problem.只需创建一个Map<String, TimeSeriesInfo>属性,它应该可以正常工作。 Also, I propose to use BigDecimal instead of Double and Long .另外,我建议使用BigDecimal而不是DoubleLong Below you can find whole POJO s structure which works properly without any extra annotations:您可以在下面找到整个POJO的结构,它可以正常工作而无需任何额外的注释:

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以上代码在2.9.8版本中使用Jackson进行了测试

michal ziober - thanks for great answer! michal ziober - 感谢您的出色回答! made my own version for kotlin- for who ever wants (:为 kotlin 制作了我自己的版本 - 谁想要(:

data class DailyStock(
    @SerializedName("Meta Data")
    val metaData: MetaData,
    @SerializedName("Time Series (Daily)")
    val timeSeriesDaily: Map<String, TimeSeriesDaily>
)

data class MetaData(
    @SerializedName("1. Information")
    val information: String,
    @SerializedName("3. Last Refreshed")
    val lastRefreshed: String,
    @SerializedName("4. Output Size")
    val outputSize: String,
    @SerializedName("2. Symbol")
    val symbol: String,
    @SerializedName("5. Time Zone")
    val timeZone: String
)
data class TimeSeriesDaily (
    @SerializedName("1. open")
        val `open`: BigDecimal,
    @SerializedName("2. high")
        val high: BigDecimal,
    @SerializedName("3. low")
        val low: BigDecimal,
    @SerializedName("4. close")
        val close: BigDecimal,
    @SerializedName("5. adjusted close")
        val adjustedClose: BigDecimal,
    @SerializedName("6. volume")
        val volume: BigDecimal,
    @SerializedName("7. dividend amount")
        val dividendAmount: BigDecimal,
    @SerializedName("8. split coefficient")
        val splitCoefficient: BigDecimal,
    ){

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM