D
D
Daniil Miroshnichenko2015-06-10 16:25:56
Java
Daniil Miroshnichenko, 2015-06-10 16:25:56

How to parse complex json files using Gson and TypeAdapterFactory?

Hello.
I am developing a rest application on Android. I use Retrofit + Gson + RxJava.
The following responses come from the server:

{"error":false,"json":true,"body":{...JSON object...}}

You should always parse what's in body.
I tried to create my own TypeAdapterFactory and this is what happened:
public class ItemTypeAdapterFactory implements TypeAdapterFactory {

    public static final String BODY = "body";

    @Override
    public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
        final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
        final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);

        return new TypeAdapter<T>() {

            public void write(JsonWriter out, T value) throws IOException {
                delegate.write(out, value);
                Logger.d(this, "dami");
            }

            public T read(JsonReader in) throws IOException {
                JsonElement jsonElement = elementAdapter.read(in);
                if (jsonElement.isJsonObject()) {
                    JsonObject jsonObject = jsonElement.getAsJsonObject();
                    if (jsonObject.has(BODY) && jsonObject.get(BODY).isJsonObject()) {
                        jsonElement = jsonObject.get(BODY);
                    }
                }

                return delegate.fromJsonTree(jsonElement);
            }
        }.nullSafe();
    }

Next, we use this in creating the retrofit service:
public abstract class AbstractApiService {
    private RestAdapter restAdapter;

    public AbstractApiService() {
        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new ItemTypeAdapterFactory())
                .create();

        restAdapter = new RestAdapter.Builder()
                .setEndpoint(ApiConf.API_URL)
                .setConverter(new GsonConverter(gson))
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
    }

    protected <T> T create(Class<T> service) {
        return restAdapter.create(service);
    }
}

The result is that it never even gets into the create method of the ItemTypeAdapterFactory and, apparently, Gson continues to use its standard implementation.
Help me please.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
dmolokanov, 2015-06-11
@dmolokanov

If I'm not mistaken, in order for parsing to work, you must explicitly tell GSON what type of object to parse. Otherwise, he does not know why he should parse with the specified parser. But I really didn't use retrofit.

Similar questions
K
KhanTengri2011-06-17 23:56:41
Get from a remote web page?</a> <a class="content__item-button" href="/q/get-title-from-a-remote-web-page"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" class=""> <path fill-rule="evenodd" d="M15 14a1.002 1.002 0 01-1.703.71h-.004l-.003-.01-1.704-1.7H3c-1.104 0-2-.9-2-2V3c0-1.1.896-2 2-2h10c1.104 0 2 .9 2 2v11zM5 6c.552 0 1 .45 1 1s-.448 1-1 1-1-.45-1-1 .448-1 1-1zm3 0c.552 0 1 .45 1 1s-.448 1-1 1-1-.45-1-1 .448-1 1-1zm3 0c.552 0 1 .45 1 1s-.448 1-1 1-1-.45-1-1 .448-1 1-1z"></path> </svg> <span class="dark">6</span><span class="dn">Reply</span> </a> </div> </div><div class="content__item"> <div class="content__item-img name-color-I"> <span>I</span></div> <div class="content__item-content"> <div class="content__item-row"> <a href="/q/hibernate-orm-mapping-issue">im_berzki</a><span>2011-06-19 12:13:36</span></div> <a class="content__item-title similar" href="/q/hibernate-orm-mapping-issue">Hibernate ORM: Mapping issue</a> <a class="content__item-button" href="/q/hibernate-orm-mapping-issue"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" class=""> <path fill-rule="evenodd" d="M15 14a1.002 1.002 0 01-1.703.71h-.004l-.003-.01-1.704-1.7H3c-1.104 0-2-.9-2-2V3c0-1.1.896-2 2-2h10c1.104 0 2 .9 2 2v11zM5 6c.552 0 1 .45 1 1s-.448 1-1 1-1-.45-1-1 .448-1 1-1zm3 0c.552 0 1 .45 1 1s-.448 1-1 1-1-.45-1-1 .448-1 1-1zm3 0c.552 0 1 .45 1 1s-.448 1-1 1-1-.45-1-1 .448-1 1-1z"></path> </svg> <span class="dark">6</span><span class="dn">Reply</span> </a> </div> </div> </div> </div> </div> <div class="content find"> <p class="find__p">Didn't find what you were looking for?</p><a class="find__btn" href="#!">Ask your question</a> </div> <div class="find sm"> <p class="find__title">Ask a Question </p> <form class="find__form" action="#!"> <input class="find__input" type="text" placeholder="Ask your question here"> <button class="find__btn" type="submit"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 16 16" class="nBqR1"><path fill-rule="evenodd" d="M12.696 7.256L9.657 4.217a1 1 0 00-1.415 1.414l1.344 1.344H3.949a1.001 1.001 0 000 2h5.637l-1.344 1.343a1.002 1.002 0 000 1.415c.391.39 1.024.39 1.415 0l3.039-3.04A.993.993 0 0013 7.975a.997.997 0 00-.293-.708l-.011-.011z"></path></svg></button> </form> <p class="find__span">731 491 924 answers to any question</p> </div> </div> <aside class="banners"> <p>banners </p> </aside> </div> </main> </div> <script src="/assets/theme/js/highlight/highlight.min.js"></script> <script src="/assets/theme/js/app.min.js?_v=20220404145216"> </script> <script>hljs.highlightAll();</script> </body> </html>