如何避免 Gson 将 JsonString 中的 int long 等数字转化为带小数的 Double

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何避免 Gson 将 JsonString 中的 int long 等数字转化为带小数的 Double相关的知识,希望对你有一定的参考价值。

参考技术A 在将 json 串转为 Map<String, Object> 时

内部的类似 page=1, limit=10 等int类型数据会被转换为 Double,输出 page=1.0, limit = 10.0

而类似 timestamp=1231231231231 等 long 类型也会被转换为 Double,输出 1exxxx(科学计数法)

Gson 2.8.4 包含的这个提交 解决了这个问题,它允许我们指定数字类型如何被转换。

Gson 最常用的功能

反序列号为对象

普通对象
Person person = gson.fromJson(jsonString, Person.class);
Person person = gson.fromJson(jsonString, new TypeToken<Person>() {}.getType());
2
2
 
1
Person person = gson.fromJson(jsonString, Person.class);
2
Person person = gson.fromJson(jsonString, new TypeToken<Person>() {}.getType());
数组
String[] array = gson.fromJson(jsonString, String[].class);
String[] array = gson.fromJson(jsonString, new TypeToken<String[]>() {}.getType());
int[][] array = gson.fromJson(jsonString, int[][].class);
3
3
 
1
String[] array = gson.fromJson(jsonString, String[].class);
2
String[] array = gson.fromJson(jsonString, new TypeToken<String[]>() {}.getType());
3
int[][] array = gson.fromJson(jsonString, int[][].class);
集合
List<Person> list = gson.fromJson(jsonString, new TypeToken<List<Person>>() {}.getType());//支持带泛型
Map<String, Integer> map = gson.fromJson(jsonString2, new TypeToken<Map<String, Integer>>() {}.getType());
2
2
 
1
List<Person> list = gson.fromJson(jsonString, new TypeToken<List<Person>>() {}.getType());//支持带泛型
2
Map<String, Integer> map = gson.fromJson(jsonString2, new TypeToken<Map<String, Integer>>() {}.getType());
问题:为何要用 TypeToken 去包装要解析的类型?为何不直接用 List<Person>.class ?
解疑:因为编译之后,List<String> 和 List<User> 这俩个的字节码文件只一个,那就是 List.class,这是Java泛型使用时要注意的问题:泛型擦除。

为某个字段提供多个属性名

或者说将 json 字符串中的某一字段的值赋给要转化的对象中的某一指定字段。
比如,服务器可能通过不同的字段返回给我们错误信息,有的用tips、有的用msg、有的用errorinfo……现在,我们不管服务器用哪种方式返回给我们错误信息,我们都用 message 字段去接收。
@SerializedName(value = "message", alternate = {"tips", "msg","errorinfo","error"})
public String message;
2
2
 
1
@SerializedName(value = "message", alternate = {"tips", "msg","errorinfo","error"})
2
public String message;
当上面的几个属性中出现任意一个时均可以得到正确的结果,如果多种属性同时出,那么是以最后一个出现的值为准。

用JsonElement去定义未知类型的字段

可以用 【JsonElement】去解析json数据中不确定具体类型的某些字段。
如下面的 data ,对于不同的网络请求,其内容是完全不一样的,可能是一个JsonObject,也可能是一个JsonArray,也可能是一个String,那么就可以用一个 JsonElement 类型的字段去接收,Gson解析时不会解析具体内容,而是把此字段中的值【原封不动】的返回给你。
PS:JsonElement 是 Gson 框架中所有元素的父类,其子类包括 JsonObject、JsonArray、JsonPrimitive、JsonNull。Json字符串中的所有 value 都可以被解析为 JsonElement 的子类。
public class Test {
	public static void main(String[] args) {
		String content = "{\"code\":\"100\",\"data\":{\"errorinfo\":\"成功\"}}";
		String content2 = "{\"code\":\"100\",\"data\":\"成功\"}";
		System.out.println(new Gson().fromJson(content, Response.class).data);//【{"errorinfo":"成功"}】
		System.out.println(new Gson().fromJson(content2, Response.class).data);//【"成功"】
	}

	static class Response {
		public String code;
		public JsonElement data;//用一个JsonObject去接收不详解析的内容
	}
}
13
13
 
1
public class Test {
2
    public static void main(String[] args) {
3
        String content = "{\"code\":\"100\",\"data\":{\"errorinfo\":\"成功\"}}";
4
        String content2 = "{\"code\":\"100\",\"data\":\"成功\"}";
5
        System.out.println(new Gson().fromJson(content, Response.class).data);//【{"errorinfo":"成功"}】
6
        System.out.println(new Gson().fromJson(content2, Response.class).data);//【"成功"】
7
    }
8
9
    static class Response {
10
        public String code;
11
        public JsonElement data;//用一个JsonObject去接收不详解析的内容
12
    }
13
}
打印内容为:
{"errorinfo":"成功"}
"成功"
2
2
 
1
{"errorinfo":"成功"}
2
"成功"
注意,上面的字符串时有双引号的,如果用 Object 去定义 data,则打印内容为:
{errorinfo=成功}
成功
2
2
 
1
{errorinfo=成功}
2
成功
可以看到,两者被解析后的具体内容是不一样的。

解析Json字符串中的内容

String jsonString = "{‘flag‘:true,‘data‘:{‘name‘:‘张三‘,‘age‘:18,‘address‘:‘广州‘}}";
JsonObject root = new JsonParser().parse(jsonString).getAsJsonObject();

boolean flag = root.getAsJsonPrimitive("flag").getAsBoolean();
String name = root.getAsJsonObject("data").get("name").getAsString();
System.out.println(flag + "  " + name);//true  张三
6
6
 
1
String jsonString = "{‘flag‘:true,‘data‘:{‘name‘:‘张三‘,‘age‘:18,‘address‘:‘广州‘}}";
2
JsonObject root = new JsonParser().parse(jsonString).getAsJsonObject();
3
4
boolean flag = root.getAsJsonPrimitive("flag").getAsBoolean();
5
String name = root.getAsJsonObject("data").get("name").getAsString();
6
System.out.println(flag + "  " + name);//true  张三

将序列化后的内容保存到Appendable

gson.toJson(user,System.out); //直接写到控制台。System.out是PrintStream的子类,PrintStream是Appendable接口的实现类

FileWriter fileWriter=new FileWriter("d://a.txt");//将toJson后的字符串拼接到文件中
gson.toJson(person, fileWriter);//FileWriter extends OutputStreamWriter extends Writer,Writer实现了Appendable接口
fileWriter.close();

StringBuilder builder=new StringBuilder();//将toJson后的字符串拼接到StringBuilder中
gson.toJson(person, builder);//StrngBuilder、StringBuffer都是Appendable接口的实现类
System.out.println(builder.toString());
 
1
gson.toJson(user,System.out); //直接写到控制台。System.out是PrintStream的子类,PrintStream是Appendable接口的实现类
2
3
FileWriter fileWriter=new FileWriter("d://a.txt");//将toJson后的字符串拼接到文件中
4
gson.toJson(person, fileWriter);//FileWriter extends OutputStreamWriter extends Writer,Writer实现了Appendable接口
5
fileWriter.close();
6
7
StringBuilder builder=new StringBuilder();//将toJson后的字符串拼接到StringBuilder中
8
gson.toJson(person, builder);//StrngBuilder、StringBuffer都是Appendable接口的实现类
9
System.out.println(builder.toString());

使用 JsonWriter 编写 Json 串

JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));//可以先写到文件中,再从文件中读取
writer.beginObject().name("name").value("包青天").name("sport").beginArray().value("篮球").value("排球").endArray()//数据
		.name("info").beginObject().name("age").value(28).endObject()//对象
		.endObject();
writer.close(); //{"name":"包青天","sport":["篮球","排球"],"info":{"age":28}}
x
1
JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));//可以先写到文件中,再从文件中读取
2
writer.beginObject().name("name").value("包青天").name("sport").beginArray().value("篮球").value("排球").endArray()//数据
3
        .name("info").beginObject().name("age").value(28).endObject()//对象
4
        .endObject();
5
writer.close(); //{"name":"包青天","sport":["篮球","排球"],"info":{"age":28}}
写到指定位置:
final StringBuilder builder = new StringBuilder();
Writer writer = new Writer() {
   @Override
   public void write(@NonNull char[] cbuf, int off, int len) throws IOException {
      builder.append((new String(cbuf, off, len)));
   }
   
   @Override
   public void flush() throws IOException {
      System.out.println("【flush】");
   }
   
   @Override
   public void close() throws IOException {
      System.out.println("【close】");
      System.out.println(builder.toString());
   }
};

JsonWriter jsonWriter = new JsonWriter(writer);//可以先写到文件中,再从文件中读取
jsonWriter.setIndent("    ");//设置缩进格式,一般使用2-4个空格,或使用制表符\t
jsonWriter.beginObject().name("name").value("包青天").name("sport").beginArray().value("篮球").value("排球").endArray()//数据
      .name("info").beginObject().name("age").value(28).endObject()//对象
      .endObject();
jsonWriter.close(); //{"name":"包青天","sport":["篮球","排球"],"info":{"age":28}}
25
1
final StringBuilder builder = new StringBuilder();
2
Writer writer = new Writer() {
3
   @Override
4
   public void write(@NonNull char[] cbuf, int off, int len) throws IOException {
5
      builder.append((new String(cbuf, off, len)));
6
   }
7
   
8
   @Override
9
   public void flush() throws IOException {
10
      System.out.println("【flush】");
11
   }
12
   
13
   @Override
14
   public void close() throws IOException {
15
      System.out.println("【close】");
16
      System.out.println(builder.toString());
17
   }
18
};
19
20
JsonWriter jsonWriter = new JsonWriter(writer);//可以先写到文件中,再从文件中读取
21
jsonWriter.setIndent("    ");//设置缩进格式,一般使用2-4个空格,或使用制表符\t
22
jsonWriter.beginObject().name("name").value("包青天").name("sport").beginArray().value("篮球").value("排球").endArray()//数据
23
      .name("info").beginObject().name("age").value(28).endObject()//对象
24
      .endObject();
25
jsonWriter.close(); //{"name":"包青天","sport":["篮球","排球"],"info":{"age":28}}
结果
{
    "name": "包青天",
    "sport": [
        "篮球",
        "排球"
    ],
    "info": {
        "age": 28
    }
}
x
1
{
2
    "name": "包青天",
3
    "sport": [
4
        "篮球",
5
        "排球"
6
    ],
7
    "info": {
8
        "age": 28
9
    }
10
}
2018-5-27

以上是关于如何避免 Gson 将 JsonString 中的 int long 等数字转化为带小数的 Double的主要内容,如果未能解决你的问题,请参考以下文章

gson中的java.lang.StackOverflowError

使用 GSON 解析 JSON 数组

如何使用新值对象进行jsonify?

将 Gson 的 JsonObject 保存为没有 Members 对象的纯 Json 到 mongoDB

java怎么使用gson解析json字符串

你能避免 Gson 将“<”和“>”转换为 unicode 转义序列吗?