2

I want to receive items using retrofit and parse them into a Java list. However, the server response is not a JSON array but a JSON object containing the items. That is why retrofit cannot just convert the response into a java list.

The response looks something like this:

{
    "4": {
        "key": "value",
        ...
    },
    "5": {
        ...
    }, 
    ...
}

Usually, I would try to receive the items like this:

@GET("items")
Call<List<Item>> getItems();

But this obviously does not work and Retrofit responds: Expected BEGIN_ARRAY but was BEGIN_OBJECT

What is my best option to convert this object into a java list using retrofit?

4
  • I faced this case once, I believe there is no way that Retrofit can fully parse the response like this, we have to catch the root object -> use GSon to convert it to String, then parse it manually. The best way: tell server guy to fix it, he did a very bad and stupid thing! Commented Aug 16, 2019 at 14:42
  • I thin the solution could be someting like in this post: stackoverflow.com/questions/37550388/… Maybe something like Call<List<Map<String, Item>>>. Try a bit arround, good luck. Commented Aug 16, 2019 at 14:45
  • @ThinkTwiceCodeOnce Thank you for the answer. I am pretty sure that the server guys at Philips will not change this. But hopefully, they will not create something like this again. Commented Aug 19, 2019 at 20:16
  • @DanielSpiess: Thank you for the link. It is similar to Fred's answer and it solves my issue. Commented Aug 19, 2019 at 20:17

2 Answers 2

2

I'd personally do this in 2 steps to avoid having to write a custom adapter for the deserialization.

I'd write the interface like:

@GET("items")
Call<Map<String, Item>> getItems();

And once you'd call the API on the response I'd just call values().

Things to take into consideration is that because the API returns a map and not a list, there's no guarantee that the order of any list you'd produce would be consistent. The json standard doesn't define any order for objects unless they're in a json array.

Sign up to request clarification or add additional context in comments.

Comments

0

When you say the response is List, the JSON should be an "ARRAY".

E.g.:

[ "a", "b" ]

or

{ 
   "xxx": [ "a", "b" ] 
}

In either case, the objects you'd want to parse into would look like:

List<String> for the first one.

Thing for the second one.

And Thing would look like:

class Thing {
   public List<String> xxx;
}

You're trying to parse this:

{
    "4": {
        "key": "value",
        ...
    },
    "5": {
        ...
    }, 
    ...
}

So based on the above information, what do you think your response looks like when parsed? (hint: you can try something like this Java POJO generator to get an idea ;)

2 Comments

Thank you for answering. I cannot change the server response. That is why I have to deal with this stupid 'object-list'.
Gotcha, I see you've already gotten an answer. I was simply teasing you to see if you could figure it out on your own (it's just a Map<> not a List<>) but glad to hear you've solved it ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.