java jackson parse json array

2019-08-27 16:35发布

I need help with parsing, I've tried to create a different kind of model classes, but no use, please help me out here. the json looks like this:

[
  [
    1518909300000,
    "0.08815700",
    "0.08828700",
    "0.08780000",
    "0.08792900",
    "1727.93100000",
    1518910199999,
    "152.11480375",
    5118,
    "897.71600000",
    "79.04635703",
    "0"
  ],
  [
    1518910200000,
    "0.08788400",
    "0.08824200",
    "0.08766200",
    "0.08810000",
    "1789.81300000",
    1518911099999,
    "157.20177729",
    6201,
    "898.89500000",
    "78.95697080",
    "0"
  ]
]

and I'm trying to parse it using data class:

@JsonIgnoreProperties(ignoreUnknown = true)
public class KlineResponse {

    public List<Kline> getKlineList() {
        return klineList;
    }

    public List<Kline> klineList;

    public class Kline {
        @JsonProperty("4")
        Double close;

        @JsonProperty("8")
        Integer tradesNumber;

        public Double getClose() {
            return close;
        }

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

        public Integer getTradesNumber() {
            return tradesNumber;
        }

        public void setTradesNumber(Integer tradesNumber) {
            this.tradesNumber = tradesNumber;
        }
    }
}

and this line

mapper.readValue(response.getBody(), new TypeReference<List<KlineResponse>>(){})

or

mapper.readValue(response.getBody(), KlineResponse.class)

but each time the error: Can not deserialize instance of pt.settings.model.KlineResponse out of START_ARRAY token, please help

3条回答
乱世女痞
2楼-- · 2019-08-27 17:02

The core issue is that you receive an array of arrays where you expect and array of objects. Changing mapper.readValue(response.getBody(), KlineResponse.class) to mapper.readValue(response.getBody(), Object[].class) confirms it.

You have a couple of options on how to proceed:

  1. Change from Jackson to standard JSON parsing, as suggested by @cricket_007 on his answer
  2. Instead of mapping it to an object try to access the JSON differently. See @jschnasse's answer for an example.
  3. Change the format of text you parse, if you can
  4. If you can't change the format of the input then you can either
    • Create a constructor and annotate it with @JsonCreator, like instructed here
    • Parse the input as Object array and feed the parsed array into a constructor of your own
查看更多
劳资没心,怎么记你
3楼-- · 2019-08-27 17:12

Use JsonNode together with JPointer. Avoid to create a POJO and work directly on the data via JsonNode.

ObjectMapper mapper = new ObjectMapper();
JsonNode matrix = mapper.readValue(in, JsonNode.class);
matrix.forEach(array -> {
    System.out.println("Next Values:");
    System.out.println(array.at("/4").asDouble());
    System.out.println(array.at("/8").asInt());
});

Prints

Next Values:
0.087929
5118.0
Next Values:
0.0881
6201.0
查看更多
Emotional °昔
4楼-- · 2019-08-27 17:14

You don't need any java classes. There are no JSON objects to deserialize, only arrays.

In the second case, Jackson is expecting { "klineList": [] }

In the first, [{ "klineList": [] }, { "klineList": [] }]

And a Kline object is only parsable as {"4": 0.0, "8": 0 } (replace zeros with any value of same type)... So really unclear why you expected that to work given that data... The annotations are not the index of the lists.

Plus, your lists have both strings and integers, so you can only deserialize as TypeReference<List<List<Object>>>, then iterate that to parse ints, floats, or strings

I might recommend you use a standard json parser, not an objectmapper

查看更多
登录 后发表回答