Gson deserialization, the ultimate solution for integers to decimals
1. Scenario display
When using gson for deserialization (json to java object), you may encounter that the value corresponding to the key is an integer, but after deserialization, it becomes a decimal (add .0 after it).
how to solve this problem?
2.Specific analysis
Preparation
public class Number {
private byte b;
private short s;
private int i;
private long l;
private double d;
private float f;
private Byte B2;
private Short S2;
private Integer I2;
private Long L2;
private Double D2;
private Float F2;
private BigDecimal bd;
private BigInteger gi;
}
Let's first review the specific usage scenarios where this happens.
Now, there is such a requirement:
To convert a json array into a List, Gson's implementation syntax is as follows:
new Gson().fromJson(json, new TypeToken<List<T>>(){
}.getType());
The following three calling methods will cause the integer to become a decimal:
Number number = new Number((byte)1, (short)2, 3, 4L, 5D, 6F);
List<Number> numbers = new ArrayList<>(1);
numbers.add(number);
String gsonStrs = new Gson().toJson(numbers);
System.out.println(gsonStrs);
// 错误方式一:不加泛型限制
List<Number> numberList = new Gson().fromJson(gsonStrs, new TypeToken<List>(){
}.getType());
System.out.println(numberList);
// 错误方式二:使用反射
numberList = new Gson().fromJson(gsonStrs, new TypeToken<List<?>>(){
}.getType());
System.out.println(numberList);
Mistake 3: Package usage
List<Number> numberList = JsonUtils.toJavaBeansByGson(gsonStrs);
System.out.println(numberList);
The execution results are as follows:
3. Solutions
The first two ways to realize the mistakes, most people will not make such mistakes.
The problem lies in the third type, which is a bit of a surprise.
Originally, I thought about encapsulating Gson again, so that it can be called directly next time, without writing such a long code, the result is:
Self-defeating!
Let's add specific generic restrictions, and then look at the execution results.
List<Number> numberList = new Gson().fromJson(gsonStrs, new TypeToken<List<Number>>(){
}.getType());
System.out.println(numberList);
We can see that this time there is no problem.
Method 1: List must be limited by specific entity classes;
So, if you want to use gson to convert the json array into a list entity class, the list must specify a specific generic class.
In other words, the way gson converts the json array into a list cannot be re-encapsulated.
If it is packaged and used like wrong way 3, you must ensure that your java entity class does not contain numeric type attributes, otherwise, it will all be converted into decimal Double types.
Method 2: Repackage.
Since the above method cannot be encapsulated again, we might as well change our thinking:
Since there are bugs in the implementation, why don't we just use it?
Come on, let's try to see if there is any problem with Gson converting json string to java object:
Number number = new Number((byte)1, (short)2, 3, 4L, 5D, 6F);
String gsonStr = new Gson().toJson(number);
System.out.println(gsonStr);
Number numberGson = new Gson().fromJson(gsonStr, Number.class);
System.out.println(numberGson.toString());
We can see that there is no problem converting json strings to java objects through gson conversion.
Then, we can: first convert the json array string to a json array, then traverse it to convert it (json object) into a java object, and stuff it into the list.
/*
* JsonArray字符串转List(Gson)
* @description:
* @date: 2023/8/19 19:21
* @param: jsons json数组字符串
* @param: clazz 实体类
* @return: java.util.List<T>
*/
@Nullable
public static <T> List<T> toJavaBeansByGson(String jsons, Class<T> clazz) {
// net.sf.json
JSONArray jsonArray = JSONArray.fromObject(jsons);
if (arraysIsEmpty(jsonArray)) return null;
List<T> beans = new ArrayList<>(jsonArray.size());
jsonArray.forEach(netJson -> beans.add(new Gson().fromJson(netJson.toString(), clazz)));
return beans;
}
test
Number number = new Number((byte)1, (short)2, 3, 4L, 5D, 6F);
List<Number> numbers = new ArrayList<>(1);
numbers.add(number);
String gsonStrs = new Gson().toJson(numbers);
System.out.println(gsonStrs);
List<Number> numberList = JsonUtils.toJavaBeansByGson(gsonStrs, Number.class);
System.out.println(numberList);
We can see that the conversion of numeric types is no problem.
Summarize:
When we need to use gson to convert strings to lists in a small amount, we can use the first method;
If there are a large number of positions that need to be converted with gson, you can consider using the second implementation.
write at the end
If anyone finds any mistakes in the article or needs to add more content, please leave a message! ! !
Let me share with you: the most practical self-discipline is saving money, the most eye-catching self-discipline is fitness, the healthiest self-discipline is going to bed early, the most temperamental self-discipline is reading, and the best self-discipline is financial independence.