2015-12-18 16 views
1

我有一個應用程序將對象列表序列化爲json,然後通過套接字連接將其發送到客戶端。使用PopulateObject來填充列表而不重複條目

在客戶端,我使用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 =「ID」)等。我似乎無法讓json識別兩個對象是相同的,如果他們的ID屬性匹配。

+0

你是不是也用'PreserveReferencesHandling = PreserveReferencesHandling.Objects'序列化數據時在客戶端設置?如果你想保留引用,這是必須的 - 它通過在JSON中編寫特殊的'$ id'和'$ ref'屬性來工作,以幫助解序列化。有關詳細信息,請參閱@ Plutonix的答案。 –

回答

0

那不是什麼PreserveReferencesHandling做你試圖重寫的equals()函數。它用於避免序列化重複對象,有效縮短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個齊格對象,但所得到的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); 
    } 
} 

這增加只是那些價值/ id不主列表中已經存在,添加任何你需要檢測欺騙的邏輯。

參見:Preserving Object References

0

有serilized對象

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); 
} 
+0

是的,我已經嘗試過,看起來沒有幫助。我不確定Json.net是否使用Equals方法來確定相等性。 – MRizzo

+0

您是否在JsonSerializerSettings中嘗試了此設置ObjectCreationHandling.Reuse? –

+0

是的,我也試過,並沒有改變。我開始認爲可能有一個屬性可以用來將「ID」屬性指定爲唯一標識符。但就像我說過的,我嘗試過的任何屬性都沒有任何影響。 – MRizzo