Reputation: 2805
I wanna create an parser for parse JSON by using Gson.
The first IParser.java
public interface IParser<T> {
public T parse(String json);
}
The second 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;
}
}
The third 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;
}
}
And 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 + "]";
}
}
My JSON String:
{
status: 200,
data: {
usrId: 2,
usrNm: "John",
usrPwd: "123",
usrEml: "[email protected]"
}
}
I wanna parse above jsonString to MyJson<T>
object.
I do:
MyJson<T> jsonParsed = gson.fromJson(json, new TypeToken<MyJson<T>>() {
}.getType());
=> Gson
parses my User
in MyJson
to LinkedTreeMap
It mean: Object data = jsonParsed.getData();
=> data instance of LinkedTreeMap
What I want: data instance of User
But, when I try:
MyJson<User> jsonParsed = gson.fromJson(json, new TypeToken<MyJson<User>>() {
}.getType());
gson works fine.
So I wanna know that How can I make gson works fine with the first way (use T instead of User) because I wanna parse other object by using Parser
Thanks for your help.
Upvotes: 6
Views: 4382
Reputation: 8248
As noted by others the problem is that the TypeToken
has to be instantiated with all concrete types (i.e. not parameterized with any T
). So you need the caller to instantiate the TypeToken
for you ("you" being the Parser
class here).
John's accepted answer works (if you ignore the fact that it returns null
and print the result instead), but I think it's nicer to enforce the Type
parameter compatibility with the returned type, like this:
public T parse(String json, TypeToken<MyJson<T>> typeToken) {
MyJson<T> deserializedMyJson = gson.fromJson(json, typeToken.getType());
return deserializedMyJson.getData();
}
And it will enforce at compile time that any call to parse()
is passed a correct TypeToken
, so that something like
A a = parser.parse(jsonString, new TypeToken<MyJson<B>>(){}); // incorrect
will fail at compile time, while something like this (assuming the parse()
method takes a Type
as parameter):
A a = parser.parse(jsonString, new TypeToken<MyJson<B>>(){}.getType()); // incorrect too, but will compile
will only fail at runtime (when trying to cast the B
result from parse()
execution into the a
variable of type A
).
Upvotes: 2
Reputation: 66
@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;
}
Using:
User user = myJson.parse(jsonString, new TypeToken<User>() {
}.getType());
Upvotes: 4