2017-08-27 64 views
0

我是.NET和MVC的新手。正在努力將一些JSON反序列化爲ViewBag中的對象。 JSON來自Azure搜索。我已經驗證了WebHttpRequest返回JSON這樣的:反序列化MVC中的JSON

{ 
    "@odata.context": "https://url.toazuresearch/indexes('index01')/$metadata#docs", 
    "value": [ 
     { 
      "@search.score": 0.31507686, 
      "Id": "34", 
      "Date": "2017-08-24T09:14:56.193Z", 
      "Domain": "domain.com", 
      "RuleName": "Legacy Reports", 
      "Log": "Log text", 
      "ChangeId": "changeId", 
      "ParentId": "0", 
      "Comments": "Comments" 
     }, 
     { 
      "@search.score": 0.2553736, 
      "Id": "35", 
      "Date": "2017-08-24T09:14:56.193Z", 
      "Domain": "domain.com", 
      "RuleName": "Legacy Reports", 
      "Log": "Log text", 
      "ChangeId": "changeId", 
      "ParentId": "0", 
      "Comments": "Comments" 
     } 
    ] 
} 

我的類看起來是這樣的:

[DataContract] 
public class SearchResult 
{ 
    [DataMember] 
    public float SearchScore { get; set; } 
    [DataMember] 
    public string Id { get; set; } 
    [DataMember] 
    public DateTime Date { get; set; } 
    [DataMember] 
    public string Domain { get; set; } 
    [DataMember] 
    public string RuleName { get; set; } 
    [DataMember] 
    public string Log { get; set; } 
    [DataMember] 
    public string ChangeId { get; set; } 
    [DataMember] 
    public string ParentId { get; set; } 
    [DataMember] 
    public string Comments { get; set; } 
} 

我的控制器來處理這裏的響應代碼:

try 
{ 
    WebResponse response = request.GetResponse(); 
    using (Stream responseStream = response.GetResponseStream()) 
    { 
     StreamReader reader = new StreamReader(responseStream, Encoding.UTF8); 

     DataContractJsonSerializer serializer = 
      new DataContractJsonSerializer(typeof(IEnumerable<SearchResult>)); 
     var results = 
      (IEnumerable<SearchResult>)serializer.ReadObject(responseStream); 

     ViewBag.SearchResults = results; 
    } 
} 
catch (WebException ex) 
{ 
    WebResponse errorResponse = ex.Response; 
    using (Stream responseStream = errorResponse.GetResponseStream()) 
    { 
     StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); 
     ViewBag.SearchError = reader.ReadToEnd(); 
     ViewBag.SearchResults = "0 Results"; 

    } 
    throw; 
} 

而且最後,我試圖在我看來循環播放結果:

@foreach (var searchResult in ViewBag.SearchResults) 
{ 
    @searchResult.Id <br /> 
} 

我只是得到一個空白頁面。當我在VS中測試時沒有例外。

回答

3

您遇到的反序列化問題是由於Azure搜索響應將值搜索結果包裝在值數組中。讀取結果的一種方法是創建自己的包裝對象,以反映Azure有效負載。

例如:

public class AzureSearchResponse 
{ 
    [JsonProperty("@odata.context")] 
    public string ODataContext { get; set; } 
    public List<SearchResult> value { get; set; } 
} 

您可能會發現它有助於使用Newtonsoft.Json庫,它可以使用的NuGet命令進行安裝:

Install-Package Newtonsoft.Json 

然後,您可以用一個命令,如反序列化:

var searchResult = JsonConvert.DeserializeObject<AzureSearchResponse>(reader.ReadToEnd()); 

對於與您的CL不匹配的屬性名稱與屬性[R屬性名裝點

[JsonProperty(PropertyName = "@search.score")] 

無需[DataContract]和[DataMember]標註屬性

關於獲取數據到你的觀點,我建議您使用視圖模型,而不是在ViewBag 。你可以創建一個基本上是你的反序列化的搜索結果的ViewModel,並在你的剃鬚刀中進行迭代。

在您的視圖的頂部裝飾與模型的關鍵字,如:

@model Namespace.Path.To.Your.Model 

你的模型類可能包含列表,然後使用你的循環,例如

<ul> 
@foreach(var result in Models.Results) { 
    <li>@result.RuleName</li> 
} 
</ul> 

希望這可以幫助,讓我知道你是如何得到。

問候 菲爾

+1

大答案和詳細的完美。幹得好 – Darthchai

+0

這是我在幫助論壇上收到的最佳答案之一。感謝您的詳細信息,以及ViewModels上的提示。我現在正在解析Azure搜索結果。再次感謝! – JOb801

6

使用的Json.Net代替DataContractJsonSerializer更容易。

首先你的模型:

public class Value 
{ 
    [JsonProperty("@search.score")] 
    public double SearchScore { get; set; } 
    public string Id { get; set; } 
    public string Date { get; set; } 
    public string Domain { get; set; } 
    public string RuleName { get; set; } 
    public string Log { get; set; } 
    public string ChangeId { get; set; } 
    public string ParentId { get; set; } 
    public string Comments { get; set; } 
} 

public class RootObject 
{ 
    [JsonProperty("@odata.context")] 
    public string Contextcontext { get; set; } 
    public List<Value> value { get; set; } 
} 

序列化代碼:

var result = JsonConvert.DeserializeObject<RootObject>(reader.ReadToEnd()); 

編輯

如果你真的想用DataContractJsonSerializer方式,你的模型應該是

[DataContract] 
public class SearchResult 
{ 
    [DataMember(Name = "@search.score")] 
    public float SearchScore { get; set; } 
    [DataMember] 
    public string Id { get; set; } 
    [DataMember] 
    public DateTime Date { get; set; } 
    [DataMember] 
    public string Domain { get; set; } 
    [DataMember] 
    public string RuleName { get; set; } 
    [DataMember] 
    public string Log { get; set; } 
    [DataMember] 
    public string ChangeId { get; set; } 
    [DataMember] 
    public string ParentId { get; set; } 
    [DataMember] 
    public string Comments { get; set; } 
} 

[DataContract] 
public class RootObject 
{ 
    [DataMember(Name = "@odata.context")] 
    public string Context { get; set; } 
    [DataMember] 
    public List<SearchResult> value { get; set; } 
} 

您的序列代碼(請參閱日期時間處理代碼)

var settings = new DataContractJsonSerializerSettings() 
{ 
    DateTimeFormat = new DateTimeFormat(@"yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture) 
}; 
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(RootObject),settings); 

var results = (RootObject)serializer.ReadObject(responseStream);