我的类有一个自定义反序列化器,如下所示:
private class HolderDeserializer implements JsonDeserializer<Holder> {
@Override
public Holder deserialize(JsonElement json, Type type, JsonDeserializationContext context)
throws JsonParseException {
Type mapType = new TypeToken<Map<String, String>>() {}.getType();
// in the below data map, I want value to be stored in lowercase
// how can I do that?
Map<String, String> data = context.deserialize(json, mapType);
return new Holder(data);
}
}
这就是我在创建 Gson 对象时注册解串器的方式:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Holder.class, new HolderDeserializer());
Gson gson = gsonBuilder.create();
最后,像这样解析我的 JSON:
Type responseType = new TypeToken<Map<String, Holder>>() {}.getType();
Map<String, Holder> response = gson.fromJson(jsonLine, responseType);
在我的 deserialize
方法中,json
的值如下所示 {"linkedTo":"COUNT"}
然后它得到作为 {linkedTo=COUNT}
加载到数据映射中。我想看看是否有任何方法可以使 data
映射的所有值都小写,因此它应该像这样存储,而不是这个 {linkedTo=COUNT}
{linkedTo=count}
自动出现在数据 map 中?
有什么方法可以在 Gson 中自动执行此操作吗?
更新:
下面是我的 JSON 内容:
{
"abc": {
"linkedTo": "COUNT",
// possibly more data...
},
"plmtq": {
"linkedTo": "TITLE",
"decode": "TRUE",
// possibly more data...
}
}
最佳答案
首先建议使用Gson TypeAdapter而不是JsonDeserializer 。所以我将用它来回答你的问题:
New applications should prefer TypeAdapter, whose streaming API is more efficient than this interface's tree API.
问题:反序列化前如何修改json内容?
解决方案之一:在反序列化之前对json内容进行预处理,修改其部分内容。
我们如何使用 TypeAdapter 来实现这一点:定义一个自定义的 TypeAdapter
,在其 read
方法中获取 json 内容(该方法仅被调用)反序列化之前)并修改内容。
代码示例:
定义一个TypeAdapterFactory
和一个TypeAdapter
;
TypeAdapterFactory myCustomTypeAdapterFactory = new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type); //
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
JsonElement tree = delegate.toJsonTree(value);
beforeWrite(value, tree);
elementAdapter.write(out, tree);
}
public T read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
afterRead(tree);
return delegate.fromJsonTree(tree);
}
/**
* Modify {@code toSerialize} before it is written to
* the outgoing JSON stream.
*/
protected void beforeWrite(T source, JsonElement toSerialize) {
}
/**
* Modify {@code deserialized} before it is parsed
*/
protected void afterRead(JsonElement deserialized) {
if(deserialized instanceof JsonObject) {
JsonObject jsonObject = ((JsonObject)deserialized);
Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for(Map.Entry<String,JsonElement> entry : entrySet){
if(entry.getValue() instanceof JsonPrimitive) {
if(entry.getKey().equalsIgnoreCase("linkedTo")) {
String val = jsonObject.get(entry.getKey()).toString();
jsonObject.addProperty(entry.getKey(), val.toLowerCase());
}
} else {
afterRead(entry.getValue());
}
}
}
}
};
}
};
我们在反序列化之前添加了一个额外的过程。我们从 json 内容中获取 entrySet
并更新 linkedTo
键的值。
工作示例:
String jsonContent = "{\"abc\":{\"linkedTo\":\"COUNT\"},\"plmtq\":{\"linkedTo\":\"TITLE\",\"decode\":\"TRUE\"}}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(myCustomTypeAdapterFactory);
Gson gson = gsonBuilder.create();
Map mapDeserialized = gson.fromJson(jsonContent, Map.class);
输出:
关于java - 如何在自定义反序列化器Gson中小写JsonElement值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41203175/