很多ASP.NET项目,尤其是使用了Ajax的项目,常常需要返回JSON格式的数据,网框架从3.5版本开始提供了JSON的序列化和反序列化工具,不过个人感觉不太好,用后来找了第三方的Newtonsoft.Json来用。再后来,在MVC4中,微软已经默认使用Json.NET (Newtonsoft。Json)来处理Json数据了。
JavaScript数值精度是32位,如果整数数度超过32位,就会被当作浮点数处理。换句话说,如果从服务端生成的Json,某个值是64位整数,传到前端JavaScript,再传回服务端,不做任何运算,都可能出现失真。做个实验:
比;var=123456789012345678 比;console.log(一个); 123456789012345680
很要命的一点是,数据库设计中常常会用长整型数字(64位)整数来作为主键,是一个非常重要而且不能有偏差的数据,比如,一个模型:
//c#匿名对象 新{ id: 123456789012345678 l, 名称:“詹姆斯” };
转换成JSON输出到前端是:
{" id ": 123456789012345678,“名字”:“詹姆斯”}
通过Ajax取得的对象输出就有点不妙了
.getJSON美元(“/api/测试”).done(函数(乔){ console.log(乔); }); {//对象id: 123456789012345680,名字:“詹姆斯”}
显然,这个对象修改数值之后再传回服务器,就会找不到主键,或者更新成错误的数据,造成一个不易发现的巨大错误。
解决办法当然是有的,JavaScript处理字符串的能力非常强,完全可以把服务器端的64位整数处理成字符串类型。不过Json。净默认是把长处理成数字类型的,如果要处理成字符串类型,需要自定义一个JsonConverter。
考虑到用十六进制表示的整数看起来比较整齐,所以定义一个HexLongConverter来转换长/ulong型数据与16进制表示的字符串。
公共类HexLongConverter: JsonConverter { 公共覆盖空白WriteJson (JsonWriter作家,对象的价值,JsonSerializer序列化器) {//由于CanConvert过滤,数据类型只可能是长或ulong//统一转换成长类型处理 ulong v=值?(长)(ulong)价值:(长)值; writer.WriteValue (v.ToString(“乘16”)); } 公共覆盖对象ReadJson (objectType JsonReader读者,类型、对象existingValue JsonSerializer序列化器) {//取得读到的十六进制字符串 十六进制字符串=读者。值作为字符串;//调用ToInt64扩展将字符串转换成型//ToInt64扩展方法后附 长v=hex.ToInt64 (NumberStyles。HexNumber 0 l);//将v转换成实际需要的类型ulong或长(不转换) 返回typeof (ulong)==objectType吗?(对象)(ulong) v:; } 公共覆盖bool CanConvert objectType(类型) {//只处理长和ulong两种类型的数据 开关(objectType.FullName) { 例“System.Int64”: 例“System.UInt64”: 返回true; 默认值: 返回错误; } } }
上面的代码用到了一个字符串的扩展方法ToInt32:
StringExtention公共静态类 { 公共静态int ToInt32(我这个字符串,NumberStyles风格, int defaultValue) { int ?值=https://www.yisu.com/zixun/me.ToInt32(风格); 返回值==零?defaultValue: value.Value; } }
在序列化或反序列化模型的时候,只需要加入HexLongConverter对象作为参数即可:
//序列化 json=JsonConvert字符串。SerializeObject(模型、新HexLongConverter ());//反序列化 SomeModal模型=JsonConvert.DeserializeObject(json,新的HexLongConverter));
相关链接:
(json。净)
- <李> http://json.codeplex.com/
李> <李> http://james.newtonking.com/json
李>