Java 如何防止Gson将整数表示为浮点数
当我尝试将字符串转换为json时,Gson有一些奇怪的行为。下面的代码将字符串草稿转换为json响应。有没有办法防止gson将“.0”添加到所有整数值Java 如何防止Gson将整数表示为浮点数,java,android,gson,Java,Android,Gson,当我尝试将字符串转换为json时,Gson有一些奇怪的行为。下面的代码将字符串草稿转换为json响应。有没有办法防止gson将“.0”添加到所有整数值 ArrayList<Hashtable<String, Object>> responses; Type ResponseList = new TypeToken<ArrayList<Hashtable<String, Object>>>() {}.getType(); response
ArrayList<Hashtable<String, Object>> responses;
Type ResponseList = new TypeToken<ArrayList<Hashtable<String, Object>>>() {}.getType();
responses = new Gson().fromJson(draft, ResponseList);
draft:
[ {"id":4077395,"field_id":242566,"body":""},
{"id":4077398,"field_id":242569,"body":[[273019,0],[273020,1],[273021,0]]},
{"id":4077399,"field_id":242570,"body":[[273022,0],[273023,1],[273024,0]]}
]
responses:
[ {id=4077395.0, body=, field_id=242566.0},
{id=4077398.0, body=[[273019.0, 0.0], [273020.0, 1.0], [273021.0, 0.0]], field_id=242569.0},
{id=4077399.0, body=[[273022.0, 0.0], [273023.0, 1.0], [273024.0, 0.0]], field_id=242570.0}
]
ArrayList响应;
类型ResponseList=newTypeToken(){}.getType();
responses=new Gson().fromJson(草稿,ResponseList);
草案:
[{“id”:4077395,“field_id”:242566,“body”:“”,
{“id”:4077398,“field_id”:242569,“body”:[[273019,0],[273020,1],[273021,0]},
{“id”:4077399,“field_id”:242570,“body”:[[273022,0],[273023,1],[273024,0]}
]
响应:
[{id=4077395.0,body=,field_id=242566.0},
{id=4077398.0,body=[[273019.0,0.0],[273020.0,1.0],[273021.0,0.0]],field_id=242569.0},
{id=4077399.0,body=[[273022.0,0.0],[273023.0,1.0],[273024.0,0.0]],field_id=242570.0}
]
您告诉Gson它正在寻找字符串到对象的映射列表,这本质上是说它要对对象的类型做出最佳猜测。因为对于数值字段,Gson必须默认为Float/Double
Gson的基本功能是检查要填充的对象的类型,以确定如何解析数据。如果你不给它任何暗示,它就不会很好地工作。一个选项是定义一个自定义JsonDeserializer,不过最好不要使用HashMap(当然也不要使用Hashtable!),而是向Gson提供更多关于它所期望的数据类型的信息
class Response {
int id;
int field_id;
ArrayList<ArrayList<Integer>> body; // or whatever type is most apropriate
}
responses = new Gson()
.fromJson(draft, new TypeToken<ArrayList<Response>>(){}.getType());
类响应{
int-id;
int字段的id;
ArrayList body;//或任何最合适的类型
}
响应=新的Gson()
.fromJson(草稿,新的TypeToken(){}.getType());
同样,Gson的全部要点是将结构化数据无缝地转换为结构化对象。如果你让它创建一个几乎未定义的结构,比如一个对象映射列表,那么你就破坏了Gson的全部功能,还不如使用一些更简单的JSON解析器。我来晚了,但我自己也遇到了这个问题。在我的例子中,我不想在ArrayList中指定整数类型,因为它可以是字符串或整数 我的解决办法如下:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Double.class, new JsonSerializer<Double>() {
public JsonElement serialize(Double src, Type typeOfSrc,
JsonSerializationContext context) {
Integer value = (int)Math.round(src);
return new JsonPrimitive(value);
}
});
Gson gs = gsonBuilder.create();
我不知道如何测试或转换这些数据类型,但这应该会让您走上正确的道路。这是可行的:
Gson gson = new GsonBuilder().
registerTypeAdapter(Double.class, new JsonSerializer<Double>() {
@Override
public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
if(src == src.longValue())
return new JsonPrimitive(src.longValue());
return new JsonPrimitive(src);
}
}).create();
Gson Gson=new GsonBuilder()。
registerTypeAdapter(Double.class,新的JsonSerializer(){
@凌驾
公共JsonElement序列化(双src,类型typeOfSrc,JsonSerializationContext){
如果(src==src.longValue())
返回新的JsonPrimitive(src.longValue());
返回新的JsonPrimitive(src);
}
}).create();
基本上,这个问题没有完美的答案。所有“解决方案”仅适用于某些情况。这是一个向gson团队报告的问题,不幸的是,他们似乎坚持“javascript没有整数类型”,好像他们没有意识到gson是用于java而不是javascript的。所以他们直到今天(2018年至今)才修复它,尽管像杰克逊这样的自由党根本没有这样的问题,尽管修复起来有多么容易。因此,您可能需要自己从gson源代码中修复这个问题,并构建自己的gson.jar。源文件是gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java
case NUMBER:
return in.nextDouble();
这是我的工作
步骤1:
将gson中的ObjectTypeAdapter复制到项目中,保持路径与gson中的路径相同
像这样
com
- xxx
- xxx
com
- google
- gson
- internal
- bind
ObjectTypeAdapter
步骤2:
修改ObjectTypeAdapter
case NUMBER:
return in.nextDouble();
修改为
case NUMBER:
String number = in.nextString();
try {
return Long.valueOf(number);
} catch (NumberFormatException e) {
return Double.valueOf(number);
}
嗯。
Gson将优先考虑项目中的ObjectTypeAdapter。fun jsonToMap(json:JSONObject):Map{
fun jsonToMap(json: JSONObject): Map<String, Any> {
val doubles = Gson().fromJson<Map<String, Any>>(json.toString(), Map::class.java)
fun doublesToLong(doubles: Map<String, Any>): Map<String, Any> = doubles
.map { entry ->
Pair(entry.key, entry.value.let {
when (it) {
is Map<*, *> -> doublesToLong(it as Map<String, Any>)
is Double -> it.toLong()
else -> it
}
})
}
.toMap()
return doublesToLong(doubles)
}
val doubles=Gson().fromJson(json.toString(),Map::class.java)
趣味双打长(双打:地图):地图=双打
.map{entry->
配对(entry.key、entry.value.let{
什么时候{
is Map->doublesToLong(它作为Map)
是Double->it.toLong()
否则->它
}
})
}
.toMap()
返回双打(双打)
}
类似的双精度到int的问题:@PatrickKafka,但这里的答案是gold。或者,试着转换成JacksonAlso(参见我为类似问题编写的文章);问题是,你必须将数据解析为一个对象
,然后转换为你需要的任何对象。在我看来,听到“它可能是一个字符串或整数”是一个很大的危险信号。听起来你的JSON数据结构不好-你正在创建一个包含整数和字符串的列表?从技术上讲,JSON规范允许这样做,但它会给每个试图与之接口的反序列化程序带来麻烦。取而代之的是,考虑一个“保留整个列表字符串,如果只是一个巧合,有些是数字,B”将数字分割成自己的列表,或者c)将列表类型更改为更复杂的对象,以更好地反映数据的意图。@dimo414所有三种解决方案都有其缺陷:a)没有用,因为您不知道哪个是数字,哪个是字符串;b) 丢失排序信息(然后需要索引和开销的详细列表);c) 复杂对象将导致膨胀json@Enerccio复杂的数据需要复杂的表示,因此c)通常是可以接受的折衷方案。您的观点得到了很好的采纳,但在实践中,我会满足于混合数据类型通常会比它的价值更麻烦,并且通常重新检查您的需求会发现一种可供选择的结构,该结构可以满足您的需要,而无需跳过这些障碍。请随意发布一个带有具体用例的问题,我很乐意加入。您好,我找到了这个答案,并且使用了您在本文中提到的方式,但是,当它应该是int时,我得到了双精度:-(@armnotstrong这对哪个数字不起作用?上面的代码应该是
fun jsonToMap(json: JSONObject): Map<String, Any> {
val doubles = Gson().fromJson<Map<String, Any>>(json.toString(), Map::class.java)
fun doublesToLong(doubles: Map<String, Any>): Map<String, Any> = doubles
.map { entry ->
Pair(entry.key, entry.value.let {
when (it) {
is Map<*, *> -> doublesToLong(it as Map<String, Any>)
is Double -> it.toLong()
else -> it
}
})
}
.toMap()
return doublesToLong(doubles)
}