一种简单,轻量,灵活的C#对象转Json对象的方案(下)
2013-08-23 23:00
393 查看
性能优化
JsonBuilder第一版对一般对象的是进行实时反射的,所以性能不会很好,所以我首先想到的是优化他的性能
看我前几天发表过一篇《[源码]Literacy 快速反射读写对象属性,字段》的文章,这东西的效率不错,用来代替反射正好。
我把优化后的类取名QuickJsonBuilder
在继承JsonBuilder的基础上,我仅仅需要重写一个方法
像这样我很简单的将原来的实时反射改成了Literacy
但是这样显然并不能保证性能,所以我还要加一个缓存
缓存本身是全局静态的,所以为了防止多线程并发的问题,特别加了锁
再为了它能性能能够好上那么一点点(更多的是为了自己的强迫症吧....),再修改一些地方
好了来看看他和他父亲在性能上的差异:
测试代码和《几个常用Json组件的性能测试》中的是一样的,
不过今天在自己的电脑上运行了,感觉和昨天的测试结果的差异还是有些大的,所以还是那句话:测试结果因配置不同会有所出入,此结果仅供参考
功能扩展
相比较性能优化来说 这个要更重要一些,随着现在硬件各种不值钱,性能上的问题绝对可以在硬件上解决,而功能不足却是大多数时候我们放弃一个现成类库的原因
在这个时候一个类库是否可扩展就显得尤为重要了。
先来看一个栗子
将DataSet转为Json对象
随便来个简单个DataSet
再来看看每个组件的转换结果
各组件转换结果
我们可以很清楚的发现每个组件都有各自的转换方式,结果都不相同
fastJSON.NET 结果中每列的"列名"丢失了
Jayrock.Json 算是比较标准的格式了
Newtonsoft.Json 数据格式和Jayrock.Json类似,但是时间格式太蛋疼了,造成的结果就是这个字符串直接在网页js中运行是不可能的,需要2次转换
TestJavaScriptSerializer 报错,无法转换
TestServiceStack 报错,无法转换
JsonBuilder,因为是我自己写的,所以有自己的格式,我习惯将Table转换为2个部分一个columns,一个rows,因为在行数多的情况下,列名每次都重复会增加数据大小
以上几个组件的结果 可能可以通过参数设置,我不确定 但即使是参数设定,也只不过是选择几种预置的格式罢了。
这时候JsonBuilder灵活性就显现出来了
假设我现在的项目有以下需求:
DataTable转换需要可以在,Jayrock.Json和JsonBuilder格式之间切换
DateTime可以在 Data,Time,DataTime 3种模式中切换
Guid要去掉中间的连字符(-)
true,false要转换为1,0
OK 现在我需要重写4个方法 AppendDataTable(如果有必要也一起重写AppendDataView),AppendDateTime,AppendGuid,AppendBoolean
然后就可以调用了
结果
完整Demo下载
点击下载
Literacy源码下载
源码下载
JsonBuilder第一版对一般对象的是进行实时反射的,所以性能不会很好,所以我首先想到的是优化他的性能
看我前几天发表过一篇《[源码]Literacy 快速反射读写对象属性,字段》的文章,这东西的效率不错,用来代替反射正好。
我把优化后的类取名QuickJsonBuilder
在继承JsonBuilder的基础上,我仅仅需要重写一个方法
public class QuickJsonBuilder : JsonBuilder { protected override void AppendOther(object obj) { Literacy lit = new Literacy(obj.GetType()); string fix = ""; Buff.Append('{'); foreach (var p in lit.Property) { Buff.Append(fix); AppendKey(p.Name, false); AppendObject(p.GetValue(obj)); fix = ','; } Buff.Append('}'); } }
像这样我很简单的将原来的实时反射改成了Literacy
但是这样显然并不能保证性能,所以我还要加一个缓存
static Dictionary<Type, Literacy> _LitCache = new Dictionary<Type, Literacy>(); protected override void AppendOther(object obj) { Literacy lit; Type type = obj.GetType(); if (_LitCache.TryGetValue(type, out lit) == false) { lock (_LitCache) { if (_LitCache.TryGetValue(type, out lit) == false) { lit = new Literacy(type); _LitCache.Add(type, lit); } } } string fix = ""; Buff.Append('{'); foreach (var p in lit.Property) { Buff.Append(fix); AppendKey(p.Name, false); AppendObject(p.GetValue(obj)); fix = ','; } Buff.Append('}'); }
缓存本身是全局静态的,所以为了防止多线程并发的问题,特别加了锁
再为了它能性能能够好上那么一点点(更多的是为了自己的强迫症吧....),再修改一些地方
static Dictionary<Type, Literacy> _LitCache = new Dictionary<Type, Literacy>(); protected override void AppendOther(object obj) { Literacy lit; Type type = obj.GetType(); if (_LitCache.TryGetValue(type, out lit) == false) { lock (_LitCache) { if (_LitCache.TryGetValue(type, out lit) == false) { lit = new Literacy(type); _LitCache.Add(type, lit); } } } Buff.Append('{'); var ee = lit.Property.GetEnumerator(); if (ee.MoveNext()) { AppendKey(ee.Current.Name, false); AppendObject(ee.Current.GetValue(obj)); while (ee.MoveNext()) { Buff.Append(','); AppendKey(ee.Current.Name, false); AppendObject(ee.Current.GetValue(obj)); } } Buff.Append('}'); }
好了来看看他和他父亲在性能上的差异:
测试代码和《几个常用Json组件的性能测试》中的是一样的,
I7-2630 4核8线程 主频2.0 内存 1600 4G*2 没有显卡 硬盘 闪迪 msata 128 r:500m/s w:350m/s
不过今天在自己的电脑上运行了,感觉和昨天的测试结果的差异还是有些大的,所以还是那句话:测试结果因配置不同会有所出入,此结果仅供参考
功能扩展
相比较性能优化来说 这个要更重要一些,随着现在硬件各种不值钱,性能上的问题绝对可以在硬件上解决,而功能不足却是大多数时候我们放弃一个现成类库的原因
在这个时候一个类库是否可扩展就显得尤为重要了。
先来看一个栗子
将DataSet转为Json对象
随便来个简单个DataSet
DataTable dt1 = new DataTable("User"); dt1.Columns.Add("UID", typeof(Guid)); dt1.Columns.Add("Name", typeof(string)); dt1.Columns.Add("Birthday", typeof(DateTime)); dt1.Columns.Add("Sex", typeof(int)); dt1.Columns.Add("IsDeleted", typeof(bool)); dt1.Rows.Add(Guid.NewGuid(), "blqw", DateTime.Parse("1986-10-29"), 1, false); dt1.Rows.Add(Guid.NewGuid(), "小明", DateTime.Parse("1990-1-1"), 1, false); dt1.Rows.Add(Guid.NewGuid(), "小华", DateTime.Parse("1990-2-2"), 0, false); DataTable dt2 = new DataTable("UserInfo"); dt2.Columns.Add("ID", typeof(int)); dt2.Columns.Add("UID", typeof(Guid)); dt2.Columns.Add("Address", typeof(string)); dt2.Columns.Add("ZipCode", typeof(int)); dt2.Rows.Add(1, dt1.Rows[0][0], "广州", 100000); dt2.Rows.Add(2, dt1.Rows[1][0], "上海", 200000); dt2.Rows.Add(3, dt1.Rows[2][0], "背景", 300000); DataSet ds = new DataSet(); ds.Tables.Add(dt1); ds.Tables.Add(dt2);
再来看看每个组件的转换结果
各组件转换结果
我们可以很清楚的发现每个组件都有各自的转换方式,结果都不相同
fastJSON.NET 结果中每列的"列名"丢失了
Jayrock.Json 算是比较标准的格式了
Newtonsoft.Json 数据格式和Jayrock.Json类似,但是时间格式太蛋疼了,造成的结果就是这个字符串直接在网页js中运行是不可能的,需要2次转换
TestJavaScriptSerializer 报错,无法转换
TestServiceStack 报错,无法转换
JsonBuilder,因为是我自己写的,所以有自己的格式,我习惯将Table转换为2个部分一个columns,一个rows,因为在行数多的情况下,列名每次都重复会增加数据大小
以上几个组件的结果 可能可以通过参数设置,我不确定 但即使是参数设定,也只不过是选择几种预置的格式罢了。
这时候JsonBuilder灵活性就显现出来了
假设我现在的项目有以下需求:
DataTable转换需要可以在,Jayrock.Json和JsonBuilder格式之间切换
DateTime可以在 Data,Time,DataTime 3种模式中切换
Guid要去掉中间的连字符(-)
true,false要转换为1,0
OK 现在我需要重写4个方法 AppendDataTable(如果有必要也一起重写AppendDataView),AppendDateTime,AppendGuid,AppendBoolean
using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; namespace blqw { class MyJsonBuilder : QuickJsonBuilder { /// <summary> 表风格 /// <para> 默认 { columns:[colname,colname2],rows:[[x,x],[y,y]] } </para> /// <para> 1 [{ colname:x,colname2:x },{ colname:y,colname2:y }] </para> /// </summary> public int TableStyle { get; set; } /// <summary> 时间风格 /// <para> 默认 yyyy-MM-dd HH:mm:ss </para> /// <para> 1 yyyy-MM-dd </para> /// <para> 2 HH:mm:ss </para> /// </summary> public int DateTimeStyle { get; set; } protected override void AppendDateTime(DateTime value) { switch (DateTimeStyle) { case 1: Buff.Append('"'); Buff.Append(value.ToString("yyyy-MM-dd")); Buff.Append('"'); break; case 2: Buff.Append('"'); Buff.Append(value.ToString("HH:mm:ss")); Buff.Append('"'); break; default: base.AppendDateTime(value); break; } } protected override void AppendGuid(Guid value) { Buff.Append('"'); Buff.Append(value.ToString("N")); Buff.Append('"'); } protected override void AppendBoolean(bool value) { base.AppendNumber(value.GetHashCode()); } protected override void AppendDataTable(System.Data.DataTable table) { if (TableStyle == 1) { Buff.Append('['); var fix = ""; foreach (DataRow row in table.Rows) { Buff.Append(fix); var fix2 = ""; Buff.Append('{'); foreach (DataColumn col in table.Columns) { Buff.Append(fix2); AppendKey(col.ColumnName,false); AppendObject(row[col]); fix2 = ","; } Buff.Append('}'); fix = ","; } Buff.Append(']'); } else { base.AppendDataTable(table); } } } }
然后就可以调用了
MyJsonBuilder jb = new MyJsonBuilder(); Console.WriteLine("TableStyle=1 ; DateTimeStyle=1"); jb.TableStyle = 1; jb.DateTimeStyle = 1; Console.WriteLine(jb.ToJsonString(ds)); Console.WriteLine(""); Console.WriteLine("TableStyle=0 ; DateTimeStyle=2"); jb.TableStyle = 0; jb.DateTimeStyle = 2; Console.WriteLine(jb.ToJsonString(ds));
结果
TableStyle=1 ; DateTimeStyle=1 {"User":[{"UID":"0f3f70f0939546d8803d8cd0ef4de8ec","Name":"blqw","Birthday":"1986-10-29","Sex":1,"IsDeleted":0},{"UID":"72489efcbc694801a358b697414892ee","Name":"小明","Birthday":"1990-01-01","Sex":1,"IsDeleted":0},{"UID":"865cddbb1f0c427e97a724844c35a83d","Name":"小华","Birthday":"1990-02-02","Sex":0,"IsDeleted":0}],"UserInfo":[{"ID":1,"UID":"0f3f70f0939546d8803d8cd0ef4de8ec","Address":"广州","ZipCode":100000},{"ID":2,"UID":"72489efcbc694801a358b697414892ee","Address":"上海","ZipCode":200000},{"ID":3,"UID":"865cddbb1f0c427e97a724844c35a83d","Address":"背景","ZipCode":300000}]} TableStyle=0 ; DateTimeStyle=2 {"User":{"columns":["UID","Name","Birthday","Sex","IsDeleted"],"rows":[["0f3f70f0939546d8803d8cd0ef4de8ec","blqw","00:00:00",1,0],["72489efcbc694801a358b697414892ee","小明","00:00:00",1,0],["865cddbb1f0c427e97a724844c35a83d","小华","00:00:00",0,0]]},"UserInfo":{"columns":["ID","UID","Address","ZipCode"],"rows":[[1,"0f3f70f0939546d8803d8cd0ef4de8ec","广州",100000],[2,"72489efcbc694801a358b697414892ee","上海",200000],[3,"865cddbb1f0c427e97a724844c35a83d","背景",300000]]}} 请按任意键继续. . .
完整Demo下载
点击下载
Literacy源码下载
源码下载
相关文章推荐
- 一种简单,轻量,灵活的C#对象转Json对象的方案
- 一种简单,轻量,灵活的C#对象转Json对象的方案(上)
- 一种简单,轻量,灵活的C#对象转Json对象的方案(续)
- 一种简单,轻量,灵活的C#对象转Json对象的方案(续)
- 一种简单,轻量,灵活的C#对象转Json对象的方案
- 一种简单,轻量,高性能Json对象设计方案
- C# 对象与JSON串互相转换
- Newtonsoft.Json 将C#对象转化为json格式
- asp.net MVC接收前端传递的复杂json对象的简单处理方法
- 在C# 2.0上写另外一种语言来创建对象
- js(十四)——简单对象创建和json
- C# DataTable 对象转换成Json时 出现 序列化类型为“System.Reflection.Module”的对象时检测到循环引用 的错误!
- C# Json简单处理
- 推荐一个简单、轻量、功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler
- C#将json字符串解析成对象
- C#中对象,字符串,dataTable、DataReader、DataSet,对象集合转换成Json字符串方法。
- Json字符串和Json对象的简单总结
- 简单json对象for asp
- c#实现ajax通信:向后台发送JSON字符串,接收响应字符串,并转换为对象