2017-08-27 68 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);