2017-11-29 12 views
1

私はそれにJSON配列を持つ有効なJSONオブジェクトを持っています。 JSON配列には中括弧はなく、コンマで区切られた混合型のリストが含まれています。私はリストのリストでそれをテストしてみたJson.Netを使用してJSON配列をオブジェクトに逆シリアル化する方法

class myModel 
{ 
    public int ID { get; set; } 
    public int Days { get; set; } 
    public DateTime StartDate { get; set; } 
    public DateTime EndDate { get; set; } 
    public string State { get; set; } 
    public string Page { get; set; } 
    public string Test { get; set; } 
    List<ChildModel> Rows { get; set; } 
} 

:複雑な配列のためのリストを持つ、私はJSONの構造を反映するクラスを作成しました

{ 
    "ID": 17, 
    "Days": 979, 
    "Start_Date": "10/13/2012", 
    "End_Date": "11/12/2012", 
    "State": "", 
    "Page": 1, 
    "Test": "Valid", 
    "ROWS": [ 
     [441210, "A", "12/31/2009", "OK", "Done", "KELLEY and Co'", "12/31/2009", "06/29/2010", "TEXAS", "Lawyers", 6, "", "<img src=\"/includes/images/Icon_done.gif\" border=\"0\" alt=\"Done\" title=\"Done\" />"], 
     [441151, "B", "12/31/2009", "No", "In-process", "Sage & Co", "12/31/2009", "06/29/2010", "CALIFORNIA", "Realtor", 6, "", "<img src=\"/includes/images/Icon_InProcess.gif\" border=\"0\" alt=\"In Process\" title=\"In Process\" />"] 
    ] 
} 

:それはこのようになりますあまりに:

List<List<ChildModel>> Rows { get; set; } 

そして、このような子モデル:

class ChildModel 
{ 
    public int ID { get; set; } 
    public string StatusId { get; set; } 
    public DateTime ContactDate { get; set; } 
    public string State { get; set; } 
    public string Status { get; set; } 
    public string CustomerName { get; set; } 
    public DateTime WorkStartDate { get; set; } 
    public DateTime WorkEndDate { get; set; } 
    public string Territory { get; set; } 
    public string CustType { get; set; } 
    public int JobOrder { get; set; } 
    public string Filler { get; set; } 
    public string Link { get; set; } 
} 
私のProgram.csファイルで

は、私はこのようにそれをデシリアライズしています:

using (StreamReader r = new StreamReader(@"D:\01.json")) 
{ 
    myModel items = JsonConvert.DeserializeObject<myModel>(r.ReadToEnd()); 
} 

私はこのプログラムを実行すると、子オブジェクト(行)が常にnullです。私は間違って何をしていますか?

+0

あなたは 'ChildModel'がオブジェクトではなく配列としてシリアル化されていると言っていますか?シリアライゼーションはあなたのコントロールから外れていますか? –

+2

あなたのリスト内のものとChildModelクラスの間にはマッピングがないからです。デシリアライザは、モデルのどのプロパティにどのような値を入れるべきかを知っていますか?可能であれば、シリアライゼーションを修正し、そうでなければカスタムパーサを構築し、リスト内のデータの順序を変更しないように祈ってください。 –

+1

その配列を 'ChildModel'に非直列化するには、[C#JSON.NET - 異常なデータ構造を使用するレスポンスの逆直列化](https://stackoverflow.com/q/39461518/3744182)の' ObjectToArrayConverter 'を使用できます。 – dbc

答えて

2

Json.Netには、配列を自動的にクラスにマップする機能がありません。これを行うには、カスタムJsonConverterが必要です。ここでは、あなたのために動作する一般的なコンバータです。カスタム[JsonArrayIndex]属性を使用して、クラス内のどのプロパティが配列内のどのインデックスに対応するかを識別します。これにより、JSONが変更された場合にモデルを簡単に更新することができます。また、不要なクラスのプロパティ(たとえば、Filler)を安全に省略することもできます。ここで

コードは次のとおりです。

public class JsonArrayIndexAttribute : Attribute 
{ 
    public int Index { get; private set; } 
    public JsonArrayIndexAttribute(int index) 
    { 
     Index = index; 
    } 
} 

public class ArrayToObjectConverter<T> : JsonConverter where T : class, new() 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(T); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JArray array = JArray.Load(reader); 

     var propsByIndex = typeof(T).GetProperties() 
      .Where(p => p.CanRead && p.CanWrite && p.GetCustomAttribute<JsonArrayIndexAttribute>() != null) 
      .ToDictionary(p => p.GetCustomAttribute<JsonArrayIndexAttribute>().Index); 

     JObject obj = new JObject(array 
      .Select((jt, i) => 
      { 
       PropertyInfo prop; 
       return propsByIndex.TryGetValue(i, out prop) ? new JProperty(prop.Name, jt) : null; 
      }) 
      .Where(jp => jp != null) 
     ); 

     T target = new T(); 
     serializer.Populate(obj.CreateReader(), target); 

     return target; 
    } 

    public override bool CanWrite 
    { 
     get { return false; } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

コンバータを使用するには、以下に示すように、あなたのChildModelクラスをマークアップする必要があります。

[JsonConverter(typeof(ArrayToObjectConverter<ChildModel>))] 
class ChildModel 
{ 
    [JsonArrayIndex(0)] 
    public int ID { get; set; } 
    [JsonArrayIndex(1)] 
    public string StatusId { get; set; } 
    [JsonArrayIndex(2)] 
    public DateTime ContactDate { get; set; } 
    [JsonArrayIndex(3)] 
    public string State { get; set; } 
    [JsonArrayIndex(4)] 
    public string Status { get; set; } 
    [JsonArrayIndex(5)] 
    public string CustomerName { get; set; } 
    [JsonArrayIndex(6)] 
    public DateTime WorkStartDate { get; set; } 
    [JsonArrayIndex(7)] 
    public DateTime WorkEndDate { get; set; } 
    [JsonArrayIndex(8)] 
    public string Territory { get; set; } 
    [JsonArrayIndex(9)] 
    public string CustType { get; set; } 
    [JsonArrayIndex(10)] 
    public int JobOrder { get; set; } 
    [JsonArrayIndex(12)] 
    public string Link { get; set; } 
} 

は、それからちょうどいつものようにデシリアライズし、それがとして動作するはずですあなたは欲しかった。 https://dotnetfiddle.net/n3oE3L

注:私はWriteJsonを実装していませんでした。したがって、モデルをJSONにシリアル化すると、配列形式にシリアル化されません。代わりに、デフォルトのオブジェクト直列化を使用します。

+0

拡張メソッドは魅力的に機能しました。ありがとう。 – SJaka

2

... JSONオブジェクトに

public class Rootobject 
{ 
    public int ID { get; set; } 
    public int Days { get; set; } 
    public string Start_Date { get; set; } 
    public string End_Date { get; set; } 
    public string State { get; set; } 
    public int Page { get; set; } 
    public string Test { get; set; } 
    public object[][] ROWS { get; set; } 
} 

をあなたのデータをデシリアライズするために使用します...そして、ご希望のターゲットオブジェクトにobject[][]を変換ユーティリティ関数を作成...

(視覚スタジオで作成:編集 - >形式を選択して貼り付け - > JSONクラス)

関連する問題