我的客户端检索JSON内容如下:
{
"table": "tablename",
"update": 1495104575669,
"rows": [
{"column5": 11, "column6": "yyy"},
{"column3": 22, "column4": "zzz"}
]
}
在rows
数组内容中,密钥未修复。我想检索密钥和值,并使用Gson 2.8.x保存到Map
。
如何将Gson配置为仅用于反序列化?
这是我的想法:
public class Dataset {
private String table;
private long update;
private List<Rows>> lists; <-- little confused here.
or private List<HashMap<String,Object> lists
Setter/Getter
}
public class Rows {
private HashMap<String, Object> map;
....
}
Dataset k = gson.fromJson(jsonStr, Dataset.class);
log.info(k.getRows().size()); <-- I got two null object
感谢。
答案 0 :(得分:1)
Gson不支持开箱即用。如果您可以修改属性名称,那就太好了。如果没有,那么您可以选择一些可能对您有帮助的选项。
Dataset.lists
字段重命名为Dataset.rows
,rows
。@SerializedName
选择其他名称。TypeAdapter
(流模式;需要更少的内存,但更难使用)或在JsonDeserializer
注册的自定义GsonBuilder
(对象模式;需要更多内存来存储中间树视图,但它易于使用)。对于选项#2,您只需添加名称替代品的名称:
@SerializedName(value = "lists", alternate = "rows")
final List<Map<String, Object>> lists;
对于选项#3,绑定试图动态检测名称的下游List<Map<String, Object>>
类型适配器。请注意,为简单起见,我省略了Rows
类反序列化策略(我相信您可能希望删除Rows
类,而不是简单Map<String, Object>
(另请注意:使用Map
,尽量不指定集合实现 - 哈希映射是无序的,但是告诉Gson你要处理Map
会让它选择一个有序的地图,如LinkedTreeMap
(Gson internals)或LinkedHashMap
对数据集可能很重要))。
// Type tokens are immutable and can be declared constants
private static final TypeToken<String> stringTypeToken = new TypeToken<String>() {
};
private static final TypeToken<Long> longTypeToken = new TypeToken<Long>() {
};
private static final TypeToken<List<Map<String, Object>>> stringToObjectMapListTypeToken = new TypeToken<List<Map<String, Object>>>() {
};
private static final Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
if ( typeToken.getRawType() != Dataset.class ) {
return null;
}
// If the actual type token represents the Dataset class, then pick the bunch of downstream type adapters
final TypeAdapter<String> stringTypeAdapter = gson.getDelegateAdapter(this, stringTypeToken);
final TypeAdapter<Long> primitiveLongTypeAdapter = gson.getDelegateAdapter(this, longTypeToken);
final TypeAdapter<List<Map<String, Object>>> stringToObjectMapListTypeAdapter = stringToObjectMapListTypeToken);
// And compose the bunch into a single dataset type adapter
final TypeAdapter<Dataset> datasetTypeAdapter = new TypeAdapter<Dataset>() {
@Override
public void write(final JsonWriter out, final Dataset dataset) {
// Omitted for brevity
throw new UnsupportedOperationException();
}
@Override
public Dataset read(final JsonReader in)
throws IOException {
in.beginObject();
String table = null;
long update = 0;
List<Map<String, Object>> lists = null;
while ( in.hasNext() ) {
final String name = in.nextName();
switch ( name ) {
case "table":
table = stringTypeAdapter.read(in);
break;
case "update":
update = primitiveLongTypeAdapter.read(in);
break;
default:
lists = stringToObjectMapListTypeAdapter.read(in);
break;
}
}
in.endObject();
return new Dataset(table, update, lists);
}
}.nullSafe(); // Making the type adapter null-safe
@SuppressWarnings("unchecked")
final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) datasetTypeAdapter;
return typeAdapter;
}
})
.create();
final Dataset dataset = gson.fromJson(jsonReader, Dataset.class);
System.out.println(dataset.lists);
上面的代码将打印出来:
[{column5 = 11.0,column6 = yyy},{column3 = 22.0,column4 = zzz}]