使用GSON将JSON转换为嵌套对象(通用对象)

时间:2014-02-24 08:55:33

标签: android json gson

我想使用Gson为解析JSON创建一个解析器。

第一个IParser.java

public interface IParser<T> {
    public T parse(String json);
}

第二个Parser.java

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

public class Parser<T> implements IParser<T> {

    @Override
    public T parse(String json) {
        GsonBuilder builder = new GsonBuilder();
        Gson gson = builder.enableComplexMapKeySerialization().create();
        MyJson<T> jsonParsed = gson.fromJson(json, new TypeToken<MyJson<T>>() {
        }.getType());

        System.out.println(jsonParsed.toString());
        return null;
    }

}

第三个MyJson.java

public class MyJson<T> {
    private int status;
    private T data;

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

User.java

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private long usrId;
    private String usrNm;
    private String usrPwd;
    private String usrEml;

    public User() {

    }

    public long getUsrId() {
        return usrId;
    }

    public void setUsrId(long usrId) {
        this.usrId = usrId;
    }

    public String getUsrNm() {
        return usrNm;
    }

    public void setUsrNm(String usrNm) {
        this.usrNm = usrNm;
    }

    public String getUsrPwd() {
        return usrPwd;
    }

    public void setUsrPwd(String usrPwd) {
        this.usrPwd = usrPwd;
    }

    public String getUsrEml() {
        return usrEml;
    }

    public void setUsrEml(String usrEml) {
        this.usrEml = usrEml;
    }

    @Override
    public String toString() {
        return "User [usrId=" + usrId + ", usrNm=" + usrNm + ", usrPwd="
                + usrPwd + ", usrEml=" + usrEml + "]";
    }
}

我的JSON字符串:

{
    status: 200,
    data: {
        usrId: 2,
        usrNm: "John",
        usrPwd: "123",
        usrEml: "john@test.com"
    }
}

我想在jsonString上解析为MyJson<T>对象。

我做:

MyJson<T> jsonParsed = gson.fromJson(json, new TypeToken<MyJson<T>>() {
            }.getType());

=&GT; GsonUser中的MyJson解析为LinkedTreeMap

意思是:Object data = jsonParsed.getData(); =&gt; LinkedTreeMap

的数据实例

我想要的是:User

的数据实例

但是,当我尝试:

MyJson<User> jsonParsed = gson.fromJson(json, new TypeToken<MyJson<User>>() {
            }.getType());

gson工作正常。

所以我想知道我怎么能用第一种方式使gson正常工作(使用T而不是User),因为我想用 Parser

来解析其他对象

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

@Override
public T parse(String json, Type type) {
    GsonBuilder builder = new GsonBuilder();
    Gson gson = builder.enableComplexMapKeySerialization().create();
    MyJson<T> jsonParsed = gson.fromJson(json, type);

    System.out.println(jsonParsed.toString());
    return null;
}

使用:

User user = myJson.parse(jsonString, new TypeToken<User>() {
        }.getType());

答案 1 :(得分:2)

正如其他人所指出的那样,问题是TypeToken必须用所有具体类型进行实例化(即不用任何T参数化)。所以你需要调用者为你实例化TypeToken(&#34;你&#34;这里是Parser类。)

John接受的答案是有效的(如果你忽略它返回null并打印结果的事实),但我认为强制执行Type参数更好与返回类型的兼容性,如下所示:

public T parse(String json, TypeToken<MyJson<T>> typeToken) {
    MyJson<T> deserializedMyJson = gson.fromJson(json, typeToken.getType());
    return deserializedMyJson.getData();
}

它会在编译时强制执行对parse()的任何调用都传递正确的TypeToken,以便类似

A a = parser.parse(jsonString, new TypeToken<MyJson<B>>(){});  // incorrect

将在编译时失败,而类似这样的事情(假设parse()方法将Type作为参数):

A a = parser.parse(jsonString, new TypeToken<MyJson<B>>(){}.getType());  // incorrect too, but will compile

只会在运行时失败(尝试将B执行的parse()结果转换为a类型的A变量时。