使用 GSON 序列化具有通用嵌套数据对象的响应对象
Serialize response object with generic nested data object with GSON
我正在使用 Retrofit 和 GSON 进行 JSON 序列化,使用 Realm 进行存储。
我的 JSON 回复总是看起来像(简单)
{
status : 1
data: { object data }
}
所以我有元信息和一个包含结果(对象或数组)的数据根对象
现在我正在尝试为 GSON 编写自定义反序列化程序,它将结果转换为对象或对象列表。
对我来说,它只适用于静态对象类型定义,例如:
public class ResponseDeserializer implements JsonDeserializer {
@Override
public Object1 deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
{
JsonElement data = je.getAsJsonObject().get("data");
GsonBuilder gsonBuilder = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
Gson gson = gsonBuilder.create();
Object1 o1 = gson.fromJson(data, new TypeToken<Object1>() {}.getType());
return o1;
}
}
第一个问题:当我尝试从 Json 更改为泛型类型时,结果是 "com.google.gson.internal.LinkedTreeMap" 具有对象的键值对,代码:
public class ResponseDeserializer<T> implements JsonDeserializer<T> {
@Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
{
JsonElement data = je.getAsJsonObject().get("data");
GsonBuilder gsonBuilder = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
Gson gson = gsonBuilder.create();
T o = gson.fromJson(data, new TypeToken<T>() {}.getType());
return o;
}
}
第二个问题:反序列化器如何根据json结果return一个对象或一个对象列表。
现在我已经用不同的方法解决了它:
列表和对象的 2 个响应模型:
public class ApiResponse<T> {
private int success;
private String[] errors;
private String[] messages;
private T data;
}
public class ApiListResponse<T> {
private int success;
private String[] errors;
private String[] messages;
private List<T> data;
}
1 个用于响应模型的解串器
public class ResponseDeserializer<T> implements JsonDeserializer {
@Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
JsonElement data = je.getAsJsonObject().get("data");
GsonBuilder gsonBuilder = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
Gson gson = gsonBuilder.create();
T response = gson.fromJson(je, type);
return response;
}
}
现在我可以为 GSON 注册类型,例如:
gsonBuilder.registerTypeAdapter(new TypeToken<ApiResponse<Object1>>() {}.getType(), new ResponseDeserializer<ApiResponse>());
gsonBuilder.registerTypeAdapter(new TypeToken<ApiListResponse<Object1>>() {}.getType(), new ResponseDeserializer<ApiListResponse>());
现在可以正确转换以下 JSON 回复:
ApiResponse
{
"data":{
"Object1Id":"1",
"Name":"Test 1",
},
"messages":[
],
"errors":[
],
"success":"1"
}
ApiListResponse
{
"data":[{
"Object1Id":"1",
"Name":"Test 1",
},{
"Object1Id":"2",
"Name":"Test 2",
}],
"messages":[
],
"errors":[
],
"success":"1"
}
有没有更好的解决方案?
我正在使用 Retrofit 和 GSON 进行 JSON 序列化,使用 Realm 进行存储。
我的 JSON 回复总是看起来像(简单)
{
status : 1
data: { object data }
}
所以我有元信息和一个包含结果(对象或数组)的数据根对象
现在我正在尝试为 GSON 编写自定义反序列化程序,它将结果转换为对象或对象列表。
对我来说,它只适用于静态对象类型定义,例如:
public class ResponseDeserializer implements JsonDeserializer {
@Override
public Object1 deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
{
JsonElement data = je.getAsJsonObject().get("data");
GsonBuilder gsonBuilder = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
Gson gson = gsonBuilder.create();
Object1 o1 = gson.fromJson(data, new TypeToken<Object1>() {}.getType());
return o1;
}
}
第一个问题:当我尝试从 Json 更改为泛型类型时,结果是 "com.google.gson.internal.LinkedTreeMap" 具有对象的键值对,代码:
public class ResponseDeserializer<T> implements JsonDeserializer<T> {
@Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
{
JsonElement data = je.getAsJsonObject().get("data");
GsonBuilder gsonBuilder = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
Gson gson = gsonBuilder.create();
T o = gson.fromJson(data, new TypeToken<T>() {}.getType());
return o;
}
}
第二个问题:反序列化器如何根据json结果return一个对象或一个对象列表。
现在我已经用不同的方法解决了它:
列表和对象的 2 个响应模型:
public class ApiResponse<T> {
private int success;
private String[] errors;
private String[] messages;
private T data;
}
public class ApiListResponse<T> {
private int success;
private String[] errors;
private String[] messages;
private List<T> data;
}
1 个用于响应模型的解串器
public class ResponseDeserializer<T> implements JsonDeserializer {
@Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
JsonElement data = je.getAsJsonObject().get("data");
GsonBuilder gsonBuilder = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
Gson gson = gsonBuilder.create();
T response = gson.fromJson(je, type);
return response;
}
}
现在我可以为 GSON 注册类型,例如:
gsonBuilder.registerTypeAdapter(new TypeToken<ApiResponse<Object1>>() {}.getType(), new ResponseDeserializer<ApiResponse>());
gsonBuilder.registerTypeAdapter(new TypeToken<ApiListResponse<Object1>>() {}.getType(), new ResponseDeserializer<ApiListResponse>());
现在可以正确转换以下 JSON 回复:
ApiResponse
{
"data":{
"Object1Id":"1",
"Name":"Test 1",
},
"messages":[
],
"errors":[
],
"success":"1"
}
ApiListResponse
{
"data":[{
"Object1Id":"1",
"Name":"Test 1",
},{
"Object1Id":"2",
"Name":"Test 2",
}],
"messages":[
],
"errors":[
],
"success":"1"
}
有没有更好的解决方案?