GSON:JSON反序列化为变量类型(列表/字符串) [英] GSON: JSON deserialization to variable type (List/String)
问题描述
在这一点上,这已经是一个老问题了,我可能已经阅读了SO上的每个相关主题.
At this point it's already an old question and I've probably read every related topic on SO.
但是要点.我需要一些建议或更正吗?
But to the point. I need some advice or correction maybe?
由于某些原因,我们产生了两种类型的可生成Json:
For some reason we have generatable Jsons of 2 types:
{"data": {"id": "value"}}
和{"data":[{"id": "value"}]}
对象和数组.还有其他参数,但在这里无关紧要.每个请求的"id"都不同.有时是userId,PortfolioId等.因此我得到"id"并将其传递给相关的var.
Object and Array. There are also other params but they doesn't matter here. "id" is differ for every request. Sometimes it's userId, portfolioId etc. So I get "id" and pass it to related var.
很长一段时间我一直在处理第一种情况.并像这样创建POJO:
For a long time I was working with the first case. And created POJO like this:
Data.class
public class Data {
@SerializedName("id")
@Expose
private String id;
public Data() {
}
public Data(String id) {
super();
this.id = id;
}
protected String getId() {
return id;
}
然后我通过 User.class 处理数据"参数.
And I adress "data" paramets via User.class.
@JsonAdapter(UserDeserializer.class)
public Data data;
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public User() {
}
public User(Data data) {
super();
this.data = data;
}
Gson gson = new Gson();
public String getPortfolioList(String tokenId, String userId) {
Call<User> call = apiRequest.getPortfolioList(userId, tokenId);
try {
User newResult = gson.fromJson(String.valueOf(call.execute().body()), User.class);
System.out.println(newResult.getData().getId());
} catch (IOException e) {
e.printStackTrace();
}
return getPortfolioId();
}
Deserializer.class
public class UserDeserializer implements JsonDeserializer<User> {
private Type listType = new TypeToken<List<Data>>(){}.getType();
@Override
public User deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
User user = new User();
JsonElement jsonElement;
if (json.isJsonArray()) {
jsonElement = json.getAsJsonArray();
user.data = context.deserialize(jsonElement,listType);
// user.data = new Gson().fromJson(jsonElement, new TypeToken<List<Data>>() {}.getType());
} else {
jsonElement = json.getAsJsonObject();
user.data = context.deserialize(jsonElement, Data.class);
// user.setData(new Gson().fromJson(jsonElement, new TypeToken<Data>() {}.getType()));
}
return user;
}
}
Baseppi类中的
Gson生成器,以防万一:
Gson builder in BaseApi class just in case:
Gson gson = new GsonBuilder().registerTypeAdapter(UserDeserializer.class, new UserDeserializer()).setLenient().create();
没有自定义反序列化和Array JSON问题,它将可以完美地工作.但是现在我必须确定我得到的数据"的确切类型.
Without custom deserialization and Array JSON issue this would work perfectly. But now I have to determine "data" 's exact type I get.
在上述情况下,我得到java.lang.ClassCastException: java.util.ArrayList cannot be cast to auto.Rest.Data
In above case I get java.lang.ClassCastException: java.util.ArrayList cannot be cast to auto.Rest.Data
我假设我必须创建另一个 Data 类(例如,将有 DataObject & DataArray ),并将每个参数描述为I以前在 Data.class 中完成了这项工作吗?我想反序列化期间做错了什么,但是我不确定tbh在哪里.
I assume I have to create another Data class (for example there will be DataObject & DataArray) and describe every parameter as I did before in Data.class to get this work? I think I do something wrong during deserialization but I'm not sure where tbh.
还是我错了,可以将 Data 用作 List ,将 Data 用作 Object 同一班?
Or am I wrong and it is possible to invoke Data as List and Data as an Object of the same class?
我已经为此工作了好几天(?),并且正在考虑使用泛型而不是Gson帮助,是的,我很绝望.因此,任何帮助表示赞赏.
I'm working on this for several days already(?) and was thinking about use generics instead of Gson help, yeah, I'm desperate. So any help appreciated.
推荐答案
如果始终使用object
或one-element array
,则可以编写自定义解串器,如下所示:
If you always have object
or one-element array
you can write custom deserialiser as below:
class OneOrElementJsonDeserializer<T> implements JsonDeserializer<T> {
@Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json instanceof JsonArray) {
final JsonArray array = (JsonArray) json;
final int size = array.size();
if (size == 0) {
return null;
}
return context.deserialize(array.get(0), typeOfT);
}
return context.deserialize(json, typeOfT);
}
}
简化后的示例模型如下:
Your example model after simplification looks like below:
class User {
@JsonAdapter(OneOrElementJsonDeserializer.class)
private Data data;
public User() {
}
public User(Data data) {
super();
this.data = data;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
@Override
public String toString() {
return "User{" +
"data=" + data +
'}';
}
}
class Data {
private String id;
protected String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "Data{" +
"id='" + id + '\'' +
'}';
}
}
示例用法:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.JsonAdapter;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
User root = gson.fromJson(new FileReader(jsonFile), User.class);
System.out.println(root);
}
}
JSON
有效负载以下的代码上方:
Above code for below JSON
payload:
{
"data": [
{
"id": "c87ca3fe85781007869b83f"
}
]
}
打印:
User{data=Data{id='c87ca3fe85781007869b83f'}}
对于object
情况JSON
有效载荷:
{
"data": {
"id": "c87ca3fe85781007869b83f"
}
}
打印:
User{data=Data{id='c87ca3fe85781007869b83f'}}
如果您的媒体资源可能包含JSON object
或multi-element array
,请参阅我对这个问题的回答
In case your property could contain JSON object
or multi-element array
see my answer to this question Mapping Json Array to Java Models. There is implemented deserialiser which handle cases like this.
这篇关于GSON:JSON反序列化为变量类型(列表/字符串)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!