1
votes

I'm trying to deserialize json from worldbank.com to a pojo without any success. The json looks like: [{"page":1,"pages":7,"per_page":"50","total":304},[{"id":"ABW","iso2Code":"AW","name":"Aruba","region":{"id":"LCN","value":"Latin America & Caribbean "},

and can be found via: http://api.worldbank.org/countries/?format=json

and im running into problems with gson telling me: WorldBankDemo: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 52 path $[1]

Any clues as to how i can solve this? Preferably without changing from gson since that is the lib used by the networking lib I'm using (retrofit)

 WorldBankDataService service = ServiceFactory.createRetrofitService(WorldBankDataService.class, WorldBankDataService.SERVICE_ENDPOINT);
        service.getCountries()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<WorldBank[]>() {
                    @Override
                    public final void onCompleted() {
                        // do nothing
                    }

                    @Override
                    public final void onError(Throwable e) {
                        Log.e("WorldBankDemo", e.getMessage());
                    }

                    @Override
                    public final void onNext(WorldBank[] response) {
                        Log.d("TAG", "resp: "+response);
                        //mCardAdapter.addData(response);
                    }
                });


public class ServiceFactory {
/**
 * Creates a retrofit service from an arbitrary class (clazz)
 * @param clazz Java interface of the retrofit service
 * @param endPoint REST endpoint url
 * @return retrofit service with defined endpoint
 */
public static <T> T createRetrofitService(final Class<T> clazz, final 
String endPoint) {
        final RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(endPoint)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
        T service = restAdapter.create(clazz);

        return service;
    }
}

public class WorldBank {
    int page;
    int pages;
    String per_page;
    int total;
    //Country[] countrys;
}
5
put your code here - Vishal Patoliya ツ
Show your code.... - ElefantPhace
put your WorldBankDemo class code here? - Rahul Sharma
JSON response which is produced by api, is invalid. it is like [{...}]], it must be {...} - Burak Cakir
the response from the api is valid, but not ideal for gson parsing. - Carl-Emil Kjellstrand

5 Answers

2
votes

JSON is not constructed well(especially for auto parsing), Array can contain objects or arrays but not both at same level, in the above JSON structure it starts with Array in that the first element is an object and second element is an array, so this kind of JSON structure is not recommended for auto parsing, if at all you want to continue with same JSON response you can go for manual parsing or change response structure.

0
votes

It's actually a JSON array. so you can't use class. try this:

YourPojo[] objects = gson.fromJson(jsonString, YourPojo[].class)

works like a charm

0
votes

try this way

Gson gson = new Gson();
String jsonOutput = "Your JSON String";
Type listType = new TypeToken<List<ApiResponse>>(){}.getType();
List<ApiResponse> posts = (List<ApiResponse>) gson.fromJson(jsonOutput, listType);

and ApiResponse is like

public  class ApiResponse{
WorldBank object1;
ArrayList<Country> objects2;
}

I haven't try this on my end, but it will be similar like that.

0
votes

You can use gson to customize using this dependency

compile 'org.immutables:gson:2.3.1'

But slightly different way while invoking the rest client

For instance .If we have to get a list of countries declare an interface

public interface GetAllAPI {
 @GET("/all")
   List<Country> getCountries();
 }

Now rest client will be

public List<Country> GetAllCountries() {

   Gson gson = new GsonBuilder().create();

   RestAdapter restAdapter = new RestAdapter.Builder()
   .setEndpoint(service_url)
   .setConverter(new GsonConverter(gson))
   .build();

   GetAllAPI service = restAdapter.create(GetAllAPI.class);

   List<Country> countrylist = service.getCountries();

   return countrylist;
 }

Getting the results from API will be

List<Country> countrylist = service.getCountries();

You have to customize this implementation for specific requirement. This is an idea how to implement Gson with Retrofit

Go through this for more clarification

0
votes

Decided to give up and use another api, the world bank api just sucks :(