Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使GSON将数字反序列化为整数或双精度_Java_Json_Gson - Fatal编程技术网

Java 使GSON将数字反序列化为整数或双精度

Java 使GSON将数字反序列化为整数或双精度,java,json,gson,Java,Json,Gson,我和格森相处得很艰难 我有一个简单的JSON,我想将其反序列化为映射 对我来说,123应该被解析为int(或long),123.4应该被解析为float(或double) 另一方面,格森一直在创造双打 我能告诉格森不要一直滥用双倍吗 我的实际代码: Type mapType = new TypeToken<Map<String, Object>>() {}.getType(); GSON gson = new Gson(); Map<String, Object&g

我和格森相处得很艰难

我有一个简单的JSON,我想将其反序列化为
映射

对我来说,123应该被解析为int(或long),123.4应该被解析为float(或double)

另一方面,格森一直在创造双打

我能告诉格森不要一直滥用双倍吗

我的实际代码:

Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
GSON gson = new Gson();
Map<String, Object> map = gson.fromJson(someString, mapType);
Type-mapType=new-TypeToken(){}.getType();
GSON GSON=新的GSON();
Map Map=gson.fromJson(someString,mapType);

混合这样的类型(整数和双精度)不是一个好办法。由于将对象用作类型,因此无法从映射中同时获取整数和双精度。Gson决定哪个类型更适合对象。在您的例子中,它是Double,因为所有值都可以是Double,但所有值都不能是整数

如果确实需要混合类型,请尝试使用Number类而不是Object。例如:

public static void main(String[] args){
        String array = "[1, 2.5, 4, 5.66]";
        Gson gson = new Gson();

        Type type = new TypeToken<ArrayList<Number>>() {}.getType();
        List<Number> obj = gson.fromJson(array, type);

        System.out.println(Arrays.toString(obj.toArray()));
    }
publicstaticvoidmain(字符串[]args){
字符串数组=“[1,2.5,4,5.66]”;
Gson Gson=新的Gson();
Type Type=new-TypeToken(){}.getType();
List obj=gson.fromJson(数组,类型);
System.out.println(Arrays.toString(obj.toArray());
}
输出:[1,2.5,4,5.66]

而这:

public static void main(String[] args){
    String array = "[1, 2.5, 4, 5.66]";
    Gson gson = new Gson();

    Type type = new TypeToken<ArrayList<Object>>() {}.getType();
    List<Object> obj = gson.fromJson(array, type);

    System.out.println(Arrays.toString(obj.toArray()));
}
publicstaticvoidmain(字符串[]args){
字符串数组=“[1,2.5,4,5.66]”;
Gson Gson=新的Gson();
Type Type=new-TypeToken(){}.getType();
List obj=gson.fromJson(数组,类型);
System.out.println(Arrays.toString(obj.toArray());
}
将为您提供输出:[1.0、2.5、4.0、5.66]

您可以执行以下更改以解析该数据: 下面是实际解析它的代码。
Type-mapType=new-TypeToken(){
}.getType();
字符串str=prop.getProperty(“testData1”);
系统输出打印项次(str);
Gson Gson=新的Gson();
Map Map=gson.fromJson(str,mapType);
for(字符串键:map.keySet()){
字符串a=null;
试一试{
if(map.get(key)instanceof Double){
a=“”+map.get(键);
}否则{
if(map.get(key)instanceof String){
a=(字符串)map.get(键);
}否则{
a=零;
}
}
如果(a!=null&&a.contains(“.”)&&a.endsWith(“.0”)){
//将其转换为Double/Float
}否则{
//以整数形式工作
}
}捕获(例外情况除外){
例如printStackTrace();
}
}

以下代码编译并运行:

package test;

import java.lang.reflect.Type;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;

public class Main {

    public static void main(String[] args) {
        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(Object.class, new MyObjectDeserializer());
        Gson gson = builder.create();
        String array = "[1, 2.5, 4, 5.66]";

        Type objectListType = new TypeToken<ArrayList<Object>>() {}.getType();
        List<Object> obj = gson.fromJson(array, objectListType);

        System.out.println(Arrays.toString(obj.toArray()));
    }

    public static class MyObjectDeserializer implements JsonDeserializer<Object> {

        public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
            throws JsonParseException {

          Number num = null;
          try {
              num = NumberFormat.getInstance().parse(json.getAsJsonPrimitive().getAsString());
          } catch (Exception e) {
              //ignore
          }
          if (num == null) {
              return context.deserialize(json, typeOfT);
          } else {
              return num;
          }
      }
    }

}

如果您不一定要特别使用gson库,您可以使用jackson库解决此反序列化问题,如下所示:

new ObjectMapper().readValue(yourJson, new TypeReference<Map<String,Object>>() {});
newObjectMapper().readValue(yourJson,newTypeReference(){});
下面是一个完整的junit测试,它揭示了反序列化整数值的两个库之间的差异:

@Test
public void integerDeserializationTest() throws Exception {

    final String jsonSource = "{\"intValue\":1,\"doubleValue\":2.0,\"stringValue\":\"value\"}";

    //Using gson library "intValue" is deserialized to 1.0
    final String gsonWrongResult = "{\"intValue\":1.0,\"doubleValue\":2.0,\"stringValue\":\"value\"}";
    Map<String,Object> gsonMap = new Gson().fromJson(jsonSource, new TypeToken<Map<String, Object>>() {
    }.getType());
    assertThat(new Gson().toJson(gsonMap),is(gsonWrongResult));


    //Using jackson library "intValue" is deserialized to 1
    Map<String,Object> jacksonMap = new ObjectMapper().readValue(jsonSource, new TypeReference<Map<String,Object>>() {});
    assertThat(new ObjectMapper().writeValueAsString(jacksonMap),is(jsonSource));

}
@测试
public void integerDeserializationTest()引发异常{
最后一个字符串jsonSource=“{\'intValue\':1,\'doubleValue\':2.0,\'stringValue\':\'value\'”;
//使用gson库将“intValue”反序列化为1.0
最后一个字符串gsonErrorResult=“{\'intValue\':1.0,\'doubleValue\':2.0,\'stringValue\':\'value\'”;
Map gsonMap=new Gson(){
}.getType());
断言(new Gson().toJson(gsonMap),是(gsonErrorResult));
//使用jackson库将“intValue”反序列化为1
Map jacksonMap=new ObjectMapper().readValue(jsonSource,new TypeReference(){});
assertThat(newObjectMapper().writeValueAsString(jacksonMap),是(jsonSource));
}

根本问题是只有一种数字类型。没有int类型-它们都是浮点,小数点尽可能省略。@McDowell是的,我知道这一点。但是GSON的行为使得反序列化和序列化产生了与原始输入不同的输出,这真是令人讨厌;e、 g.我有一个
timestamp
字段,最初是123456780,在反序列化循环之后是1.23456789E9,有什么解决方案吗?根本问题是gson无法提供将整数转换为整数的选项。gson能检测出整数吗?是的,您可以使用LongSerializationPolicy.STRING转换为字符串。为什么没有长期策略,长期策略?我知道这并不像看上去那么简单,因为JSON没有整数类型(同一字段在一个实例中可以是整数,在另一个实例中可以是十进制),但这就是策略的作用。谢谢。但是我需要一个
对象
,因为可能存在其他非数字字段——就像在任何JSON中一样。我只想改变对数字的处理……谢谢。事实上,我将反序列化许多对象和类的完整映射;GSON处理此文件,我不喜欢它处理数字的方式..我根据您的反馈更新了我的答案,如果我理解正确,那么我认为Workbook应该是有希望的,但它依赖于区域设置(分隔符),不应该是:-(什么是区域设置相关?我不明白。我通过使用上下文修复了它。。这应该可以。我的意思是
Numberformat.getInstance()
返回当前默认区域设置的实例。
private static Number parse(String str) {
    Number number = null;
    try {
        number = Float.parseFloat(str);
    } catch(NumberFormatException e) {
    try {
        number = Double.parseDouble(str);
    } catch(NumberFormatException e1) {
        try {
            number = Integer.parseInt(str);
        } catch(NumberFormatException e2) {
            try {
                number = Long.parseLong(str);
            } catch(NumberFormatException e3) {
                throw e3;
            }       
        }       
    }       
}
    return number;
}
new ObjectMapper().readValue(yourJson, new TypeReference<Map<String,Object>>() {});
@Test
public void integerDeserializationTest() throws Exception {

    final String jsonSource = "{\"intValue\":1,\"doubleValue\":2.0,\"stringValue\":\"value\"}";

    //Using gson library "intValue" is deserialized to 1.0
    final String gsonWrongResult = "{\"intValue\":1.0,\"doubleValue\":2.0,\"stringValue\":\"value\"}";
    Map<String,Object> gsonMap = new Gson().fromJson(jsonSource, new TypeToken<Map<String, Object>>() {
    }.getType());
    assertThat(new Gson().toJson(gsonMap),is(gsonWrongResult));


    //Using jackson library "intValue" is deserialized to 1
    Map<String,Object> jacksonMap = new ObjectMapper().readValue(jsonSource, new TypeReference<Map<String,Object>>() {});
    assertThat(new ObjectMapper().writeValueAsString(jacksonMap),is(jsonSource));

}