我试图让Gson
解析没有浮点值的值为Longs而不是默认情况下的双打值:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Object.class, (JsonDeserializer<Object>) (json, type, context) -> {
// we don't want integer values to be parsed as floats
String value = json.getAsJsonPrimitive().getAsString();
if (value.matches("\\d+")) {
return Long.valueOf(value);
} else {
return context.deserialize(json, type);
}
}).create();
...
gson.fromJson(payload);
我只想测试,天气包含.
的值,如果没有,请将其解析为Long
。否则使用默认解析方法。
然而,当我放置断点时,永远不会调用该方法。我想我以错误的方式注册了适配器。
EDIT1:Json可能包含包含字符串,整数,双精度和地图的列表。我需要一个通用的解决方案。
EDIT2:我也试过各种.registerTypeAdapter(Number.class
或.registerTypeAdapter(Double.class
但没有效果。还没有打电话。
答案 0 :(得分:0)
我找不到比完全覆盖Gson功能更好的方法。这是一个非常黑客,但没有其他解决方案似乎解决了这个问题:
public class Gson {
private static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
public <T> TypeAdapter<T> create(com.google.gson.Gson gson, TypeToken<T> type) {
return type.getRawType() == Object.class ? (TypeAdapter<T>) new LongObjectTypeAdapter(gson) : null;
}
};
static {
try {
Field field = ObjectTypeAdapter.class.getDeclaredField("FACTORY");
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.setAccessible(true);
field.set(null, FACTORY);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
private com.google.gson.Gson gson = new com.google.gson.Gson();
public <T> T fromJson(String payload, Class<T> c) {
return gson.fromJson(payload, c);
}
public String toJson(Object object) {
return gson.toJson(object);
}
public static class LongObjectTypeAdapter extends TypeAdapter<Object> {
private com.google.gson.Gson gson;
public LongObjectTypeAdapter(com.google.gson.Gson gson) {
this.gson = gson;
}
public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
switch (token) {
case BEGIN_ARRAY:
ArrayList list = new ArrayList();
in.beginArray();
while(in.hasNext()) {
list.add(this.read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT:
LinkedTreeMap map = new LinkedTreeMap();
in.beginObject();
while(in.hasNext()) {
map.put(in.nextName(), this.read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER:
String value = in.nextString();
if (value.contains(".")) {
return Double.valueOf(value);
} else {
return Long.valueOf(value);
}
case BOOLEAN:
return Boolean.valueOf(in.nextBoolean());
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
public void write(JsonWriter out, Object value) throws IOException {
if (value == null) {
out.nullValue();
} else {
TypeAdapter typeAdapter = gson.getAdapter(value.getClass());
if (typeAdapter instanceof LongObjectTypeAdapter) {
out.beginObject();
out.endObject();
} else {
typeAdapter.write(out, value);
}
}
}
}
}