使用PopulateObject填充列表而不复制条目

时间:2015-12-18 13:24:42

标签: c# json json.net

我有一个应用程序将对象列表序列化为json,然后通过套接字连接将其发送给客户端。

在客户端,我使用JsonConvert.PopulateObject()用新接收的json数据填充现有的对象列表。但是,如果存在任何重复项,则会不断将对象附加到列表中,而不是重复使用列表中的现有对象。

以下是我正在序列化/反序列化的课程:

public class Process : INotifyPropertyChanged
{
    private int _id;
    private string _name;

    public int ID
    {
        get { return _id; }
        set
        {
            if (value != _id)
            {
                _id = value;
                NotifyPropertyChanged("ID");
            }
        }
    }

    public string Name
    {
        get { return _name; }
        set
        {
            if (value != _name)
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }

    public Process() { }

    public Process(int id, string name)
    {
        ID = id;
        Name = name;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

这是我使用的PopulateObject代码:

JsonSerializerSettings settings = new JsonSerializerSettings() { PreserveReferencesHandling = PreserveReferencesHandling.Objects, ObjectCreationHandling = ObjectCreationHandling.Auto };
ObservableCollection<Process> Processes = new ObservableCollection<Process>();
JsonConvert.PopulateObject(response, Processes, settings);

尽管属性值完全相同,但json.net似乎并不知道对象是重复的引用。我已经在我的类上尝试了多个JsonObject属性组合(IsReference = true,Id =&#34; ID&#34;)等等。我似乎无法让json识别两个对象是否相同,如果他们的ID财产匹配。

2 个答案:

答案 0 :(得分:0)

您是否已尝试覆盖已加强化对象的Equals()函数

public override bool Equals(Process p)
{
    // If parameter is null return false:
    if ((object)p == null)
    {
        return false;
    }

    // Return true if the fields match:
    return (ID == p.ID);
}

答案 1 :(得分:0)

这不是PreserveReferencesHandling的作用。它用于避免序列化重复对象,有效缩短json结果。例如:

List<NameValuePair> nvpList = new List<NameValuePair>();

NameValuePair z = new NameValuePair(Name="Ziggy", Value= 42);
nvpList.Add(z);
nvpList.Add(new NameValuePair("Zoey", 3));
nvpList.Add(z);

JsonSerializerSettings settings = new JsonSerializerSettings() { 
                PreserveReferencesHandling = PreserveReferencesHandling.Objects, 
                };
string json = JsonConvert.SerializeObject(nvpList, Formatting.Indented,
               settings);

我的List有2个Ziggy对象,但生成的json是:

[
  {
    "$id": "1",
    "Name": "Ziggy",
    "Value": 42
  },
  {
    "$id": "2",
    "Name": "Zoey",
    "Value": 3
  },
  {
    "$ref": "1"
  }
]

它分配内部$Id,然后引用重复对象的内容。这仅适用于对象引用相同的情况。如果创建并添加了2个Ziggy对象 - 即使具有相同的值 - json将反映并重复它们。

为防止反序列化时列表中出现重复,您必须使用映射器或等效代码:

List<NameValuePair> tmp = JsonConvert.DeserializeObject<List<NameValuePair>>(json);

foreach (NameValuePair nvp in tmp)
{
    if (nvpList.Where(w => w.Value == nvp.Value).FirstOrDefault() == null)
    {
        nvpList.Add(nvp);
    }
}

这只会添加主列表中尚不存在Value / Id的那些,添加检测欺骗所需的任何逻辑。

请参阅:Preserving Object References