Android GSON POJO可选字段解析

时间:2015-12-18 16:03:02

标签: java android json gson

好的,所以我正在使用api,因为一个JSON参数可以返回两种不同的类型。所以我可以从服务器接收JSON对象或字符串。我对Android开发很陌生,所以如果有人可以通过代码示例向我解释如何处理这个问题。

json回复示例{视频:"视频ID"}或{视频:{id:"视频ID",...额外数据}}。我查看了自定义解串器,但无法找到易于遵循的示例。必须有一种简单的方法来解决我的问题。目前我收到错误"预期字符串但发现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;
//        }

}

和劈开的部分

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

2 个答案:

答案 0 :(得分:1)

对不起,花了这么长时间:

如果必须将JSON映射到对象,最好的办法是修复JSON。

尝试使用以下代码清理JSON:

public static String cleanJson(String json) {
    int videoPos = json.indexOf("video");
    if(videoPos == -1) {
        return json; //return, no video here
    }
    boolean isObject = false;

    int objectBegin = -1;
    String cleanedJson = json.replaceAll("\\\"", "\\\\");
    for(int i = videoPos; i < cleanedJson.length(); i++) {
        if(cleanedJson.charAt(i) == '"') {
            System.out.println("string");
            return json; // its a string anyway
        }
        if(cleanedJson.charAt(i) == '{') {
            //its an object
            // i now is the position beginning the object
            objectBegin = i;
        }
    } //replace " with space
    if(objectBegin == -1) {// we did not find any { or " it is a string
        return json;
    }
    boolean inString = false;
    int objectEnd = -1;
    for(int i = objectBegin; i < cleanedJson.length(); i++) {
        //looking for the end of the object;
        if(cleanedJson.charAt(i) == '"') inString = !inString;
        if(cleanedJson.charAt(i) == '}') {
            objectEnd = i;
            break;
        }
    }
    if(objectEnd != -1) {
        String start = json.substring(0,objectBegin);
        String videoPart = json.substring(objectBegin, objectEnd+1);
        String end = json.substring(objectEnd+1);
        // now we want to get the id
        String newVideoPart = "";
        int idStart = videoPart.indexOf("id");
        int idStringStart = -1;
        int idStringEnd = -1;

        for(int i = idStart; i < videoPart.length(); i++) {
            if(videoPart.charAt(i) == '"') {
                if(idStringStart == -1) {
                    idStringStart = i;
                } else {
                    idStringEnd = i;
                    break;
                }
            }
        }
        if(idStringStart != -1 && idStringEnd != -1) {
            newVideoPart = videoPart.substring(idStringStart, idStringEnd+1);
        }

        return start+newVideoPart+end;
    }
    return json;
}

使用这两个测试jsons:

System.out.println(cleanJson("{video:\"1234\"}"));
System.out.println(cleanJson("{video:{id:\"2345\", name=\"test\"}}"));

试试这样:

notficationsList = (List<MyNotification>) gson.fromJson(cleanJson(jsonString), listType);

答案 1 :(得分:0)

好的,所以我选择的解决方案是我编写了自己的类型适配器,gson允许你使用

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 && in.getPath().contains(".video")){
       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);
}
}

然后在我的活动数据管理器(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);
}

似乎要做的工作