Json.NET特殊处理64位长整型数据-创新互联

很多ASP.NET项目,尤其是使用了Ajax的项目,常常需要返回JSON格式的数据。.NET框架从3.5版本开始提供了JSON的序列化和反序列化工具,不过个人感觉不太好用,后来找了第三方的Newtonsoft.Json来用。再后来,在MVC4中,微软已经默认使用Json.NET(Newtonsoft.Json)来处理JSON数据了。

创新互联专注于企业成都全网营销推广、网站重做改版、全州网站定制设计、自适应品牌网站建设、H5页面制作商城建设、集团公司官网建设、外贸营销网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为全州等各大城市提供网站开发制作服务。

JavaScript数值精度是32位,如果整数数度超过32位,就会被当作浮点数处理。换句话说,如果从服务端生成的JSON,某个值是64位整数,传到前端JavaScript,再传回服务端,不做任何运算,都可能出现失真。做个实验:

> var a = 123456789012345678 > console.log(a); 123456789012345680

很要命的一点是,数据库设计中常常会用bigint(64位)整数来作为主键,是一个非常重要而且不能有偏差的数据,比如,一个模型:

// C# 匿名对象 new { id: 123456789012345678L, name: "James" };

转换成JSON输出到前端是:

{"id":123456789012345678,"name":"James"}

通过Ajax取得的对象输出就有点不妙了

$.getJSON("/api/test").done(function(jo) { console.log(jo); }); // Object {id: 123456789012345680, name: "James"}

显然,这个对象修改数值之后再传回服务器,就会找不到主键,或者更新成错误的数据,造成一个不易发现的巨大BUG。

解决办法当然是有的,JavaScript处理字符串的能力非常强,完全可以把服务器端的64位整数处理成字符串类型。不过 Json.NET 默认是把 long 处理成 number 类型的,如果要处理成 string 类型,需要自定义一个JsonConverter。

考虑到用十六进制表示的整数看起来比较整齐,所以定义一个HexLongConverter来转换long/ulong型数据与16进制表示的字符串。

public class HexLongConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 由于CanConvert过滤,数据类型只可能是long或ulong // 统一转换成long类型处理 long v = value is ulong ? (long)(ulong)value : (long)value; writer.WriteValue(v.ToString("X16")); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 取得读到的十六进制字符串 string hex = reader.Value as string; // 调用ToInt64扩展将字符串转换成long型 // ToInt64扩展方法后附 long v = hex.ToInt64(NumberStyles.HexNumber, 0L); // 将v转换成实际需要的类型 ulong 或 long(不转换) return typeof (ulong) == objectType ? (object) (ulong) v : v; } public override bool CanConvert(Type objectType) { // 只处理long和ulong两种类型的数据 switch (objectType.FullName) { case "System.Int64": case "System.UInt64": return true; default: return false; } } }

上面的代码用到了一个string的扩展方法ToInt32:

public static class StringExtention { public static int ToInt32(this string me, NumberStyles style, int defaultValue) { int? value = me.ToInt32(style); return value == null ? defaultValue : value.Value; } }

在序列化或反序列化模型的时候,只需要加入HexLongConverter对象作为参数即可:

// 序列化 string json = JsonConvert.SerializeObject(model, new HexLongConverter()); // 反序列化 SomeModal model = JsonConvert.DeserializeObject(json, new HexLongConverter));


相关链接:

[Json.NET]

  • http://json.codeplex.com/

  • http://james.newtonking.com/json

另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


网站题目:Json.NET特殊处理64位长整型数据-创新互联
网站URL:http://ybzwz.com/article/ccdhsg.html