接着上一篇,在上一篇里我们通过http请求获得了北京的天气预报,但是返回格式是json,在做web的时候肯定对json再熟悉不过了,今天就看看怎么在windows phone8里解析json。在wp里本身就集成了解析json的类System.Runtime.Serialization.Json.DataContractJsonSerializer。除此之外还可以用第三方开源类库json.net。下面是我在json.net的home上看到的(见文章最后备注),从这个数据来看无论是支持的功能还是序列化和反序列化的性能,都是json.net好,但是这个数据本身就是json.net提供的,不做评论。
上次我们从http://www.weather.com.cn/data/cityinfo/101010100.html获取到的天气数据是这样的
{"weatherinfo":{"city":"北京","cityid":"101010100","temp1":"27℃","temp2":"22℃","weather":"大雨转中雨","img1":"d9.gif","img2":"n8.gif","ptime":"11:00"}}
我们先不管这些都是什么内容,只观察这个json的格式,创建的实体类应该是这样的
1 public class WeatherModel 2 { 3 public WeatherInforDetails weatherinfo { get; set; } 4 public class WeatherInforDetails 5 { 6 public string city { get; set; } 7 public string cityid { get; set; } 8 public string temp1 { get; set; } 9 public string temp2 { get; set; } 10 public string weather { get; set; } 11 public string img1 { get; set; } 12 public string img2 { get; set; } 13 public string ptime { get; set; } 14 } 15 }
再把上一篇里的请求扩展下,先看看用.net自带的DataContractJsonSerializer要怎么写
1 HttpClient hc = new HttpClient(); 2 try 3 { 4 var task = await hc.GetAsync("http://www.weather.com.cn/data/cityinfo/101010100.html"); 5 string result = await task.Content.ReadAsStringAsync(); 6 using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(result))) 7 { 8 WeatherModel obj = Activator.CreateInstance(); 9 DataContractJsonSerializer js = new DataContractJsonSerializer(obj.GetType()); 10 WeatherModel model = (WeatherModel)js.ReadObject(ms); 11 MessageBox.Show(model.weatherinfo.city); 12 } 13 14 } 15 catch (Exception e) 16 { 17 MessageBox.Show(e.Message); 18 }
调试一下,已经可以出结果了。我们再看看用json.net应该怎么做,其他地方不用动,只要把上面try里的代码换一下就行
在调整调整之前要先下载json.net的dll,可以从这里下载http://json.codeplex.com/,注意在wp项目中引用dll的时候要引用Portable40文件夹下的Newtonsoft.Json.dll
WeatherModel model = (WeatherModel)JsonConvert.DeserializeObject(result, typeof(WeatherModel)); MessageBox.Show(model.weatherinfo.city);
调试一下也没问题,json.net稍微简洁了一点。看下面的对比表格,json.net支持linq to json,我们再看看如何用json.net的linq to json。
JObject obj = JObject.Parse(result); JToken tok = obj["weatherinfo"]; MessageBox.Show(tok["city"].ToString());
居然还可以这么用,而且JObject还可以用foreach遍历,可以转换成array,list,collection等等。
看到这突然灵光一线,对于这个json来说只是嵌套了一层,对于从另外一个更全的可以获得未来5天的天气api来说,返回的json简直就太复杂了,而且很多数据我们并用到,时不时可以用这样的写法简化一下model呢。我们再建一个model,WeatherModel1
1 public class WeatherModel1 2 { 3 public string city { get; set; } 4 public string cityid { get; set; } 5 public string temp1 { get; set; } 6 public string temp2 { get; set; } 7 public string weather { get; set; } 8 public string img1 { get; set; } 9 public string img2 { get; set; } 10 public string ptime { get; set; } 11 }
再把解析json的地方改成这样
1 JObject obj = JObject.Parse(result); 2 WeatherModel1 details = (WeatherModel1)JsonConvert.DeserializeObject(obj["weatherinfo"].ToString(), typeof(WeatherModel1)); 3 MessageBox.Show(details.city);
是不是简单了不少,对于那些返回数据比较发杂的的json数据来说就太有用了。
备注:
Json.NET | DataContractJsonSerializer | JavaScriptSerializer | |
Supports JSON | |||
Supports BSON | |||
Supports JSON Schema | |||
Supports .NET 2.0 | |||
Supports .NET 3.5 | |||
Supports .NET 4.0 | |||
Supports .NET 4.5 | |||
Supports Silverlight | |||
Supports Windows Phone | |||
Supports Windows 8 | |||
Supports Portable Class Library | |||
Open Source | |||
MIT License | |||
LINQ to JSON | |||
Thread Safe | |||
XPath-like JSON query syntax | |||
Indented JSON support | |||
Efficient dictionary serialization | |||
Nonsensical dictionary serialization | |||
Deserializes IList, IEnumerable, ICollection, IDictionary properties | |||
Serializes circular references | |||
Supports serializing objects by reference | |||
Deserializes polymorphic properties and collections | |||
Serializes and deserializes multidimensional arrays | |||
Supports including type names with JSON | |||
Globally customize serialization process | |||
Supports excluding null values when serializing | |||
Supports SerializationBinder | |||
Conditional property serialization | |||
Includes line number information in errors | |||
Converts XML to JSON and JSON to XML | |||
JSON Schema validation | |||
JSON Schema generation from .NET types | |||
Camel case JSON property names | |||
Non-default constructors support | |||
Serialization error handling | |||
Supports populating an existing object | |||
Efficiently serializes byte arrays as base64 text | |||
Handles NaN, Infinity, -Infinity and undefined | |||
Handles JavaScript constructors | |||
Serializes .NET 4.0 dynamic objects | |||
Serializes ISerializable objects | |||
Supports serializing enums to their text name | |||
JSON recursion limit support | |||
Attribute property name customization | |||
Attribute property order customization | |||
Attribute property required customization | |||
Supports ISO8601 dates | |||
Supports JavaScript constructor dates | |||
Supports Microsoft AJAX dates | |||
Unquoted property names support | |||
Raw JSON support | |||
Supports reading and writing comments | |||
Supports BigInteger | |||
Serializes anonymous types | |||
Deserializes anonymous types | |||
Deserializes read only collections | |||
Opt-in mode serialization | |||
Opt-out mode serialization | |||
Field (Serializable) mode serialization | |||
Efficiently stream reading and writing JSON | |||
Single or double quote JSON content | |||
Supports overriding a type's serialization | |||
Supports OnDeserialized, OnSerializing, OnSerialized and OnDeserializing attributes | |||
Supports serializing private properties | |||
DataMember attribute support | |||
MetdataType attribute support | |||
DefaultValue attribute support | |||
Serializes DataSets and DataTables | |||
Serailizes Entity Framework | |||
Serializes nHibernate | |||
Case-insensitive property deserialization | |||
Tracing |