Json.NET特殊处理64位长整型数据

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

  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<model>(json, new HexLongConverter));


相关链接:

[Json.NET]

Json.NET特殊处理64位长整型数据,布布扣,bubuko.com

时间: 2024-10-06 13:53:45

Json.NET特殊处理64位长整型数据的相关文章

(DateTime)日期型数据转换成C#长整型数据

这里介绍日期型数据转换成C#长整型数据,由于各种数据库对日期型的定义和处理是不一样的,各种语言对日期型数据的定义的处理也各不相同,因为,我宁愿将日期型数据转换成长整型数据再保存到数据库中. AD:51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验 C#语言还是比较常见的东西,这里我们主要介绍日期型数据转换成C#长整型数据,包括介绍DateTime 的构造函数等方面. 转自:http://developer.51cto.com/art/200908/147684.htm 日期型数

PHP长整型在32位系统中强制转化溢出

CleverCode近期遇到一个PHP项目整形转化问题,mysql有一个字段id是bigint的,里面有长整型,如id = 5147486396.可是php代码因为历史原因却部署在多台机器中,当中A机器32位系统中,B机器64系统中.如今的问题是64系统中页面訪问正常.32位系统中訪问出错了.原因是php整形溢出. 1 A机器演示 1.1 获取A机器系统位数 # getconf LONG_BIT 1.2 整形转化代码 <? php $id = 5147486396; echo '$id:'.$i

整形_长整型的使用范围和规则

整形_长整型的使用范围(两个数的乘积) 1. I.unsigned long :%lu ; unsigned long long :%llu. II.当结果在输出格式范围之内,则输出正确,否则不正确. III. 当结果在输出格式范围之外,则输出的值与结果模(变量类型的大小的值)相等,且输出的值在变量类型的范围内.这里若结果大于2^64,则上述结论不正确. Code: 1 #include <stdio.h> 2 #include <stdlib.h> 3   4 int main(

【c语言】把一个长整型给一个字符指针

// 把一个长整型给一个字符指针,修改的时候只修改了一个字节,结果会是一个很大的随机数 // 并不能通过这种方式给长整型赋值1 #include <stdio.h> void VarInit(unsigned char* pucArg) { *pucArg = 1; return; } int main() { unsigned long ulGlobal; VarInit((unsigned char*)&ulGlobal); printf("%lu\n", ul

Java把长整型时间转成字符串日期

数据库里存放的是timestamp格式,前端取得后是这种:1436255550710长整型时间截转换成"2015-07-07"这种格式呢? import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class Test { /** * Java把长整型时间转成字符串日期 * @param args * @throws IOException */ public

WIN7系统 64位出现 Net Framework 数据提供程序要求 Microsoft Data Access Components(MDAC).

WIN7系统 64位出现  Net Framework 数据提供程序要求 Microsoft Data Access Components(MDAC).请安装 Microsoft Data Access Components(MDAC)2.6或更高的版本.怎么解决,已经下载了2.8版本安装了,但是还是不顶用. 2015-12-02 10:51网友采纳 这应该是你安装的系统有精简过系统文件,导致安装一些程序缺乏文件出错.换个系统吧.可到我的系统贴吧下载GHO系统与GHO安装工具,可以在进入现在的系

Python 数值类型(整型、长整型、浮点型、复数型)

一.整型 In [1]: a = 123 # 定义整数类型 In [2]: type(a) # 查看数据类型 Out[2]: int -2147483648 —— 2147483647 # 整型的取值范围,如果超过了这个范围则成为长整型 二.长整型 In [7]: a = 123456789123456789123456789 # 定义长整型 In [8]: type(a) # 查看数据类型 Out[8]: long In [9]: a # 长整型后面会带有字母(l或L)以标识这是长整型 Out

php长整型原始输出

今天调用webservice时返回一个字段是int64 长整型 原始的数值应该是 190000002101056096 而php返回时转成 1.9000000210106E+17 当传入另一个接口就报错了 解决方法 $c=1.9000000210106E+17; 1 number_format() number_format($c,0,'','') 2 sprintf sprintf("%.0f",$c);

整数、长整型、浮点型、字符串

如: 18.73.84 每一个整数都具备如下功能: int 二.长整型 可能如:2147483649.9223372036854775807 每个长整型都具备如下功能: long 三.浮点型 如:3.14.2.88 每个浮点型都具备如下功能: float 四.字符串 如:'wupeiqi'.'alex' 每个字符串都具备如下功能: str