将两个稍微不同的JSON字符串(相同的结构,不同的名称)反序列化为同一个类

时间:2016-04-27 16:16:18

标签: c# json.net deserialization

我的问题很简单:我需要将两个大的JSON字符串反序列化为一个类,但字符串略有不同。这是第一个:

@{
    var group = (SelectList)ViewBag.Group;
 }

@Html.ListBox("Group", (IEnumerable<SelectListItem>)ViewBag.Group, new { style = "width: 300px;" })

和另一个:

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

你可以看到一次是“人”,另一次是“人”。这有什么简单的解决方案吗?我在考虑在班上创建两个列表

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

并且在反序列化之后以某种方式手动组合。但必须有一个更简单的方法。

顺便说一句,这不是我需要反序列化的确切代码。我只是想让主要想法尽可能简单。

3 个答案:

答案 0 :(得分:3)

一个简单的解决方案是在您的类中使用单个列表,但随后添加另一个具有引用相同列表的另一个名称的setter。只要您使用[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

修改

要解决您的意见: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

答案 1 :(得分:0)

两者都包含List<Person>。将它们反序列化为两个类,例如normal,但只需获取每个类的List并将它们添加到同一个List中,因为它们包含相同的信息。

答案 2 :(得分:0)

你可以通过你不同的&#39;字符串分为不同的JObject s。然后从不同的名称中取出两个内部集合(JObject允许),然后将这些集合反序列化为具有一个共同c#类的集合。

看起来像是反序列化部分JSON区域,所以,你可以看看this link