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