《Silverlight 2 & ASP.NET高级编程》第9章创建用户界面,本章将介绍如何使用Silverlight的网络和通信功能来访问分布式数据。本章将涵盖如何创建Silverlight可以调用的服务,讨论处理跨域问题的不同方法,并介绍Silverlight内置的、用于处理数据的类。本节为大家介绍处理JSON数据。

AD:


    9.5.3  处理JSON数据

    Silverlight为解析从Web服务、REST API或者其他类型所返回的XML数据提供了非常优秀的支持。由于许多服务均返回XML数据,因此在Silverlight应用程序中,诸如XmlReader、XmlSerializer或XDocument之类的类会频繁被使用。但是,XML数据并不是可以从服务返回的唯一数据类型。服务也可能支持JavaScript对象表示(Java Script Object Notation,JSON)。该格式为客户端和服务之间交换数据提供了一种压缩的方法。JSON最初设计是和JavaScript语言一起使用,但是很多情况下,需要在Silverlight中利用诸如C#或者VB.NET之类的语言对它进行处理。在这些情况下,可以使用Silverlight的DataContractJsonSerializer类,该类支持将CLR对象序列化为JSON以及将JSON消息反序列化为CLR对象。

    DataContractJsonSerializer类位于System.Runtime.Serialization.Json名称空间中。为了使用该类,需要在Silverlight项目中引用System.ServiceModel.Web程序集。DataContractJson Serializer的结构和功能均和前面所讨论的XmlSerializer类非常类似。它提供了诸如ReadObject的方法以实施反序列化,而提供了WriteObject方法以实施序列化。ReadObject方法接受一个包含需要反序列化的JSON数据的流作为参数,而WriteObject方法则以源对象以及序列化后的JSON数据流作为参数。两个方法的签名如下所示:

    1. public Object ReadObject(  
    2. Stream stream  
    3. )  
    4.  
    5. public void WriteObject(  
    6. Stream stream,  
    7. Object graph  

    1. JSON基础

    包括由Flickr所提供的服务的很多REST API,均允许数据以JSON格式返回。JSON利用括弧来区分不同的对象,并利用冒号将属性名和属性值实施分离。下面的例子利用JSON将来源于Flickr的图像数据传递给某个客户端:

    1. {  
    2. "id":"555242564", "owner":"555371@N00", "secret":"555afd69d",  
    3. "server":"2226", "farm":3, "title":"Camp Chihuahua: Class In Session",  
    4. "ispublic":1, "isfriend":0, "isfamily":0  

    该JSON片段利用{和}字符指定了照片数据在哪开始到哪结束,利用冒号将属性名和属性值分离,并利用逗号分隔不同的属性。如下所示,利用方括号可以定义一个photo对象的数组:

    1. {  
    2. "photo":  
    3. [  
    4. {  
    5. "id":"2386242564", "owner":"3911171@N00", "secret":"555afd69d",  
    6. "server":"2226","farm":3,"title":"Camp Chihuahua: Class In Session",  
    7. "ispublic":1, "isfriend":0, "isfamily":0  
    8. },  
    9. {  
    10. "id":"2386239664", "owner":"25111971@N02", "secret":"555cced92",  
    11. "server":"3229", "farm":4, "title":"kid and dog",  
    12. "ispublic":1, "isfriend":0, "isfamily":0  
    13. }  
    14. ]  

    如下面的JSON消息所示,通过添加嵌套的括号,对象也可以定义子对象:

    1. {  
    2. "photos":  
    3. {  
    4. "page":1, "pages":32047, "perpage":100, "total":"3204603",  
    5. "photo":  
    6. {  
    7. [  
    8. {  
    9. "id":"2386242564", "owner":"3911171@N00", "secret":"555afd69d",  
    10. "server":"2226", "farm":3, "title":"Camp Chihuahua: Class In Session",  
    11. "ispublic":1, "isfriend":0, "isfamily":0  
    12. },  
    13.  
    14. {  
    15.  
    16. "id":"2386239664", "owner":"25111971@N02", "secret":"555cced92",  
    17. "server":"3229", "farm":4, "title":"kid and dog", "ispublic":1,  
    18. "isfriend":0, "isfamily":0  
    19. }  
    20. ]  
    21. }  
    22. },  
    23. "stat":"ok"}  

    2. 使用DataContractJsonSerializer类

    为了使用DataContractJsonSerializer类,并不需要完整地理解JSON消息格式,因为它处理了数据的序列化和反序列化过程。但是,需要足够了解相关知识,以在Silverlight应用程序中创建JSON数据可以被反序列化成的匹配CLR类。映射为前面所示的JSON消息例子的类如下所示:

    1. public class FlickrResponse  
    2. {  
    3. public string stat { get; set; }  
    4. public photos photos { get; set; }  
    5. }  
    6.  
    7. public class photos  
    8. {  
    9. public int page { get; set; }  
    10. public int pages { get; set; }  
    11. public int perpage { get; set; }  
    12. public int total { get; set; }  
    13. public photo[] photo { get; set; }  
    14. }  
    15.  
    16. public class photo  
    17. {  
    18. public string id { get; set; }  
    19. public string owner { get; set; }  
    20. public string secret { get; set; }  
    21. public string title { get; set; }  
    22. public int ispublic { get; set; }  
    23. public int isfriend { get; set; }  
    24. public int isfamily { get; set; }  
    25. public string server { get; set; }  
    26. public string farm { get; set; }  
    27. //Custome properties used for data binding  
    28. public string Url { get; set; }  
    29. public ImageBrush ImageBrush { get; set; }  

    注意,在每个类中定义的属性均和包含在该JSON消息中的属性大小写匹配。这种大小写的匹配甚至应用到了子类的名称上,如photos和photo。这正是JSON消息正确反序列化的精华所在!JSON消息和CLR对象之间大小写的不匹配将导致数据丢失。

    为了反序列化JSON消息,可以调用DataContractJsonSerializer类的ReadObject方法,并为该方法传递一个包含JSON数据的流作为参数。下面所示的例子检索了来自Flickr REST服务的数据,并将其进行了反序列化。数据是利用HttpWebRequest和HttpWebResponse对象进行检索的。而反序列化JSON数据的代码则位于GetJSONResponse CallBack方法中。注意,JSON数据将被反序列化到CLR对象的类型,传递给了DataContractJsonSerializer类的构造函数。

    1. private Uri CreateJSONUri()  
    2. {  
    3. return new Uri(String.Format("{0}?method={1}&api_key={2}&text={3}" +  
    4. "&per_page={4}&format=json&nojsoncallback=1",  
    5. _BaseUri, "flickr.photos.search", _APIKey, this.txtSearchText.Text,   
    6. 50));  
    7. }  
    8.  
    9. private void StartJsonRequest()  
    10. {  
    11. //Add reference to System.Net.dll if it's not already referenced  
    12. HttpWebRequest request = (HttpWebRequest)WebRequest.Create  
    13. (CreateJSONUri());  
    14. //Start async REST request  
    15. request.BeginGetResponse(new AsyncCallback(GetJSONResponseCallBack),   
    16. request);  
    17. }  
    18.  
    19. private void GetJSONResponseCallBack(IAsyncResult asyncResult)  
    20. {  
    21. JSON.FlickrResponse res = null;  
    22. HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;  
    23. using (HttpWebResponse response =  
    24. (HttpWebResponse)request.EndGetResponse(asyncResult))  
    25. {  
    26. Stream dataStream = response.GetResponseStream();  
    27. //Deserialize JSON message into custom objects  
    28. DataContractJsonSerializer jsonSerializer =  
    29. new DataContractJsonSerializer(typeof(JSON.FlickrResponse));  
    30. jsonObj = (JSON.FlickrResponse)jsonSerializer.ReadObject  
    31. (dataStream);  
    32. Dispatcher.BeginInvoke(() => ProcessJsonObject(jsonObj));  
    33. }  
    34. }  
    35.  
    36. private void ProcessJsonObject(JSON.FlickrResponse jsonObj)  
    37. {  
    38. //Assign Url to each photo object as well as ImageBrush to paint photo  
    39. if (jsonObj != null && jsonObj.photos.photo != null)  
    40. {  
    41. foreach (JSON.photo photo in jsonObj.photos.photo)  
    42. {  
    43. photo.Url = this.CreateJSONPhotoUrl(photo);  
    44. ImageBrush brush = new ImageBrush();  
    45. brush.ImageSource = new BitmapImage(new Uri(photo.Url));  
    46. brush.Stretch = Stretch.Uniform;  
    47. photo.ImageBrush = brush;  
    48. }  
    49. DisplayJSONPhotos(jsonObj.photos.photo);  
    50. }  
    51. else  
    52. {  
    53. ShowAlert("Unable to proces photo data.");  
    54. }  
    55. }  
    56.  
    57. private string CreateJSONPhotoUrl(JSON.photo photo)  
    58. {  
    59. //http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_  
    60. {size}.jpg  
    61. //farm-id: 1  
    62. //server-id: 2  
    63. //photo-id: 1418878  
    64. //secret: 1e92283336  
    65. //size: m, s, t, b  
    66.  
    67. return String.Format(_BasePhotoUrl, photo.farm, photo.server,   
    68. photo.id,photo.secret, "s");  
    69. }  
    70.  
    71. private void DisplayJSONPhotos(JSON.photo[] photos)  
    72. {  
    73. if (photos != null && photos.Length > 0)  
    74. {  
    75. this.icPhotos.ItemsSource = photos;  
    76. }  
    77. else  
    78. {  
    79. ShowAlert("No photos found.");  
    80. }  

    相关文章:

    • 2021-09-29
    • 2021-09-14
    • 2021-09-19
    • 2021-09-19
    • 2021-09-19
    • 2018-12-07
    • 2021-11-04
    • 2021-12-12
    猜你喜欢
    • 2022-01-08
    • 2022-02-20
    • 2019-12-17
    • 2021-06-29
    • 2022-12-23
    • 2021-11-30
    • 2021-09-11
    相关资源
    相似解决方案