Vic J Vic J - 4 years ago 555
Java Question

Android GSON POJO optional field parsing

Ok so heres the thing I am working with an api that for one JSON parameter can return two different types. So I can receive from the server either a JSON Object or a String. I'm pretty new to Android development so if someone could explain to me with maybe a code example how I can handle that problem.

Example json responses {video:"ID OF VIDEO"} or {video:{id:"ID OF VIDEO",...extra data}}. I had a look at custom deserialisers but can't find an example that is easy to follow. There must be a simple way of solving my problem. Currently I receive error "Expected string but found BEGIN OBJECT"

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class MyNotification {
@SerializedName("_id")
@Expose
private String Id;
@SerializedName("comment")
@Expose
private String comment;
@SerializedName("createdAt")
@Expose
private String createdAt;
@SerializedName("message")
@Expose
private String message;
@SerializedName("read")
@Expose
private Boolean read;
@SerializedName("recipient")
@Expose
private String recipient;
@SerializedName("sender")
@Expose
private User sender;
@SerializedName("type")
@Expose
private String type;
// @SerializedName("video")
// @Expose
// private String video;

/**
*
* @return
* The Id
*/
public String getId() {
return Id;
}

/**
*
* @param Id
* The _id
*/
public void setId(String Id) {
this.Id = Id;
}

/**
*
* @return
* The comment
*/
public String getComment() {
return comment;
}

/**
*
* @param comment
* The comment
*/
public void setComment(String comment) {
this.comment = comment;
}

/**
*
* @return
* The createdAt
*/
public String getCreatedAt() {
return createdAt;
}

/**
*
* @param createdAt
* The createdAt
*/
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}

/**
*
* @return
* The message
*/
public String getMessage() {
return message;
}

/**
*
* @param message
* The message
*/
public void setMessage(String message) {
this.message = message;
}

/**
*
* @return
* The read
*/
public Boolean getRead() {
return read;
}

/**
*
* @param read
* The read
*/
public void setRead(Boolean read) {
this.read = read;
}

/**
*
* @return
* The recipient
*/
public String getRecipient() {
return recipient;
}

/**
*
* @param recipient
* The recipient
*/
public void setRecipient(String recipient) {
this.recipient = recipient;
}

/**
*
* @return
* The sender
*/
public User getSender() {
return sender;
}

/**
*
* @param sender
* The sender
*/
public void setSender(User sender) {
this.sender = sender;
}

/**
*
* @return
* The type
*/
public String getType() {
return type;
}

/**
*
* @param type
* The type
*/
public void setType(String type) {
this.type = type;
}

// /**
// *
// * @return
// * The video
// */
// public String getVideo() {
// return video;
// }
//
// /**
// *
// * @param video
// * The video
// */
// public void setVideo(String video) {
// this.video = video;
// }

}


and the part that craps out

Gson gson = new Gson();
String jsonString = String.valueOf(dataset);
Type listType = new TypeToken<List<MyNotification>>(){}.getType();
notficationsList = (List<MyNotification>) gson.fromJson(jsonString, listType);

Answer Source

Ok so the solution I went with I wrote my own type adapter that gson allow you to use

public class Helper_StringAdapter extends TypeAdapter<String>{
@Override
public String read(com.google.gson.stream.JsonReader in) throws IOException {
   if(in.peek() == JsonToken.NULL){
       in.nextNull();
       return null;
   }else if(in.peek() == JsonToken.BEGIN_OBJECT){
       L.e("VIDEO IS AN OBJECT!");
       String userId = readAndReturnVideoId(in);
       return userId;
   }else{
       return in.nextString();
   }
}

private String readAndReturnVideoId(com.google.gson.stream.JsonReader reader) throws IOException{
    String id = "";
    reader.beginObject();
    while(reader.hasNext()){
        String name = reader.nextName();
        if(name.equals("_id")){
            id = reader.nextString();
        }else{
            reader.skipValue();
        }
    }
    reader.endObject();
    L.e("READ ID RETURNED"+id);
    return id;
}

@Override
public void write(com.google.gson.stream.JsonWriter out, String value) throws IOException {
    L.e("TEST "+out);
}
}

Then in my activity data manager (Recyclerview Adapter)

public void updateData (JSONArray dataset) {
    GsonBuilder gsonb = new GsonBuilder();
    gsonb.registerTypeAdapter(String.class,new Helper_StringAdapter());
    Gson gson = gsonb.create();

    String jsonString = String.valueOf(dataset);
    Type listType = new TypeToken<List<FrameNotification>>(){}.getType();
    notficationsList = (List<FrameNotification>) gson.fromJson(jsonString, listType);
}

Seems to do the job

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download