2016-04-27 12 views
4

短い問題で私の問題:2つの大きなJSON文字列を1つのクラスに逆シリアル化する必要があります。ここでは最初のものである:2つの少し異なるJSON文字列(同じ構造体、異なる名前)を同じクラスに逆シリアル化します。

{ 
    "persons": [ 
    { 
     "age":30, 
     "name":"david", 
     "hobbies": [ 
     { 
      "name":"tennis", 
      "hours":5 
     }, 
     { 
     "name":"football", 
     "hours":10 
     } 
    ] 
    }, 
    { 
    "name":"adam", 
    "age":23, 
    "hobbies":[] 
    } 
] 
} 

と他の1:

{ 
    "person": [ 
    { 
     "age":25, 
     "name":"dave", 
     "hobbies":[ 
     { 
      "name":"Basketball", 
      "hours":5 
     }, 
     { 
      "name":"football", 
      "hours":10 
     } 
     ] 
    }, 
    { 
     "name":"Steve", 
     "age":28, 
     "hobbies": [] 
    } 
    ] 
} 

あなたが一度は、それが「人」、そしてそれは「人」だ他の時間だことがわかります。これに簡単な解決策はありますか?私はクラスで2つのリストを作成することを考えていました

List<Person> person; 
List<Person> persons; 

そして、逆シリアル化した後、何とか手作業で結合します。しかし、単純な方法が必要です。

ところで、これはデシリアライズするのに必要な正確なコードではありません。私はちょうど主なアイデアを可能な限りシンプルに保つことを望んでいた

答えて

3

単純な解決策の1つは、クラス内で単一のリストを使用することですが、同じリストを参照する別の名前を持つ代替セッターを追加することです。あなたは[JsonProperty]属性でそれを飾る限り、それを非公開にすることさえできます。こうすることで、クラスのパブリックインターフェイスは正常に見えますが、JSONの両方のプロパティ名でも動作します。

public class RootObject 
{ 
    [JsonProperty("persons")] 
    public List<Person> People { get; set; } 

    // This is visible to Json.Net and references the real list 
    [JsonProperty("person")] 
    private List<Person> Person 
    { 
     set { People = value; } 
    } 
} 

public class Person 
{ 
    [JsonProperty("name")] 
    public string Name { get; set; } 

    [JsonProperty("age")] 
    public int Age { get; set; } 

    [JsonProperty("hobbies")] 
    public List<Hobby> Hobbies { get; set; } 
} 

public class Hobby 
{ 
    [JsonProperty("name")] 
    public string Name { get; set; } 

    [JsonProperty("hours")] 
    public int Hours { get; set; } 

} 

フィドル:https://dotnetfiddle.net/9Dw48J

EDIT

コメントに対処するには:PopulateObjectは盲目的にJSONのデータを使用して、既存のオブジェクトを強化するために使用することができますが、それは、合併のようなものを行うことはありませんあなたは探している。あなたは人を名前(そしておそらく年齢?)とマッチさせる方法を探していて、それらの人々の趣味を組み合わせているようです。そのためには、独自のロジックを記述する必要があります。各リストをデシリアライズしてRootObjectクラスの別々のインスタンスにしてから、後処理ステップでデータをマージすることをお勧めします。 RootObjectクラスでは、別のRootObjectをマージするメソッドを作成できます。おそらく、このような何か:

public class RootObject 
{ 
    ... 

    public void MergeWith(RootObject other) 
    { 
     if (other.People == null) return; 
     if (People == null) People = new List<Person>(); 
     foreach (Person person in other.People) 
     { 
      // You may need to make changes here-- 
      // How do you determine whether two people are the same? 
      Person existingPerson = People.FirstOrDefault(p => p.Name == person.Name && 
                   p.Age == person.Age); 
      if (existingPerson != null) 
      { 
       existingPerson.MergeWith(person); 
      } 
      else 
      { 
       People.Add(person); 
      } 
     } 
    } 
} 

そしてPersonクラスの...あなたをデシリアライズし、マージする

public class Person 
{ 
    ... 

    public void MergeWith(Person other) 
    { 
     if (other.Hobbies == null) return; 
     if (Hobbies == null) Hobbies = new List<Hobby>(); 
     foreach (Hobby hobby in other.Hobbies) 
     { 
      Hobby existingHobby = Hobbies.FirstOrDefault(h => h.Name == hobby.Name); 
      if (existingHobby != null) 
      { 
       // You may need to make changes here-- 
       // What do you do if two hobbies have the same name but different hours? 
       existingHobby.Hours += hobby.Hours; 
      } 
      else 
      { 
       Hobbies.Add(hobby); 
      } 
     } 
    } 
} 

はその後どうなる:

var firstObj = JsonConvert.DeserializeObject<RootObject>(firstJson); 
var secondObj = JsonConvert.DeserializeObject<RootObject>(secondJson); 
firstObj.MergeWith(secondObj); 

フィドル:直列化復元で私を助けhttps://dotnetfiddle.net/8Fiwsd

+0

おかげで多くのことを、。私の現在の知識で、私はこの答えを得るために年を取っていたでしょう。 ところで、私はリストを結合するためにJsonConver.PopulateObjectを使用しようとしています。例えば、ジェイソンは、第1リストの趣味としてバスケットボールを挙げ、第2リストの彼の趣味と同じJason footballをリストアップしているかもしれません。だから私はジェイソンは、両方の趣味を1つのリストに記載してもらいたいが、何らかの理由でPopulateObject doesnt work ..何かアイデアかもしれない?それがうまくいかなければならないのでしょうか? – Jonas

+0

@Jonas - 私はあなたのコメントに答えるために私の答えを更新しました。要するに、PopulateObjectはあなたが望むようにオブジェクトをマージすることはできません。このマージを行うためにカスタムロジックを記述する必要があります。 –

0

両方ともList<Person>を含みます。それらを通常のように2つのクラスにデシリアライズしますが、同じ情報が含まれているので、それぞれが持つリストを取得して同じリストに追加します。

0

「異なる」文字列を異なるJObjectに渡すことができます。次に両方の内部コレクションを別の名前で取得し(JObject)、これらのコレクションを1つの共通のC#クラスを持つコレクションにデシリアライズします。

デシリアライズパーシャルJSONエリアのようですので、this linkをご覧ください。

関連する問題