Newtonsoft.Json使用总结


csAxp 河北工业大学 软件工程与理论 Newtonsoft.Json 使用总结 编辑:虾皮 目录 初识JSON.........................................................................................................................................2 在ASP .NET中使用JSON .................................................................................................................2 NET 2.0 使用JSON.net 进行反序列化..........................................................................................3 Newtonsoft.Json处理日期问题........................................................................................................5 JSON修饰标签,日期序列化 .........................................................................................................5 JSON集合序列化.............................................................................................................................7 JSON回调方法修饰标签.................................................................................................................9 JSON序列化错误处理...................................................................................................................12 赠人玫瑰,手留余香。 1 csAxp 初识JSON 本篇介绍 JSON 的基础知识。在没有接触 AJAX 之前我还不知道什么是 JSON,在读 Jeffrey Zhao 的《深入 Atlas 系列》时才看到这个词,所以有必要了解一下 JSON。这里我结 合今天初浅的认识及一个小练习记录我的学习。 JSON 是什么? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。 同时也易于机器解析和生成。它基于 JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON 采用完全独立于语言的文本格式,但是也使用了类似于 C 语言 家族的习惯(包括 C, C++, C#, Java, JavaScript, Perl, Python 等)。这些特性使 JSON 成为理想 的数据交换语言。 JSON 建构于两种结构: 1)“名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为 对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有 键列表(keyed list),或者关联数组 (associative array)。 2)值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。 这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使 得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。 有关 JSON 的更多介绍,访问它的官方网站:http://www.json.org 用 JSON 表示如下: {"city":"Beijing","street":" Chaoyang Road ","postcode":100025} 其中 Value 也可以是另一个 Object 或者数组,因此,复杂的 Object 可以嵌套表示,例如, 一个 Person 对象包含 name 和 address 对象,可以表示如下: {"name":"Michael","address": {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}} 在ASP.NET中使用JSON Json.NET 的简单介绍 首先介绍一个为方便在.NET 中使用 JSON 的 API,Json.NET。它方便我们读取从浏览 器流向服务器的 JSON 对象,也方便在响应流中写入 JSON 对象。这里下载:Json.NET。 Json.NET 只提供了服务器端的方法,主要有实现 JSON 文本与 XML 互相转换的类,有 自定义读写 JSON 的 JsonReader 类和 JsonWriter 类,还有一个非自定义读写 JSON 的 JavaScriptSerializer 类。 ASP.NET AJAX 中,服务器端由 JavaScriptSerializer 类的几个方法来用于实现序列化和 反序列化能力。在 Json.NET 中,服务器端的序列化和反序列化能力则主要由 JavaScriptConvert 类的几个方法提供。本篇的例子只使用了 JavaScriptConvert。 赠人玫瑰,手留余香。 2 csAxp JavaScriptConvert Json.NET 中,这个类用于序列化和反序列化 JavaScript 对象。 这个类有两个方法: 序列化 SerializeObject(object value, params JsonConverter[] converters), 它有个重载方法 SerializeObject(object value) 反序列化 DeserializeObject(string value, Type type), 它有个重载方法 DeserializeObject(string value) NET 2.0 使用JSON.net 进行反序列化 大家知道 JSON.net 最新版是基于.net 3.5 框架的,要如何使其工作在 .NET 2.0 框架下 呢,当然是 GOOGLE + baidu 啦,幸不辱命,终于在一篇英文的博客中找到了解决方法, 这篇文章的大概意思就是 首先下载最新版的 JSON.NET 源码 (http://json.codeplex.com/),然后解压,SRC 目录 是其源码,我们打开 Newtonsoft.Json.Net20.sln,这个是.NET 2.0 的解决方案,然后编译,很 顺利的就通过了,反正我是没遇啥特殊情况。编译完成后在 bin\Release 目录中你会看到一 个名为 DotNet20 的目录,很显然这个 JSON.net 的源码做的相当不错,已经为我们写好了 在.NET2.0 下运行的方法。你会发现这里边多了一个 DLL 文件(LinqBridge.dll),这个是做 什么用的呢? 在那编老外写的文章中介绍说是在.NET2.0 框架下的 LINQ,反正我对这个 LINQ 也不怎么熟,没有管,说这个组件有用就有用吧,接下来 COPY LinqBridge.dll 和 Newtonsoft.Json.Net20.dll 到 Json35r8\Source\TOOLS\ILMerge 中。还差最后一步。打开 CMD 窗口 运行如下命令: ilmerge.exe /internalize /out:Newtonsoft.Json.Net20.Merged.dll Newtonsoft.Json.Net20.dll LinqBridge.dll 这样会将两个 DLL 合并为一个 DLL,在程序中将合并后的 DLL 引入,就可以使用最新 版的 JSON.NET 了 我的反序列化代码: 代码 public static IList GetSearchList(string jsons) 我的反序列化代码: 代码 public static IList GetSearchList(string jsons) { // get JSON result objects into a list JObject o = (JObject)JsonConvert.DeserializeObject(jsons); 赠人玫瑰,手留余香。 3 csAxp JToken torrentsArray = (JToken)o["rules"]; // serialize JSON results into .NET objects IList searchResults = new List(); SearchResult c = null; foreach (JToken result in torrentsArray) { c = new SearchResult(); c.SearchField = result.SelectToken("field").ToString().Replace("\"",""); c.searchString = result.SelectToken("data").ToString().Replace("\"", ""); c.SearchOper = result.SelectToken("op").ToString().Replace("\"", ""); //Criterion searchResult = JsonConvert.DeserializeObject(result.ToString()); searchResults.Add(c); } return searchResults; } json: { "aaa":"bbbb", "rules":[ { "field":"xxxx", "data":"ooooo", "op":"lt" }, { "field":"xxxx", "data":"ooooo", "op":"gt" }, { "field":"xxyxx", "data":"ooooo", "op":"lte" } ] } 以下 json.net 实例代码网址: http://www.java2s.com/Open-Source/CSharp/Development/Json.NET/Newtonsoft/Json/Tests/Seri alization/JsonSerializerTest.cs.htm 赠人玫瑰,手留余香。 4 csAxp Newtonsoft.Json处理日期问题 1)问题描述 用 Newtonsoft.Json 转换 json,可是如果数据库是日期类型转换出来之后变成了 "\/Date(1269582661683+0800)\/"这样的格式 2)解决方案 (1)使用 IsoDateTimeConverter //第一步:获取数据 DataTable mDataTable = mDataSet.Tables[0]; //第二步:设置日期格式(使用自定义格式,如果不使用,默认是ISO8601格式) IsoDateTimeConverter mTimeConverter = new IsoDateTimeConverter(); //第三步:转换数据对象 strJosn=JsonConvert.SerializeObject(mDataTable, Formatting.Indented, mTimeConverter); strJosn=JsonConvert.SerializeObject(mDataTable, mTimeConverter); 输出结果:" LogDate": "2009-10-16 16:59:59" (2)使用 JavaScriptDateTimeConverter //第一步:获取数据 DataTable mDataTable = mDataSet.Tables[0]; //第二步:设置日期格式 JavaScriptDateTimeConverter mTimeConverter = new JavaScriptDateTimeConverter(); //第三步:转换数据对象 strJosn=JsonConvert.SerializeObject(mDataTable, Formatting.Indented, mTimeConverter); strJosn=JsonConvert.SerializeObject(mDataTable, mTimeConverter); 输出结果:"LogDate": new Date(1269582661683) //第四步:javascript 中对数据进行格式处理 renderer: Ext.util.Format.dateRenderer('Y年m月d日') 输出结果:2009年10月16日 3)注意事项 上面使用的IsoDateTimeConverter和JavaScriptDateTimeConverter类都是来至Newtonsoft.Json, 所以在使用时,记得引用该插件(using Newtonsoft.Json、using Newtonsoft.Json.Converters)。 JSON修饰标签,日期序列化 1) 修饰标签,日期序列化 (1) 通过属性标签自定义 JSON 序列化 JsonObjectAttribute:类修饰标签,用于控制类如何被序列化为一个 json 对象 JsonArrayAttribute:集合修饰标签,用于控制集合如何被序列化为一个 json 对象 JsonPropertyAttribute:域和属性修饰标签,用于控制它们如何被序列化为一个 json 对象 中的属性 JsonConverterAttribute:类,域,属性修饰标签,用于指定序列化期间的转换器 示例代码: 赠人玫瑰,手留余香。 5 csAxp [JsonObject(MemberSerialization.OptIn)] public class Customer { [JsonProperty(PropertyName="ID")] public int Unid { get; set; } [JsonProperty] public string CustomerName { get; set; } [JsonProperty] [JsonConverter(typeof(IsoDateTimeConverter))] public DateTime CreateTime { get; set; } [JsonProperty] public string Memo { get; set; } } JsonObjectAttribute 这个标签的成员序列化标志指定成员序列化是 opt-in(要序列化的成员必须带有 JsonProperty 或 DataMember 标签)还是 opt-out(默认所有的都会序列化,但通过 JsonIgnoreAttribute 标签可以忽略序列化。opt-out 是 json.net 默认的)。 JsonPropertyAttribute 允许被序列化的成员自定义名字。这个标签同时标示出:在成员序列化设置为 opt-in 的 时候,成员会被序列化。 JsonIgnoreAttribute 忽略域或属性的序列化 JsonConverterAttribute 用于指派转换对象的 JsonSerializer。 这个标签可以修饰类或类成员。用于修饰类时,通过此标签指派的 JsonConverter 会被 设置为序列化类的默认方式。用于修饰属性或域成员时,被指派的 JsonConverter 会序 列化它们的值。 (2) 序列化日期 json 中的日期是困难的。这个问题来源于 json 细则本身,因为在 json 中没有日期 的原义句法。这个细则包括对象,数组,字符串,整型和浮点,但它没有对日期定义相 关的标准。在 json.net 中用于日期的默认的格式与微软:“\/Date(1198908717056)\/”这 赠人玫瑰,手留余香。 6 csAxp 个一样。 DateTime JsonConverters 因为在 json 中没有关于日期的标准,在系统间的互操作过程中出现了大量不同的 格式。幸运的是 json.net 提供了用于读写自定义日期格式的解决方案:JsonConverters。 一个 json 转换器用于指定一种类型如何被序列化。 public class LogEntry { public string Details { get; set; } public DateTime LogDate { get; set; } } public void WriteJsonDates() { LogEntry entry = new LogEntry { LogDate = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Utc), Details = "Application started." }; string defaultJson = JsonConvert.SerializeObject(entry); // {"Details":"Application started.","LogDate":"\/Date(1234656000000)\/"} string javascriptJson = JsonConvert.SerializeObject( entry, new JavaScriptDateTimeConverter()); // {"Details":"Application started.","LogDate":new Date(1234656000000)} string isoJson = JsonConvert.SerializeObject(entry, new IsoDateTimeConverter()); // {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"} } JavaScriptDateTimeConverter 这个来自 json.net 的转换器是两种日期转换器之一。它是把日期序列化为一个 js 日期对 象。 new Date(1234656000000) IsoDateTimeConverter 这种转换器把日期序列化为一个 ISO8601 格式的字符串。 "2009-02-15T00:00:00Z" 这个类有一个日期格式化属性,用于自定义其它的格式字符串。 JSON集合序列化 Json 序列化器支持大量序列化和反序列化集合对象的方法。 要序列化一个集合(泛型列表,字典或自定义集合),只需简单的调用相关的序列 赠人玫瑰,手留余香。 7 csAxp 化器就可以了。json.net 会序列化这个集合和它包含的所有值。 1) 序列化 List _list = new List(); _list.Add(new Customer { Unid=1, CustomerName="宋江",Memo="天魁星"}); _list.Add(new Customer { Unid = 1, CustomerName = "吴用", Memo = "天机星" }); _list.Add(new Customer { Unid = 1, CustomerName = "石秀", Memo = "天慧星" }); string strJson = JsonConvert.SerializeObject(_list, Formatting.Indented); /* [{"ID": 1,"CustomerName": "宋江","Memo": "天魁星"}, {"ID": 1,"CustomerName": "吴用","Memo": "天机星"}, {"ID": 1,"CustomerName": "石秀","Memo": "天慧星"}] */ 2)反序列化 反序列化一个 json 对象到一个.net 集合,只需指定要反序列化的集合类型即可。 json.net 支持大量的集合类型。 string strJson = @"[{""ID"": 1,""CustomerName"": "" 宋江"",""Memo"": "" 天魁星 ""},{""ID"": 1,""CustomerName"": "" 吴用"",""Memo"": "" 天机星""},{""ID"": 1,""CustomerName"": ""石秀"",""Memo"": ""天慧星""}]"; List _list = JsonConvert.DeserializeObject>(strJson); foreach (Customer c in _list) { Console.WriteLine(c.CustomerName); } /* 宋江 吴用 石秀 */ 3)反序列化字典 json.net 也能把 json 对象反序列化为一个泛型字典。json 对象的属性名和值会被添 加到一个字典中。 string strJson = @"{""ID"": 1,""CustomerName"": ""宋江"",""Memo"": ""天魁星""}"; Dictionary _dictionary = JsonConvert.DeserializeObject>(strJson); 赠人玫瑰,手留余香。 8 csAxp foreach (KeyValuePair kp in _dictionary) { Console.WriteLine(kp.Key + ":" + kp.Value); } 这里还用这个例子,虽然这个例子没有意义,但属性与属性值也可以看做一个字典关系。 JSON回调方法修饰标签 2) 序列化回调方法修饰标签 json.net 支持序列化回调方法标签。一个回调修饰标签可以在序列化和反序列化对 象前后控制对象。 OnSerializing OnSerialized OnDeserializing OnDeserialized 通知序列化器在对象的序列化生命周期内要调用哪些方法,并用适合的标签来修饰 方法(序列化时,序列化后,反序列化时,反序列化后)。 参考类:Customer public class Customer { //在序列化前后没有变动 public int Unid { get; set; } //在序列化前后设置和重置 public string CustomerName { get; set; } //设置为 null,但在序列化后填充 public string Memo { get; set; } //忽略序列化,OnDeserializedAttribute 标签用于序列化之后设置一个值 [JsonIgnore] public string Other { get; set; } public Customer() { Unid = 11; CustomerName = "宋江"; Other = "忽略序列化"; Memo = null; 赠人玫瑰,手留余香。 9 csAxp } [OnSerializing] internal void OnSerializingMethod(StreamingContext context) { CustomerName = "在序列化时被写入数据文件"; } [OnSerialized] internal void OnSerializedMethod(StreamingContext context) { CustomerName = "序列化之后被赋值"; } [OnDeserializing] internal void OnDeserializingMethod(StreamingContext context) { Other = "反序列化时被赋值"; } [OnDeserialized] internal void OnDeserializedMethod(StreamingContext context) { Memo = "反序列化之后,被赋值"; } } 这个.net 类有 4 个属性: ·Unid,在序列化前后值没有变化,且值不为 null ·CustomerName,在序列化前后赋值和重设值 ·Memo,给 null 值 ·Other,这个属性忽略序列化。 public void SerializeCallbacks() { Customer customer = new Customer(); Console.WriteLine(customer.Unid); Console.WriteLine(customer.CustomerName); Console.WriteLine(customer.Memo); Console.WriteLine(customer.Other); /* 11 宋江 赠人玫瑰,手留余香。 10 csAxp 忽略序列化 */ string json = JsonConvert.SerializeObject(customer, Formatting.Indented); Console.WriteLine(json); /* {"Unid": 11,"CustomerName": "在序列化期间被写入数据文件", "Memo": null} */ Console.WriteLine(customer.Unid); Console.WriteLine(customer.CustomerName); Console.WriteLine(customer.Memo); Console.WriteLine(customer.Other); /* 11 序列化之后被赋值 忽略序列化 */ } 2)分析: (1)在没有序列化时的值 11 宋江 忽略序列化 输出 4 个属性的值,其中 Memo 值为 null (2)序列化之后 {"Unid": 11,"CustomerName": "在序列化期间被写入数据文件", "Memo": null} ·Unid 在序列化之前和之后没有变化 ·CustomerName,在序列化之前设置为“宋江”,但序列化之后变成了 “在序列化期间被写入数据文件”([OnSerializing]) ·Memo 为 null 值 ·Other 属性被忽略 序列化之后: ·Customer 对象的值: 11 序列化之后被赋值 忽略序列化 ·Unid 没有变化 ·CustomerName,序列化之后,被重新设置值“序列化之后被赋值”( [OnSerialized]) ·Other,忽略序列化,值没有变动 赠人玫瑰,手留余香。 11 csAxp (3)反序列化 接上 string json = JsonConvert.SerializeObject(customer, Formatting.Indented); 之后: customer = JsonConvert.DeserializeObject(strJson); Console.WriteLine(customer.Unid); Console.WriteLine(customer.CustomerName); Console.WriteLine(customer.Memo); Console.WriteLine(customer.Other); /* 11 在序列化时被写入数据文件 反序列化之后,被赋值 反序列化时被赋值 */ ·Unid 没有变化 ·CustomerName 在序列化时,被赋值“在序列化期间被写入数据文件”写到数据文件 (生成了 json),即 json 对象中的 CustomerName 值为“在序列化期间被写入数据文件”, 在反序列化之后,得到了 CustomerName 属性为这个值的对象 ·Memo 在反序列化之后被赋值为“反序列化之后,被赋值” [OnDeserialized]标签 ·Other 属性在序列化时是被忽略的,而即使这样,因为[OnDeserializing]标签的作用, 使它在反序列化时被设定值“反序列化时被赋值”。 JSON序列化错误处理 json.net 支持序列化和反序列化错误处理。错误处理可以捕捉错误并且可以选择处 理错误且继续序列化或把从程序中错误抛出。 定义错误处理有两种方法:错误事件和错误修饰标签。 1) 事件处理 List errors = new List(); List c = JsonConvert.DeserializeObject>(@"[ ""2009-09-09T00:00:00Z"", ""不能转换为日期"", [ 1 ], ""1977-02-20T00:00:00Z"", null, ""2000-12-01T00:00:00Z"" ]", new JsonSerializerSettings { Error =delegate(object obj,Newtonsoft.Json.Serialization.ErrorEventArgs args) { 赠人玫瑰,手留余香。 12 csAxp errors.Add(args.ErrorContext.Error.Message); args.ErrorContext.Handled = true; }, Converters ={new IsoDateTimeConverter()} }); foreach (DateTime dd in c) { Console.WriteLine(dd.ToString()); } 泛型列表 c 是一个日期类型的集合,其中有 3 个值不能成功序列化。如果不添加错 误事件处理,则序列化 出现错误。但通过错误事件处理,捕捉了其中的异常并使序列化继续下去。 输出结果: /* 2009-9-9 0:00:00 1977-2-20 0:00:00 2000-12-1 0:00:00 */ new JsonSerializerSettings { Error =delegate(object obj,Newtonsoft.Json.Serialization.ErrorEventArgs args) { errors.Add(args.ErrorContext.Error.Message); args.ErrorContext.Handled = true; }, Converters ={new IsoDateTimeConverter()} }); 在系列化设置中,添加错误事件处理: ·Error 属性是一个泛型委托: EventHandler fun = delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args) { errors.Add(args.ErrorContext.Error.Message); args.ErrorContext.Handled = true; }; 赠人玫瑰,手留余香。 13 csAxp 赠人玫瑰,手留余香。 14 这个例子中把一个 json 反序列化为一个日期集合。在序列化设置过程中为错误事件分 配一个处理器,这 个处理器用于记录错误信息并且标记这些错误是经过处理的。 这个 json 反序列化的结果是:有 3 个反序列化的日期对象和 3 个错误信息, ·该字符串未被识别为有效的 DateTime。有一个从索引 0 处开始的未知字。 ·Unexpected token parsing date. Expected String, got StartArray. ·Cannot convert null value to System.DateTime.
还剩13页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 2 人已下载

下载pdf

pdf贡献者

疯狂代码

贡献于2012-05-30

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf