主要参考http://blog.csdn.net/joyhen/article/details/24805899和http://www.cnblogs.com/yanweidie/p/4605212.html
根据自己需求,做些测试、修改、整理。
一、用JsonConvert序列化和反序列化。
实体类不用特殊处理,正常定义属性即可,控制属性是否被序列化参照高级用法1。
public interface IPerson { string FirstName { get; set; } string LastName { get; set; } DateTime BirthDate { get; set; } } public class Employee : IPerson { public string FirstName { get; set; } public string LastName { get; set; } public DateTime BirthDate { get; set; } public string Department { get; set; } public string JobTitle { get; set; } public string NotSerialize { get; set; } } public class PersonConverter : Newtonsoft.Json.Converters.CustomCreationConverter<IPerson> { //重写abstract class CustomCreationConverter<T>的Create方法 public override IPerson Create(Type objectType) { return new Employee(); } } public class Product { public string Name { get; set; } public DateTime Expiry { get; set; } public Decimal Price { get; set; } public string[] Sizes { get; set; } public string NotSerialize { get; set; } }
1.序列化代码:
#region 序列化 用JsonConvert public string TestJsonSerialize() { Product product = new Product(); product.Name = "Apple"; product.Expiry = DateTime.Now;//.AddDays(3).ToString("yyyy-MM-dd hh:mm:ss"); product.Price = 3.99M; //string json = Newtonsoft.Json.JsonConvert.SerializeObject(product); //没有缩进输出 string json = Newtonsoft.Json.JsonConvert.SerializeObject(product, Newtonsoft.Json.Formatting.Indented);//有缩进输出 //string json = Newtonsoft.Json.JsonConvert.SerializeObject( // product, // Newtonsoft.Json.Formatting.Indented, // new Newtonsoft.Json.JsonSerializerSettings { NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore }//参照高级用法中有关JsonSerializerSettings用法 //); return json; } public string TestListJsonSerialize() { Product product = new Product(); product.Name = "Apple"; product.Expiry = DateTime.Now;//.AddDays(3).ToString("yyyy-MM-dd hh:mm:ss"); product.Price = 3.99M; product.Sizes = new string[] { "Small", "Medium", "Large" }; List<Product> plist = new List<Product>(); plist.Add(product); plist.Add(product); string json = Newtonsoft.Json.JsonConvert.SerializeObject(plist, Newtonsoft.Json.Formatting.Indented); return json; } #endregion
2.反序列化代码:
#region 反序列化 用JsonConvert public string TestJsonDeserialize() { string strjson = "{\"Name\":\"Apple\",\"Expiry\":\"2014-05-03 10:20:59\",\"Price\":3.99,\"Sizes\":[\"Small\",\"Medium\",\"Large\"]}"; Product p = Newtonsoft.Json.JsonConvert.DeserializeObject<Product>(strjson); string template = @" Name:{0} Expiry:{1} Price:{2} Sizes:{3} "; return string.Format(template, p.Name, p.Expiry, p.Price.ToString(), string.Join(",", p.Sizes)); } public string TestListJsonDeserialize() { string strjson = "{\"Name\":\"Apple\",\"Expiry\":\"2014-05-03 10:20:59\",\"Price\":3.99,\"Sizes\":[\"Small\",\"Medium\",\"Large\"]}"; List<Product> plist = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Product>>(string.Format("[{0},{1}]", strjson, strjson)); string template = @" Name:{0} Expiry:{1} Price:{2} Sizes:{3} "; System.Text.StringBuilder strb = new System.Text.StringBuilder(); plist.ForEach(x => strb.AppendLine( string.Format(template, x.Name, x.Expiry, x.Price.ToString(), string.Join(",", x.Sizes)) ) ); return strb.ToString(); } #endregion
3.自定义序列化,使用实体类中定义的PersonConverter,每反序列化一次实体时会调用一次PersonConverter,还没想清楚如何用。
#region 自定义反序列化 public string TestListCustomDeserialize() { string strJson = "[ { \"FirstName\": \"Maurice\", \"LastName\": \"Moss\", \"BirthDate\": \"1981-03-08T00:00Z\", \"Department\": \"IT\", \"JobTitle\": \"Support\" }, { \"FirstName\": \"Jen\", \"LastName\": \"Barber\", \"BirthDate\": \"1985-12-10T00:00Z\", \"Department\": \"IT\", \"JobTitle\": \"Manager\" } ] "; List<IPerson> people = Newtonsoft.Json.JsonConvert.DeserializeObject<List<IPerson>>(strJson, new PersonConverter()); IPerson person = people[0]; string template = @" 当前List<IPerson>[x]对象类型:{0} FirstName:{1} LastName:{2} BirthDate:{3} Department:{4} JobTitle:{5} "; System.Text.StringBuilder strb = new System.Text.StringBuilder(); people.ForEach(x => strb.AppendLine( string.Format( template, person.GetType().ToString(), x.FirstName, x.LastName, x.BirthDate.ToString(), ((Employee)x).Department, ((Employee)x).JobTitle ) ) ); return strb.ToString(); } #endregion
4、获取Json字符串中部分内容
#region Serializing Partial JSON Fragment Example public class SearchResult { public string Title { get; set; } public string Content { get; set; } public string Url { get; set; } } public string SerializingJsonFragment() { #region string googleSearchText = @"{ 'responseData': { 'results': [{ 'GsearchResultClass': 'GwebSearch', 'unescapedUrl': 'http://en.wikipedia.org/wiki/Paris_Hilton', 'url': 'http://en.wikipedia.org/wiki/Paris_Hilton', 'visibleUrl': 'en.wikipedia.org', 'cacheUrl': 'http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org', 'title': '<b>Paris Hilton</b> - Wikipedia, the free encyclopedia', 'titleNoFormatting': 'Paris Hilton - Wikipedia, the free encyclopedia', 'content': '[1] In 2006, she released her debut album...' }, { 'GsearchResultClass': 'GwebSearch', 'unescapedUrl': 'http://www.imdb.com/name/nm0385296/', 'url': 'http://www.imdb.com/name/nm0385296/', 'visibleUrl': 'www.imdb.com', 'cacheUrl': 'http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com', 'title': '<b>Paris Hilton</b>', 'titleNoFormatting': 'Paris Hilton', 'content': 'Self: Zoolander. Socialite <b>Paris Hilton</b>...' }], 'cursor': { 'pages': [{ 'start': '0', 'label': 1 }, { 'start': '4', 'label': 2 }, { 'start': '8', 'label': 3 }, { 'start': '12', 'label': 4 }], 'estimatedResultCount': '59600000', 'currentPageIndex': 0, 'moreResultsUrl': 'http://www.google.com/search?oe=utf8&ie=utf8...' } }, 'responseDetails': null, 'responseStatus': 200 }"; #endregion Newtonsoft.Json.Linq.JObject googleSearch = Newtonsoft.Json.Linq.JObject.Parse(googleSearchText); // get JSON result objects into a list List<Newtonsoft.Json.Linq.JToken> listJToken = googleSearch["responseData"]["results"].Children().ToList(); System.Text.StringBuilder strb = new System.Text.StringBuilder(); string template = @" Title:{0} Content: {1} Url:{2} "; listJToken.ForEach(x => { // serialize JSON results into .NET objects SearchResult searchResult = Newtonsoft.Json.JsonConvert.DeserializeObject<SearchResult>(x.ToString()); strb.AppendLine(string.Format(template, searchResult.Title, searchResult.Content, searchResult.Url)); }); return strb.ToString(); } #endregion
输出结果
Title:<b>Paris Hilton</b> - Wikipedia, the free encyclopedia Content: [1] In 2006, she released her debut album... Url:http://en.wikipedia.org/wiki/Paris_Hilton Title:<b>Paris Hilton</b> Content: Self: Zoolander. Socialite <b>Paris Hilton</b>... Url:http://www.imdb.com/name/nm0385296/
5、利用Json.Linq序列化
可以突破实体类的限制,自由组合要序列化的值
public class Linq2Json { #region GetJObject //Parsing a JSON Object from text public Newtonsoft.Json.Linq.JObject GetJObject() { string json = @"{ CPU: 'Intel', Drives: [ 'DVD read/writer', '500 gigabyte hard drive' ] }"; Newtonsoft.Json.Linq.JObject jobject = Newtonsoft.Json.Linq.JObject.Parse(json); return jobject; } /* * //example:=> * Linq2Json l2j = new Linq2Json(); Newtonsoft.Json.Linq.JObject jobject = l2j.GetJObject2(Server.MapPath("json/Person.json")); //return Newtonsoft.Json.JsonConvert.SerializeObject(jobject, Newtonsoft.Json.Formatting.Indented); return jobject.ToString(); */ //Loading JSON from a file public Newtonsoft.Json.Linq.JObject GetJObject2(string jsonPath) { using (System.IO.StreamReader reader = System.IO.File.OpenText(jsonPath)) { Newtonsoft.Json.Linq.JObject jobject = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.Linq.JToken.ReadFrom(new Newtonsoft.Json.JsonTextReader(reader)); return jobject; } } //Creating JObject public Newtonsoft.Json.Linq.JObject GetJObject3() { List<Post> posts = GetPosts(); Newtonsoft.Json.Linq.JObject jobject = Newtonsoft.Json.Linq.JObject.FromObject(new { channel = new { title = "James Newton-King", link = "http://james.newtonking.com", description = "James Newton-King's blog.", item = from p in posts orderby p.Title select new { title = p.Title, description = p.Description, link = p.Link, category = p.Category } } }); return jobject; } /* { "channel": { "title": "James Newton-King", "link": "http://james.newtonking.com", "description": "James Newton-King's blog.", "item": [{ "title": "jewron", "description": "4546fds", "link": "http://www.baidu.com", "category": "jhgj" }, { "title": "jofdsn", "description": "mdsfan", "link": "http://www.baidu.com", "category": "6546" }, { "title": "jokjn", "description": "m3214an", "link": "http://www.baidu.com", "category": "hg425" }, { "title": "jon", "description": "man", "link": "http://www.baidu.com", "category": "goodman" }] } } */ //Creating JObject public Newtonsoft.Json.Linq.JObject GetJObject4() { List<Post> posts = GetPosts(); Newtonsoft.Json.Linq.JObject rss = new Newtonsoft.Json.Linq.JObject( new Newtonsoft.Json.Linq.JProperty("channel", new Newtonsoft.Json.Linq.JObject( new Newtonsoft.Json.Linq.JProperty("title", "James Newton-King"), new Newtonsoft.Json.Linq.JProperty("link", "http://james.newtonking.com"), new Newtonsoft.Json.Linq.JProperty("description", "James Newton-King's blog."), new Newtonsoft.Json.Linq.JProperty("item", new Newtonsoft.Json.Linq.JArray( from p in posts orderby p.Title select new Newtonsoft.Json.Linq.JObject( new Newtonsoft.Json.Linq.JProperty("title", p.Title), new Newtonsoft.Json.Linq.JProperty("description", p.Description), new Newtonsoft.Json.Linq.JProperty("link", p.Link), new Newtonsoft.Json.Linq.JProperty("category", new Newtonsoft.Json.Linq.JArray( from c in p.Category select new Newtonsoft.Json.Linq.JValue(c) ) ) ) ) ) ) ) ); return rss; } /* { "channel": { "title": "James Newton-King", "link": "http://james.newtonking.com", "description": "James Newton-King's blog.", "item": [{ "title": "jewron", "description": "4546fds", "link": "http://www.baidu.com", "category": ["j", "h", "g", "j"] }, { "title": "jofdsn", "description": "mdsfan", "link": "http://www.baidu.com", "category": ["6", "5", "4", "6"] }, { "title": "jokjn", "description": "m3214an", "link": "http://www.baidu.com", "category": ["h", "g", "4", "2", "5"] }, { "title": "jon", "description": "man", "link": "http://www.baidu.com", "category": ["g", "o", "o", "d", "m", "a", "n"] }] } } */ public class Post { public string Title { get; set; } public string Description { get; set; } public string Link { get; set; } public string Category { get; set; } } private List<Post> GetPosts() { List<Post> listp = new List<Post>() { new Post{Title="jon",Description="man",Link="http://www.baidu.com",Category="goodman"}, new Post{Title="jofdsn",Description="mdsfan",Link="http://www.baidu.com",Category="6546"}, new Post{Title="jewron",Description="4546fds",Link="http://www.baidu.com",Category="jhgj"}, new Post{Title="jokjn",Description="m3214an",Link="http://www.baidu.com",Category="hg425"} }; return listp; } #endregion #region GetJArray /* * //example:=> * Linq2Json l2j = new Linq2Json(); Newtonsoft.Json.Linq.JArray jarray = l2j.GetJArray(); return Newtonsoft.Json.JsonConvert.SerializeObject(jarray, Newtonsoft.Json.Formatting.Indented); //return jarray.ToString(); */ //Parsing a JSON Array from text public Newtonsoft.Json.Linq.JArray GetJArray() { string json = @"[ 'Small', 'Medium', 'Large' ]"; Newtonsoft.Json.Linq.JArray jarray = Newtonsoft.Json.Linq.JArray.Parse(json); return jarray; } //Creating JArray public Newtonsoft.Json.Linq.JArray GetJArray2() { Newtonsoft.Json.Linq.JArray array = new Newtonsoft.Json.Linq.JArray(); Newtonsoft.Json.Linq.JValue text = new Newtonsoft.Json.Linq.JValue("Manual text"); Newtonsoft.Json.Linq.JValue date = new Newtonsoft.Json.Linq.JValue(new DateTime(2000, 5, 23)); //add to JArray array.Add(text); array.Add(date); return array; } #endregion }
使用方式
Linq2Json l2j = new Linq2Json(); Newtonsoft.Json.Linq.JObject jarray = l2j.GetJObject4(); return jarray.ToString();
二、高级用法
1.忽略某些属性
当实体类中定义了很多属性,但序列化时只想针对某些属性时可以采用此方式。这种需求还可以细分为运行时不同时刻参与序列化属性集合不固定和固定两种情况。
1)能解决参与序列化属性集合固定的情况
OptOut 默认值,类中所有公有成员会被序列化,如果不想被序列化,可以用特性JsonIgnore
OptIn 默认情况下,所有的成员不会被序列化,类中的成员只有标有特性JsonProperty的才会被序列化,当类的成员很多,但客户端仅仅需要一部分数据时,很有用
仅需要姓名属性:
[JsonObject(MemberSerialization.OptIn)] public class Person { public int Age { get; set; } [JsonProperty] public string Name { get; set; } public string Sex { get; set; } public bool IsMarry { get; set; } public DateTime Birthday { get; set; } }
输出结果
不需要是否结婚属性
[JsonObject(MemberSerialization.OptOut)] public class Person { public int Age { get; set; } public string Name { get; set; } public string Sex { get; set; } [JsonIgnore] public bool IsMarry { get; set; } public DateTime Birthday { get; set; } }
输出结果
通过上面的例子可以看到,要实现不返回某些属性的需求很简单。1.在实体类上加上[JsonObject(MemberSerialization.OptOut)] 2.在不需要返回的属性上加上 [JsonIgnore]说明。
2)能解决参与序列化属性集合不固定的情况
方法1:通过设置忽略默认值属性方式。有点傻。
方法2:继承默认的DefaultContractResolver类,传入需要输出的属性。
2、默认值
可以设置某个属性的默认值,然后序列化或反序列化时自动判断是否默认值,然后选择是否忽略对具有默认值的属性序列化或反序列化。
序列化时想忽略默认值属性可以通过JsonSerializerSettings.DefaultValueHandling来确定,该值为枚举值。
DefaultValueHandling.Ignore 序列化和反序列化时,忽略默认值
DefaultValueHandling.Include 序列化和反序列化时,包含默认值
[DefaultValue(10)] public int Age { get; set; }
Person p = new Person { Age = 10, Name = "张三丰", Sex = "男", IsMarry = false, Birthday = new DateTime(1991, 1, 2) }; JsonSerializerSettings jsetting=new JsonSerializerSettings(); jsetting.DefaultValueHandling=DefaultValueHandling.Ignore; Console.WriteLine(JsonConvert.SerializeObject(p, Formatting.Indented, jsetting));
输出结果
3、空值
与默认值类似,可以选择是否忽略对空值的属性序列化或反序列化。
序列化时需要忽略值为NULL的属性,可以通过JsonSerializerSettings.NullValueHandling来确定,另外通过JsonSerializerSettings设置属性是对序列化过程中所有属性生效的,想单独对某一个属性生效可以使用JsonProperty,下面将分别展示两个方式。
1)JsonSerializerSettings.NullValueHandling方式,会忽略实体中全部空值参数
Person p = new Person { room=null,Age = 10, Name = "张三丰", Sex = "男", IsMarry = false, Birthday = new DateTime(1991, 1, 2) }; JsonSerializerSettings jsetting=new JsonSerializerSettings(); jsetting.NullValueHandling = NullValueHandling.Ignore; Console.WriteLine(JsonConvert.SerializeObject(p, Formatting.Indented, jsetting));
上例中不会序列化room。
2)JsonProperty,忽略特定的属性
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)] public Room room { get; set; }
4、支持非公共属性
[JsonProperty] private int Height { get; set; }
5、日期
对于Dateime类型日期的格式化就比较麻烦了,系统自带的会格式化成iso日期标准,但是实际使用过程中大多数使用的可能是yyyy-MM-dd 或者yyyy-MM-dd HH:mm:ss两种格式的日期,解决办法是可以将DateTime类型改成string类型自己格式化好,然后在序列化。如果不想修改代码,可以采用下面方案实现。
Json.Net提供了IsoDateTimeConverter日期转换这个类,可以通过JsnConverter实现相应的日期转换
[JsonConverter(typeof(IsoDateTimeConverter))] public DateTime Birthday { get; set; }
但是IsoDateTimeConverter日期格式不是我们想要的,我们可以继承该类实现自己的日期
public class ChinaDateTimeConverter : DateTimeConverterBase { private static IsoDateTimeConverter dtConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd" }; public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return dtConverter.ReadJson(reader, objectType, existingValue, serializer); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { dtConverter.WriteJson(writer, value, serializer); } }
自己实现了一个yyyy-MM-dd格式化转换类,可以看到只是初始化IsoDateTimeConverter时给的日期格式为yyyy-MM-dd即可,下面看下效果
[JsonConverter(typeof(ChinaDateTimeConverter))] public DateTime Birthday { get; set; }
日期处理也可以通过设置全局JsonConvert.DefaultSettings,设置JsonSerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"。
6、自定义序列化时的属性名称
等同于DataMember中PropertyName作用。
实体中定义的属性名可能不是自己想要的名称,但是又不能更改实体定义,这个时候可以自定义序列化字段名称。
[JsonProperty(PropertyName = "CName")] public string Name { get; set; }
7、枚举值的自定义格式化
默认情况下对于实体里面的枚举类型系统是格式化成改枚举对应的整型数值,那如果需要格式化成枚举对应的字符怎么处理呢?
public enum NotifyType { /// <summary> /// Emil发送 /// </summary> Mail=0, /// <summary> /// 短信发送 /// </summary> SMS=1 } public class TestEnmu { /// <summary> /// 消息发送类型 /// </summary> [JsonConverter(typeof(StringEnumConverter))] public NotifyType Type { get; set; } }
输出结果
8、自定义类型转换
默认情况下对于实体里面的Boolean系统是格式化成true或者false,对于true转成"是" false转成"否"这种需求改怎么实现了?我们可以自定义类型转换实现该需求,下面看实例
public class BoolConvert : JsonConverter { private string[] arrBString { get; set; } public BoolConvert() { arrBString = "是,否".Split(','); } /// <summary> /// 构造函数 /// </summary> /// <param name="BooleanString">将bool值转换成的字符串值</param> public BoolConvert(string BooleanString) { if (string.IsNullOrEmpty(BooleanString)) { throw new ArgumentNullException(); } arrBString = BooleanString.Split(','); if (arrBString.Length != 2) { throw new ArgumentException("BooleanString格式不符合规定"); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { bool isNullable = IsNullableType(objectType); Type t = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType; if (reader.TokenType == JsonToken.Null) { if (!IsNullableType(objectType)) { throw new Exception(string.Format("不能转换null value to {0}.", objectType)); } return null; } try { if (reader.TokenType == JsonToken.String) { string boolText = reader.Value.ToString(); if (boolText.Equals(arrBString[0], StringComparison.OrdinalIgnoreCase)) { return true; } else if (boolText.Equals(arrBString[1], StringComparison.OrdinalIgnoreCase)) { return false; } } if (reader.TokenType == JsonToken.Integer) { //数值 return Convert.ToInt32(reader.Value) == 1; } } catch (Exception ex) { throw new Exception(string.Format("Error converting value {0} to type '{1}'", reader.Value, objectType)); } throw new Exception(string.Format("Unexpected token {0} when parsing enum", reader.TokenType)); } /// <summary> /// 判断是否为Bool类型 /// </summary> /// <param name="objectType">类型</param> /// <returns>为bool类型则可以进行转换</returns> public override bool CanConvert(Type objectType) { return true; } public bool IsNullableType(Type t) { if (t == null) { throw new ArgumentNullException("t"); } return (t.BaseType.FullName=="System.ValueType" && t.GetGenericTypeDefinition() == typeof(Nullable<>)); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } bool bValue = (bool)value; if (bValue) { writer.WriteValue(arrBString[0]); } else { writer.WriteValue(arrBString[1]); } } }
自定义了BoolConvert类型,继承自JsonConverter。构造函数参数BooleanString可以让我们自定义将true false转换成相应字符串。下面看实体里面怎么使用这个自定义转换类型
public class Person { [JsonConverter(typeof(BoolConvert))] public bool IsMarry { get; set; } }
相应的有什么个性化的转换需求,都可以使用自定义转换类型的方式实现。
9、全局序列化设置
对全局缺省JsonSerializerSettings设置,省却每处都要相同设置代码的麻烦。
Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings(); JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() => { //日期类型默认格式化处理 setting.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat; setting.DateFormatString = "yyyy-MM-dd HH:mm:ss"; //空值处理 setting.NullValueHandling = NullValueHandling.Ignore; //高级用法九中的Bool类型转换 设置 setting.Converters.Add(new BoolConvert("是,否")); return setting; });