接着上一篇,在上一篇里我们通过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<WeatherModel>(); 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 | |
|
|