fastBinaryJSON






4.79/5 (77投票s)
基于fastJSON的二进制JSON序列化器(支持MonoDroid,netcore)
前言
代码现已托管在
CodePlex(使用Git源代码管理)(http://fastbinaryjson.codeplex.com/)- Github:https://github.com/mgholam/fastBinaryJSON
- Nuget:
fastBinaryJSON
引言
fastBinaryJSON
基于我的fastJSON
文章(https://codeproject.org.cn/Articles/159450/fastJSON)和代码,它是一个多态对象序列化器。fastBinaryJSON
的主要目的是提高数据传输和磁盘存储中数据的序列化和反序列化速度。它是为我即将推出的RaptorDB
- 文档数据库引擎而创建的,以追求性能。
特点
fastBinaryJSON
具有以下特性列表:
- 基于
fastJSON
代码库(非常快,多态)- 支持:HashTables、Dictionary、Generic Lists、Datasets,等等。
- 序列化速度通常提高2-10%,反序列化速度提高17%以上。
为什么?
你可能会问,为什么还需要一个序列化器,为什么不直接使用fastJSON
?答案很简单:性能。JSON是一个很棒的格式,但它存在以下问题:
- JSON是一种文本格式,因此在序列化时会丢失类型信息,这使得再次反序列化数据变得耗时。
为什么不用BSON?
你可能会问,为什么不直接使用BSON(http://bsonspec.org/)?答案如下:
- 查看上面网站上的规范,你会感到不知所措,因为它很难理解。
- 你会觉得规范随着时间而演变,许多编码部分已被弃用。
- BSON将长度编码到流中,这会膨胀数据。对于作者设想的用例来说,这可能没问题,但对于数据传输和存储来说,它只是让东西变得比实际需要更大。
- 由于长度前缀,数据对象的编码必须分两步完成:一次输出数据,第二次设置长度前缀。
我最初是从在fastJSON
上进行BSON转换开始的,但这变得太复杂了,所以被放弃了。
fastBinaryJSON如何编码数据?
JSON是一个极其简单的格式,因此fastBinaryJSON
采用了这种简单性,并添加了进行二进制序列化所需的组件。fastBinaryJSON
遵循与JSON规范(http://json.org)相同的规则,下表显示了数据的编码方式。
正如你从上面看到的,所有编码规则都与JSON相同,并且原始数据类型被赋予了1字节的标记来编码数据。因此,通用格式是:
TOKEN, { DATA } : where DATA can be 0 or more bytes
字符串
可以通过两种方式编码:UTF8或Unicode。UTF8更节省空间,而Unicode速度更快。
字符串
键或属性名称被编码为特殊的UTF8流,长度限制为255字节,以节省空间(你应该不会有问题,因为大多数属性名称都很短)。
v1.4.19 更改
在此版本中,添加了新的标记。
性能测试
为了了解fastBinaryJSON
与fastJSON
在性能上的差异,执行了以下测试。时间单位为**毫秒**,每个测试对1000个对象进行,重复5次,AVG列是测试的平均值,排除了第一个(受初始化时间影响)。
正如你在DIFF列([ fastJSON / fastBinaryJSON ])中看到的,序列化器性能至少提高了**2%**,反序列化器性能至少提高了**17%**,其中最大的差异是在DataSet
类型上,它包含大量数据行。
Using the Code
要使用fastBinaryJSON
,可以使用以下代码示例:
byte[] bytes = fastBinaryJSON.BJSON.ToJSON(obj);
byte[] bytes = fastBinaryJSON.BJSON.ToJSON(obj, true, true); // optimized dataset,
// unicode strings
object obj = fastBinaryJSON.BJSON.ToObject(bytes);
SalesInvoice obj = fastBinaryJSON.BJSON.ToObject<SalesInvoice>(bytes); // type is known
有3个参数控制序列化方式,可以在Instance
上设置,也可以像上面的示例一样按调用进行设置。
UseOptimizedDatasetSchema | 使用优化的格式序列化Dataset Schema(默认=True ) |
ShowReadOnlyProperties | 序列化ReadOnly 属性(默认=False ) |
UseUnicodeStrings | 对 |
附录 v1.3.14.1 - 参数化构造函数
从这个版本开始,fastBinaryJSON
现在可以处理没有默认构造函数的参数化构造函数类的反序列化,例如:
public class pctor
{
public pctor(int a) // pctor() does not exist
{
}
}
现在,为了做到这一点,fastBinaryJSON
使用了框架中的FormatterServices.GetUninitializedObject(type)
,它基本上只是为你的类型分配一个内存区域,并将它作为一个对象给你,同时跳过所有初始化,包括构造函数。虽然这非常快,但它有一个不幸的副作用,即忽略所有类初始化,如属性的默认值等。因此,如果你正在恢复对象的局部数据,你应该意识到这一点(如果所有数据都在JSON中并且与类结构匹配,那么你就没问题)。
要控制这一点,可以在BJSONParameters
中将ParametricConstructorOverride
设置为true
。
附录 v1.4.0 - 循环引用 & 破坏性更改
从这个版本开始,我修复了一个从一开始就一直困扰我的设计缺陷,即删除了BJSON.Instance
单例。这意味着你输入的代码更少,这总是件好事。坏处是,你需要在代码中进行查找和替换。
此外,我发现了一种非常简单快速的方法来支持循环引用的对象结构。因此,像下面的复杂结构将能够正确地序列化和反序列化(单元测试是CircularReferences()
)。
var o = new o1 { o1int = 1, child = new o3 { o3int = 3 }, o2obj = new o2 { o2int = 2 } };
o.o2obj.parent = o;
o.child.child = o.o2obj;
为此,fastBinaryJSON
会将循环引用替换为:
{"$i" : number } // number is an index for the internal reference
并且在二进制JSON的顶部添加一个$circular : true
,以便反序列化器能够识别。
附录 v1.4.19 - 类型化数组
在项目中使用fastBinaryJSON
代替BinaryFormatter
时,我发现以下代码在客户端失败:
public class DTO
{
public object Data;
}
// server side
var d = new DTO();
d.Data = new myclass[2]{ new myclass(), new myclass()};
var bytes = BJSON.ToBJSON(d);
TCP_SEND(bytes);
// client side
var bytes = TCP_READ();
DTO dto = BJSON.ToObject(bytes);
// obj.Data will be object[] containing 2 myclass
var obj = (myclass[]) dto.Data; // error here ( unable to convert object[] to myclass[] )
// in v1.4.19 obj.Data will be myclass[]
var obj = (myclass[]) dto.Data; // ok
从v1.4.19
开始,如果你将T[]
放入object
数据类型中,fastBinaryJSON
将能正确处理它,并在反序列化时得到预期的正确T[]
,就像使用BinaryFormatter
一样。
使用更少的内存
在此版本中,序列化器还将使用更少的内存,只使用一个MemoryStream
并将$types
放在stream
的末尾。这些更改是向后兼容的,不会破坏任何东西。
这些更改希望能帮助你处理大数据传输。
之前的版本
以下是fastBinaryJSON
之前版本的列表。
- 下载 fastBinaryJSON_v1.0.zip
- 下载 fastBinaryJSON_v1.1.zip
- 下载 fastBinaryJSON_v1.2.zip
- 下载 fastBinaryJSON_v1.3.zip
- 下载 fastBinaryJSON_v1.3.1.zip
- 下载 fastBinaryJSON_v1.3.2.zip
- 下载 fastBinaryJSON_v1.3.3.zip
- 下载 fastBinaryJSON_v1.3.4.zip
- 下载 fastBinaryJSON_v1.3.5.zip
- 下载 fastBinaryJSON_v1.3.7.zip
- 下载 fastBinaryJSON_v1.3.8.zip
- 下载 fastBinaryJSON_v1.3.9.zip
- 下载 fastBinaryJSON_v1.3.10.zip
- 下载 fastBinaryJSON_v1.3.11.zip
- 下载 fastBinaryJSON_v1.3.12.zip
- 下载 fastBinaryJSON_v1.3.13.zip
- 下载 fastBinaryJSON_v1.3.14.zip
- 下载 fastBinaryJSON_v1.3.14.1.zip
- 下载 fastBinaryJSON_v1.4.0.zip
- 下载 fastBinaryJSON_v1.4.1.zip
- 下载 fastBinaryJSON_v1.4.2.zip
- 下载 fastBinaryJSON_v1.4.3.zip
- 下载 fastBinaryJSON_v1.4.4.zip
- 下载 fastBinaryJSON_v1.4.6.zip
- 下载 fastBinaryJSON_v1.4.7.zip
- 下载 fastBinaryJSON_v1.4.8.zip
- 下载 fastBinaryJSON_v1.4.9.zip
- 下载 fastBinaryJSON_v1.4.10.zip
- 下载 fastBinaryJSON_v1.4.11.zip
- 下载 fastBinaryJSON_v1.4.12.zip
- 下载 fastBinaryJSON_v1.4.13.zip
- 下载 fastBinaryJSON_v1.4.14.zip
- 下载 fastBinaryJSON_v1.4.15.zip
- 下载 fastBinaryJSON_v1.4.16.zip
- 下载 fastBinaryJSON_v1.4.17.zip
- 下载 fastBinaryJSON_v1.4.18.zip
- 下载 fastBinaryJSON_v1.4.19.zip
- 下载 fastBinaryJSON_v1.4.20.zip
- 下载 fastBinaryJSON_v1.4.21.zip
- 下载 fastBinaryJSON_v1.4.23.zip
- 下载 fastBinaryJSON_v1.5.0.zip
- 下载 fastBinaryJSON_v1.5.1.zip
- 下载 fastBinaryJSON_v1.5.2.zip
- 下载 fastBinaryJSON_v1.5.3.zip
历史
- 首次发布:2012年3月25日
- 更新:2012年3月26日
- 添加了codeplex源代码管理链接
- 更新 v1.1:2012年5月26日
- 修复了datetime到本地时间的问题
- 添加了
BJSONParameters
- 添加了全局类型(与fastJSON的格式相反,以克服名称
string
的大小限制)
- 更新 v1.2:2012年7月24日
- 将反射代码重构到
Reflection
类中 - 添加了对顶层
struct
对象序列化/反序列化的支持
- 将反射代码重构到
- 更新 v1.3:2012年8月11日
- 修复了反射代码中的bug
- 添加了单元测试
- 将
ArrayList
更改为List<object>
- 更新了代码,使其与fastJSON类似
- 反序列化为
ToObject< Dictionary<T,V> >
- 反序列化为
ToObject< List<T> >
- 添加了
FillObject
方法
- 更新 v1.3.1:2012年8月16日
- 修复了
$types
和arrays
中的bug - 优化了
$types
的写入
- 修复了
- 更新 v1.3.2:2012年9月7日
- 修复了
null
对象序列化 - 为类添加了
sealed
关键字 - 修复了
SerializeNullValues=false
和末尾多余逗号的bug FillObject
支持嵌套类型
- 修复了
- 更新 v1.3.3:2012年9月17日
- 修复了反序列化零长度数组的bug
- 测试了德语区域设置的数字
- 更新 v1.3.4:2012年9月20日
- 单例使用
ThreadStatic
来处理并发(感谢Philip Jander) - 修复了当对象只有一个属性时输出中多余逗号的bug(感谢Philip Jander)
- 单例使用
- 更新 v1.3.5:2012年11月16日
- 添加了对顶层
DataSet
和DataTable
反序列化的支持(您必须使用ToObject<DataSet>(...)
) - 添加了
dataset
测试 - 添加了
MonoDroid
项目
- 添加了对顶层
- 更新 v1.3.7:2013年4月20日
customtype
现在内置了- 为
datetime
添加了UseUTCTimes
属性 - 将
properttype enum
替换为布尔值 - 使用
switch
代替链接的if
语句 - 统一了Silverlight和.NET的
DynamicMethod
SafeDictionary
的锁修复
- 更新 v1.3.8:2013年8月19日
- 添加了
static
字段和属性的序列化 - 修复了禁用输出中的扩展
- 修复了匿名类型的序列化
- 添加了对动态对象(dynamic objects)的支持
- 添加了
- 更新 v1.3.9:2013年8月27日
- 修复了动态对象和列表
- 修复了反序列化
Dictionary<T, List<V>>
和Dictionary<T, V[]>
- 为包含列表的字典添加了测试
- 更新 v1.3.10:2013年9月11日
- 修复了哈希表(hashtable)反序列化
- 为哈希表添加了测试
- 将getter列表更改为数组,性能提升约3%
- 删除了未使用的代码
- 更新 v1.3.11:2013年11月2日
- 添加了签名程序集
- 版本号将保持为1.0.0.0以兼容性兼容
- 文件版本将反映构建号
- 修复了反序列化为字典而不是
dataset
(当类型未定义时)的bug - 访问动态类型中数组内的属性,例如
d.arr[1].a
- 更新 v1.3.12:2013年11月23日
- 修复了动态JSON和根数组(如[1,2,3,4])的bug
- 修复了动态类型中数组内的对象(如[1,2,{"prop":90}])的bug
- 添加了对特殊集合的支持:
StringDictionary
、NameValueCollection
- 更新 v1.3.13:2014年1月10日
- 修复了与
const
属性和字段(即被忽略)一起工作的问题
- 修复了与
- 更新 v1.3.14:2014年3月22日
- 修复了从值和
string
创建enum
的问题 - 用
dictionary
替换了内部部分使用的safedictionary
,因此读取时没有锁 - 添加了自定义忽略属性(感谢Jared Thirsk)
- 使用
IsDefined
代替GetCustomAttributes
(感谢Andrew Rissing) - 将所有反射代码移出BJSON.cs
- 现在您可以反序列化非默认构造函数的类(感谢Anton Afanasyev)
- 修复了从值和
- 更新 v1.3.14.1:2014年3月29日
- 向
ParametricConstructorOverride
参数添加了用于控制非默认构造函数的功能
- 向
- 更新 v1.4.0:2014年4月7日
- *破坏性更改*:删除了
BJSON.Instance
单例 - 将BJSON的所有状态移至Reflection单例
- 所有BJSON接口现在都是
static
的 - 为
ToObject()
添加了BJSONParameters
重载 - 支持循环引用的对象结构
- 添加了循环测试
- *破坏性更改*:删除了
- 更新 v1.4.1:2014年5月2日
- 修复了
obj.List<List<object>>
和obj.List<object[]>
的bug - 为方法添加了代码智能提示帮助
- 添加了
ClearReflectionCache()
以重置所有内部结构
- 修复了
- 更新 v1.4.2:2014年8月16日
- 修复了循环引用的bug(感谢SonicThg)
- 更新 v1.4.3:2014年10月6日
- 修复了反序列化类中
struct
属性的bug
- 修复了反序列化类中
- 更新 v1.4.4:2014年10月23日
- 修复了反序列化私有设置和无设置属性的bug
- 为上述情况添加了
ReadonlyTest()
测试
- 更新 v1.4.6:2015年1月24日
- 修复了序列化
static
字段和属性的bug - 跳过对象上的索引器属性(感谢scymen)
- 修复了序列化
- 更新 v1.4.7:2015年2月24日
- 修复了
byte[]
作为Dictionary
键的bug(感谢Stanislav Lukeš)
- 修复了
- 更新 v1.4.8:2015年3月6日
- 修复了
public static properties
的bug
- 修复了
- 更新 v1.4.9:2015年4月27日
- 支持多维数组(感谢wmjordan)
- 更新 v1.4.10:2015年5月17日
- 添加了
BJSONParameters.SerializerMaxDepth
- 性能优化(感谢wmjordan)
- 添加了
BJSONSerializer.Dispose()
以消除编译器警告
- 添加了
- 更新 v1.4.11:2015年5月31日
- 添加了对
char
类型的支持 - 增强了
dynamic
对象处理(感谢Justin Dearing)
- 添加了对
- 更新 v1.4.12:2016年3月15日
- 清理了
using
语句 - bug修复:边缘情况
CreateArray()
时bt为null -> 默认为typeof(object)
- 清理了
- 更新 v1.4.13:2016年6月19日
- 修复了
ToObject<Dictionary<string, List<X>>>()
的bug(感谢sleiN13) - 修复了
CreateStringKeyDictionary()
的bug(感谢John Earnshaw) - 类型访问优化
- 测试重构
- 修复了
- 更新 v1.4.14:2016年7月20日
- 修复了匿名类型中
DateTime
的InvalidProgramException
bug(感谢skottmckay) - 修复了损坏的自定义类型处理程序(**抱歉大家**)
- 为自定义类型添加了测试
- 修复了
Dictionary
值中的byte[]
,并添加了测试
- 修复了匿名类型中
- 更新 v1.4.15:2016年7月23日
- 将
reflection.cs
与fastJSON
同步 - 修复了只读属性输出的bug
- 为只读属性添加了测试
- 将
NonSerialized
添加到要忽略的默认属性列表中 - 支持
ExpandoObject
序列化,并添加了测试
- 将
- 更新 v1.4.16:2016年9月3日
- 添加了对接口对象属性的支持(感谢DrDeadCrash)
- 更新 v1.4.17:2016年9月12日
- 修复了嵌套字典
D<,D<,>>
的bug
- 修复了嵌套字典
- 更新 v1.4.18:2016年10月21日
- 修复了枚举动态对象的bug
- 更新 v1.4.19:2016年12月20日
- 为类型化数组添加了
TOKENS.ARRAY_TYPED
- 正确地将
t[]
反序列化为object
,而不是object[]
- 添加了
BJSONParameters.UseTypedArrays
来控制上述功能(默认=true
) - 重命名了主解决方案文件
- 添加了
TOKENS.TYPES_POINTER
,用于将$types
放在字节流的末尾 - 优化序列化内存使用
- 如果将
DataSet
放入object
中,它将正确反序列化
- 为类型化数组添加了
- 更新 v1.4.20:2017年8月13日
- 添加了
TimeSpan
- 添加了数字限制测试
- 添加了
- 更新 v1.4.21:2018年1月19日
- 修复了反序列化带类型信息的对象数组的bug
- 为上述情况添加了测试
- 通过单独的项目支持.NET Core和netstandard2.0
- 更新 v1.4.23:2018年5月26日
- 修复了在类中更改
BJSONParameters.UsingGlobalTypes
时影响原始值的副作用 - 修复了在没有扩展的情况下使用泛型
ToObject<>
反序列化嵌套Dictionary
的bug - 修复了根
enum
反序列化的bug(感谢al6uiz) - 支持非公共setter /只读属性(感谢rbeurskens)
- 将reflection.cs与
fastJSON
统一
- 修复了在类中更改
- 更新 v1.5.0:2018年8月8日
- 将.NET 3.5项目移至单独的文件夹,以避免冲突的obj构建
- 沿用了fastjson风格的优化
- 主要的
string
优化,使用unicodestring
时速度提升约46% - * 输出字节(使用类型化数组时)存在破坏性更改 *
- 更新 v1.5.1:2018年8月23日
- 修复了快速创建没有容量构造函数的列表
- 修复了.NET35项目中的签名
- 统一了Reflection.cs
- 向后兼容v1.4类型化数组数据字节,使用
BJSONParameters.v1_4TypedArray
- * 如果使用RegisterCustomType(),则存在运行时破坏性更改 *
- 更新 v1.5.2:2019年2月25日
- 修复了包含
sbyte
数据的datasets
的bug
- 修复了包含
- 更新 v1.5.3:2019年6月23日
- 将Reflection.cs与
fastJSON
v2.2.5同步
- 将Reflection.cs与
- 更新 v2.3.0 :2019年10月26日
- 周五13号json攻击检查