skip to Main Content

I’m using an price API that returns a nested list

{"prices":[
    [1676505600000,24307.875101631602],
    [1676592000000,23756.907281577434]
  ],
"market_caps":[
   [1676505600000,468820317786.9533],
   [1676592000000,459293697174.9459],
   [1676678400000,475194230168.09973]
  ]
}

I can’t figure out how to structure my Java Object so it’s successfully parsed.

I’ve tried

public class QueryResult {
    @SerializedName("prices")
    List<List<Prices>> listPrices;

    public List<List<Prices>> getListPrices() {
        return listPrices;
    }
}
public class Prices {
    private long timestamp;
    private double price;

    public long getTimestamp() {
        return timestamp;
    }

    public double getPrice() {
        return price;
    }
}

But it doesn’t work.

I still get the error

Error: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

Usually the items in the nested list would have a key, but in this case it doesn’t.

So I’m not quite sure how to do it here.

Edit:________________________________________________________

I’m already using Gson with retrofit

@Provides
    @Singleton
    public Retrofit provideRetrofit(OkHttpClient okHttpClient) {
        return new Retrofit.Builder()
                .baseUrl(Constants.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .client(okHttpClient)
                .build();
    }

2

Answers


  1. Need to use Gson Converter

      public class Example {
        public static void main(String[] args) {
            String json = "{"prices":[[1676505600000,24307.875101631602],[1676592000000,23756.907281577434]],"market_caps":[[1676505600000,468820317786.9533],[1676592000000,459293697174.9459],[1676678400000,475194230168.09973]]}";
    
            Gson gson = new Gson();
            Data data = gson.fromJson(json, Data.class);
    
            List<List<Double>> prices = data.prices;
            List<List<Double>> marketCaps = data.market_caps;
    
            System.out.println(prices);
            System.out.println(marketCaps);
        }
    
        private static class Data {
            private List<List<Double>> prices;
            private List<List<Double>> market_caps;
        }
    }
    
    Login or Signup to reply.
  2. Your problem is a lack of understanding of how the Gson library and Json format work. What you want to achieve in your question is not possible the way you want to do it. There is a way to do it, though, and it differs a bit from what you might expect.

    {"prices":[
        [1676505600000,24307.875101631602],
        [1676592000000,23756.907281577434]
      ],
    "market_caps":[
       [1676505600000,468820317786.9533],
       [1676592000000,459293697174.9459],
       [1676678400000,475194230168.09973]
      ]
    }
    

    Here both prices and market_caps are two-dimensional double arrays – basically, matrices – meaning they do not contain Prices objects as you expect them, but an array(or as you parse them a List) of doubles with the innerList[0] element being timestamp and innerList[1] being price.

    In order to parse them correctly your model should look like this:

    public class QueryResult {
        List<List<double>> prices;
    }
    

    And if you want to have them as objects the simple approach will require having this getter for it:

    public List<Price> getListOfPrices() {
            List<Price> result = new ArrayList<Prices>();
            for (List<double> innerList: prices){
               result.add(Price(innerList.get(0), innerList.get(1)));
            }
            return result;
        }
    

    The method above will calculate every time it is called; thus, you would want to store it somewhere.

    And if you want to utilize a converter, as @Sudhakar suggested in the answer above, which is more correct but also a bit more complicated. It is called @JsonAdapter in the context of the Gson library or GsonConverterFactory in the context of Retrofit 2.0 library.

    I don’t think it is needed, though, in your case, since the easier method is reasonably sufficient if handled correctly.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search