2017-08-27 8 views
0

.NETとMVCの新機能です。 ViewBag内のオブジェクトにいくつかのJSONを逆シリアル化するために苦労します。 JSONはAzure Searchから来ています。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; } 
} 

ここでレスポンスを処理するためのコントローラでの私のコード:私はWebHttpRequestはこのようにJSONを返す確認した

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; 
} 

そして、最終的には、結果をループして表示しようとしています。

空のページが表示されています。 VSでテストしても例外はありません。

答えて

3

発生しているデシリアライズの問題は、検索結果を値配列内にラップするAzure検索の応答が原因です。結果を読み取る1つの方法は、Azureペイロードを反映する独自のラッパーオブジェクトを作成することです。あなたはそれが役に立つNugetコマンドを使用してインストールすることができNewtonsoft.Jsonライブラリを、使用することを見つけるかもしれ

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

:たとえば

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> 

希望する場合は、どうすればいいのか教えてください。

Json.Net代わりの DataContractJsonSerializerは簡単ですを使用して

よろしく フィル

+1

グレート答え、完全に詳しく説明。素敵な仕事 – Darthchai

+0

これは私がヘルプフォーラムで受け取った最高の回答の一つです。詳細、そしてViewModelsのヒントをありがとう。私はAzureの検索結果を解析しています。再度、感謝します! – JOb801

6

まずあなたのモデル:

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()); 

EDIT

あなたが本当に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);