我是.NET和MVC的新手。努力将一些JSON反序列化为ViewBag中的对象。 JSON来自Azure搜索。我已经验证了WebHttpRequest返回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中测试没有例外。
答案 0 :(得分: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; }
}
您的序列化代码(请参阅DateTime处理代码)
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);
答案 1 :(得分: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());
对于与您的CLR属性名称不匹配的属性名称,使用属性
进行装饰[JsonProperty(PropertyName = "@search.score")]
不需要[DataContract]和[DataMember]属性
关于将数据放入您的视图,我建议您使用View Model而不是ViewBag。您可以创建一个基本上是反序列化搜索结果的ViewModel,并在剃刀中迭代它。
在视图顶部使用模型关键字进行装饰,例如:
@model Namespace.Path.To.Your.Model
您的模型类可以包含List,然后在循环中使用它,例如
<ul>
@foreach(var result in Models.Results) {
<li>@result.RuleName</li>
}
</ul>
希望这会有所帮助,让我知道你是如何继续的。
此致 菲尔