今天是1024节,写篇博客纪念下(其实就是想点亮1024勋章,哈哈哈),想到前段时间做flink的数据采集遇到的json转换数值精度问题导致消费端数据转换异常
逻辑很简单,就是要将一段json格式的报文转成map,随手用了Gson来转换:
Map map = gson.fromJson(mapJson,Map.class);
报文中的value值是整型(比如1024),但是转换完就变成了1024.0,这样就导致了消费端转Long型的过程中报数据转换异常,
所以对于整型数值的用Gson不行,试了下用fastjson转换:
Map map = (Map)JSON.parse(mapJson);
结果输出1024,保留原样输出?如果是float类型的数据呢?又试了下,发现1024.0用fastjson转换完变成了1024,小数点丢失了,接着用Gson转换精度没有丢失,浮点型用Gson转换没问题。
大家在遇到json报文解析的时候,根据自己的业务需要来选择不同的方式,那么如果既有int型又有float型数据怎么办?
Gson支持添加自定义解析方案,可以使用GsonBuilder的registerTypeAdapter和registerTypeHierarchyAdapter。前者只针对设置的类进行序列化及反序列化,后者可以对设置的类及其子类进行序列化。可以添加的解析类的类型包括JsonSerializer、JsonDeserializer和TypeAdapter这三个接口的实现类。下面是一个使用自定义的JsonDeserializer方案:
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
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.JsonObject;
import com.google.gson.JsonParseException;
public class GsonDoubleInteger {
public static Gson getGson() {
Gson gson = new GsonBuilder().registerTypeAdapter(HashMap.class, new JsonDeserializer<HashMap>() {
@Override
public HashMap<String, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
HashMap<String, Object> resultMap = new HashMap<>();
JsonObject jsonObject = json.getAsJsonObject();
Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for (Map.Entry<String, JsonElement> entry : entrySet) {
resultMap.put(entry.getKey(), entry.getValue());
}
return resultMap;
}
}).create();
return gson;
}
@SuppressWarnings("unchecked")
public static void main(String[] args) {
String flink = "{ fa: 1024, fb: 1024.0 }";
HashMap<String, Object> map = getGson().fromJson(flink, HashMap.class);
System.out.println(map);
}
}
执行结果:
是不是很完美,以后遇到类似的报文解析或者接口验签等对数据准确性要求比较高的就可以用该方法!
今天是1024节,祝所有的程序员小哥哥小姐姐们节日快乐!