EzDevInfo.com

moshi

A modern JSON library for Android and Java.

Get a Class literal or a Type [duplicate]

This question already has an answer here:

Is it possible to get something similar to Class<List<Data>>.class? I read you can't call .class because of how it works interanlly, so I was wondering if maybe using something similar to new ArrayList<Data>().getClass() might work? That one in particular doesn't work as the returned class is Class<? extends List<Data>> so I'm out of options, is it even possible?

Context: I'm trying to parse a List<Data> using square/moshi but the library seems to be on alpha so there is no documentation on it.


Source: (StackOverflow)

Custom converter to subclass with Moshi

I have a User class. And two subclasses. Parent and Child. I get json from my server with {"user":"..."} and need to convert it to parent or to child depending on user.type

As I understand I need to add custom converter this way:

        Moshi moshi = new Moshi.Builder()
            .add(new UserAdapter())
            .build();

Here's my implementation of UserAdapter. I know it's dummy, but it's not working even this way:

public class UserAdapter {

@FromJson
User fromJson(String userJson) {
    Moshi moshi = new Moshi.Builder().build();
    try {
        JSONObject jsonObject = new JSONObject(userJson);
        String accountType = jsonObject.getString("type");

        switch (accountType) {
            case "Child":
                JsonAdapter<Child> childJsonAdapter = moshi.adapter(Child.class);
                return childJsonAdapter.fromJson(userJson);
            case "Parent":
                JsonAdapter<Parent> parentJsonAdapter = moshi.adapter(Parent.class);
                return parentJsonAdapter.fromJson(userJson);

        }
    } catch (JSONException | IOException e) {
        e.printStackTrace();
    }

    return null;
}

@ToJson
String toJson(User user) {
    Moshi moshi = new Moshi.Builder().build();
    JsonAdapter<User> jsonAdapter = moshi.adapter(User.class);
    String toJson = jsonAdapter.toJson(user);
    return toJson;
}

First of all I get following exception with this code.

com.squareup.moshi.JsonDataException: Expected a string but was BEGIN_OBJECT at path $.user

And second, I believe there's a better way to do it. Please advice.

Upd. here's stacktrace for the error:

 com.squareup.moshi.JsonDataException: Expected a name but was BEGIN_OBJECT at path $.user
 at com.squareup.moshi.JsonReader.nextName(JsonReader.java:782)
 at com.squareup.moshi.ClassJsonAdapter.fromJson(ClassJsonAdapter.java:141)
 at com.squareup.moshi.JsonAdapter$1.fromJson(JsonAdapter.java:68)
 at com.squareup.moshi.JsonAdapter.fromJson(JsonAdapter.java:33)
 at retrofit.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:33)
 at retrofit.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:23)
 at retrofit.OkHttpCall.parseResponse(OkHttpCall.java:148)
 at retrofit.OkHttpCall.execute(OkHttpCall.java:116)
 at retrofit.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:111)
 at retrofit.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:88)
 at rx.Observable$2.call(Observable.java:162)
 at rx.Observable$2.call(Observable.java:154)
 at rx.Observable$2.call(Observable.java:162)
 at rx.Observable$2.call(Observable.java:154)
 at rx.Observable.unsafeSubscribe(Observable.java:7710)
 at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
 at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
 at java.util.concurrent.FutureTask.run(FutureTask.java:237)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
 at java.lang.Thread.run(Thread.java:818)

Source: (StackOverflow)

Advertisements

How to deseralize an int array into a custom class with Moshi?

I use Moshi to deserialize the following JSON file:

{
    "display": "Video 1",
    "isTranslated": false,
    "videoSize": [
        1920,
        1080
    ]
}

... using the following model class:

public class Stream {

    public final String display;
    public final boolean isTranslated;
    public final int[] videoSize;

    public Stream(String display,
                  boolean isTranslated,
                  int[] videoSize) {
        this.display = display;
        this.isTranslated = isTranslated;
        this.videoSize = videoSize;
    }

}

This works as expected.


Now, I would like to replace the int[] with a dedicated VideoSize class which maps the two integer values into named fields such as:

public class VideoSize {

    public final int height;
    public final int width;

    public VideoSize(int width, int height) {
        this.height = height;
        this.width = width;
    }

}

Is this possible with a custom type adapter or somehow else?


Source: (StackOverflow)