java 格森。将整数反序列化为整数而不是双精度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17090589/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Gson. Deserialize integers as integers and not as doubles
提问by Moses
I have json object with arbitary values inside. And I want to deserialize it in a Map. Everything is ok except converting integers to a doubles. See example:
我有一个带有任意值的 json 对象。我想在地图中反序列化它。除了将整数转换为双精度数外,一切正常。见示例:
{"id":1, "inner_obj":{"key":"value","num":666,"map":{"key":"value"}}}
deserializes to this(map.toString()):
反序列化为 this(map.toString()):
{id=1.0, inner_obj={key=value, num=666.0, map={key=value}}}
Is there some easy way to deserialize "id" and "num" as Integers and not as Doubles?
是否有一些简单的方法可以将“id”和“num”反序列化为整数而不是双精度数?
回答by NINCOMPOOP
There are no integer type in JSON. 1 and 1.0 are the same. You need to parse that 1.0 to 1 in your code. Or you need to map the JSON to some VO class and define the type of fields of the class explicitly , so that GSON can understand what you are looking for.
JSON 中没有整数类型。1 和 1.0 是一样的。您需要在代码中将 1.0 解析为 1。或者你需要将 JSON 映射到某个 VO 类并明确定义该类的字段类型,以便 GSON 可以理解您要查找的内容。
回答by McDowell
JSON only has a single Number type and there is no way for the parser to automatically tell what type to convert it to.
JSON 只有一个 Number 类型,解析器无法自动告诉将它转换为什么类型。
If you aren't going to use a strongly typed object graph, consider using the JsonElementtypes:
如果您不打算使用强类型对象图,请考虑使用JsonElement类型:
JsonObject root = new Gson().fromJson(json, JsonObject.class);
int num = root.getAsJsonObject("inner_obj").get("num").getAsInt();
回答by Erik Calissendorff
Been searching for a solution to the nested Map problem myself and "???" above was the first answer that actually helped in the non trivial use cases.
我自己和“???”一直在寻找嵌套 Map 问题的解决方案 上面是第一个在非平凡用例中真正有帮助的答案。
Since the solution above only handled Number I updated the solution to provide generic parsing capability for String and booleans also, see the updated code below:
由于上面的解决方案只处理数字,我更新了解决方案以提供字符串和布尔值的通用解析功能,请参阅下面的更新代码:
private static class MapDeserializer implements JsonDeserializer<Map<String, Object>> {
public Map<String, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Map<String, Object> m = new LinkedHashMap<String, Object>();
JsonObject jo = json.getAsJsonObject();
for (Entry<String, JsonElement> mx : jo.entrySet()) {
String key = mx.getKey();
JsonElement v = mx.getValue();
if (v.isJsonArray()) {
m.put(key, g.fromJson(v, List.class));
} else if (v.isJsonPrimitive()) {
Number num = null;
ParsePosition position=new ParsePosition(0);
String vString=v.getAsString();
try {
num = NumberFormat.getInstance(Locale.ROOT).parse(vString,position);
} catch (Exception e) {
}
//Check if the position corresponds to the length of the string
if(position.getErrorIndex() < 0 && vString.length() == position.getIndex()) {
if (num != null) {
m.put(key, num);
continue;
}
}
JsonPrimitive prim = v.getAsJsonPrimitive();
if (prim.isBoolean()) {
m.put(key, prim.getAsBoolean());
} else if (prim.isString()) {
m.put(key, prim.getAsString());
} else {
m.put(key, null);
}
} else if (v.isJsonObject()) {
m.put(key, g.fromJson(v, Map.class));
}
}
return m;
}
}
private static class ListDeserializer implements JsonDeserializer<List<Object>> {
public List<Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<Object> m = new ArrayList<Object>();
JsonArray arr = json.getAsJsonArray();
for (JsonElement jsonElement : arr) {
if (jsonElement.isJsonObject()) {
m.add(g.fromJson(jsonElement, Map.class));
} else if (jsonElement.isJsonArray()) {
m.add(g.fromJson(jsonElement, List.class));
} else if (jsonElement.isJsonPrimitive()) {
Number num = null;
try {
num = NumberFormat.getInstance().parse(jsonElement.getAsString());
} catch (Exception e) {
}
if (num != null) {
m.add(num);
continue;
}
JsonPrimitive prim = jsonElement.getAsJsonPrimitive();
if (prim.isBoolean()) {
m.add(prim.getAsBoolean());
} else if (prim.isString()) {
m.add(prim.getAsString());
} else {
m.add(null);
}
}
}
return m;
}
}
private static Gson g = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserializer()).registerTypeAdapter(List.class, new ListDeserializer()).setDateFormat("yyyy-MM-dd HH:mm:ss").create();
回答by hrzafer
To avoid possible ClassCastException, it is better to cast to Number
first. In the following code map
was deserialized from JSON as a Map
with no generics.
为避免可能出现的 ClassCastException,最好先强制转换Number
。在以下代码中map
,从 JSON 反序列化为Map
没有泛型的 a。
int numberOfPages = ((Number) map.get("number_of_pages")).intValue();
回答by ???
It's my code
这是我的代码
private static class MapDeserializer implements JsonDeserializer<Map<String,Object>> {
public Map<String,Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Map<String,Object> m = new LinkedHashMap<String, Object>();
JsonObject jo = json.getAsJsonObject();
for (Entry<String, JsonElement> mx : jo.entrySet()){
String key = mx.getKey();
JsonElement v = mx.getValue();
if(v.isJsonArray()){
m.put(key, g.fromJson(v, List.class));
}else if(v.isJsonPrimitive()){
Number num = null;
try {
num = NumberFormat.getInstance().parse(v.getAsString());
} catch (Exception e) {
e.printStackTrace();
}
m.put(key,num);
}else if(v.isJsonObject()){
m.put(key,g.fromJson(v, Map.class));
}
}
return m;
}
}
private static class ListDeserializer implements JsonDeserializer<List<Object>> {
public List<Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<Object> m = new ArrayList<Object>();
JsonArray arr = json.getAsJsonArray();
for (JsonElement jsonElement : arr) {
if(jsonElement.isJsonObject()){
m.add(g.fromJson(jsonElement, Map.class));
}else if(jsonElement.isJsonArray()){
m.add(g.fromJson(jsonElement, List.class));
}else if(jsonElement.isJsonPrimitive()){
Number num = null;
try {
num = NumberFormat.getInstance().parse(jsonElement.getAsString());
} catch (Exception e) {
}
m.add(num);
}
}
return m;
}
}
private static Gson g = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserializer()).registerTypeAdapter(List.class, new ListDeserializer()).setDateFormat("yyyy-MM-dd HH:mm:ss").serializeNulls().create();
回答by Oleksandr Tsurika
Register type adapter for Map
:
注册类型适配器Map
:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Map.class, new JsonDeserializer<Map>() {
@Override
public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
LinkedTreeMap<String,Object> m = new LinkedTreeMap<String, Object>();
JsonObject jo = json.getAsJsonObject();
for (Map.Entry<String, JsonElement> mx : jo.entrySet()){
String key = mx.getKey();
JsonElement v = mx.getValue();
if(v.isJsonArray()){
m.put(key, context.deserialize(v, List.class));
}else if(v.isJsonPrimitive()){
Object value = v.getAsString();
try {
Object numValue = NumberFormat.getInstance().parse((String)value);
if (numValue != null && numValue.toString().equals(value)) {
value = numValue;
}
} catch (Exception e) {
}
m.put(key, value);
}else if(v.isJsonObject()){
m.put(key,context.deserialize(v, Map.class));
}
}
return m;
}
})
.create();
and deserialize using it like: gson.fromJson(instanceJson, Map.class)
, where instanceJson
is an json
of object which should be deserialized into Map
.
并使用它进行反序列化,例如:gson.fromJson(instanceJson, Map.class)
,其中instanceJson
是json
应反序列化为Map
.
回答by Zephyr
Here is my example, the first part is the definition of the class that has an int type field.
这是我的示例,第一部分是具有 int 类型字段的类的定义。
import com.google.api.client.util.Key;
public class Folder {
public static final String FIELD_NAME_CHILD_COUNT = "childCount";
@Key(FIELD_NAME_CHILD_COUNT)
public final int childCount;
public Folder(int aChildCount) {
childCount = aChildCount;
}
}
Then the TypeAdapter to convert the number type in Gson to a Java object.
然后 TypeAdapter 将 Gson 中的数字类型转换为 Java 对象。
GsonBuilder gsb = new GsonBuilder();
gsb.registerTypeAdapter(Folder.class, new JsonDeserializer<Folder>() {
@Override
public Folder deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
int value = json.getAsJsonObject().get("childCount").getAsJsonPrimitive().getAsInt();
return new Folder(value);
}
}
);
The third part is the test data, and it works.
第三部分是测试数据,它起作用了。
String gsonData = new String("\"folder\":{\"childCount\":0}");