2016-12-20 3 views
2

Ich habe einen JSON-String wie folgt aus:Remove Duplicate von JObject

{ 
    "managedObjects": [ 
     { 
      "id": "13289",  
      "name": "xxx"  
     }, 
     { 
      "id": "13290",  
      "name": "yyy" 
     }, 
     { 
      "id": "13289",  
      "name": "xxx" 
     }] 
} 

ich JObject

JObject obj = JObject.Parse(json) 

Jetzt bin Parsen, wie das doppelte Element aus diesem Array entfernen? Ich möchte doppeltes Element nach ID aus JObject entfernen (hier id=13289).

Antwort

1

Sie müssen dafür keine Klasse verwenden.

// Get your JObject as you've already shown 
var obj = JObject.Parse(json); 

// Use LINQ to create a List<JToken> of unique values based on ID 
// In this case the first occurence of the ID will be kept, repeats are removed 
var unique = obj["managedObjects"].GroupBy(x => x["id"]).Select(x => x.First()).ToList(); 

// Iterate backwards over the JObject to remove any duplicate keys 
for (int i = obj["managedObjects"].Count() - 1; i >= 0; i--) 
{ 
    var token = obj["managedObjects"][i]; 
    if (!unique.Contains(token)) 
    { 
     token.Remove(); 
    } 
} 

// Re-serialize into JSON 
var result = JsonConvert.SerializeObject(obj); 

Ausgang:

{
"Managed": [
{
"id": "13289",
"name": "xxx"
},
{
"ID": "13290",
"Name": "yyy"
}
]
}

Weitere Objekte neben "Name" als auch alle anderen Knoten gehalten werden.

0

Ich weiß nicht, ob es eine Möglichkeit gibt, dies direkt mit Json.Net zu spezifizieren, aber eine Lösung wäre (wenn Ihre Reihenfolge des Arrays nicht wichtig ist) lesen Sie den JSON in einer benutzerdefinierten Klassenstruktur mit einem überladene Equals Methode:

var obj = JsonConvert.DeserializeObject<Container>(json); 

// ... 

public class Container 
{ 
    public HashSet<ManagedObject> ManagedObjects { get; set;} 
} 

public class ManagedObject 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 

    protected bool Equals(ManagedObject other) 
    { 
     return string.Equals(Id, other.Id); 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     if (obj.GetType() != this.GetType()) return false; 
     return Equals((ManagedObject)obj); 
    } 

    public override int GetHashCode() 
    { 
     return (Id != null ? Id.GetHashCode() : 0); 
    } 
} 
+0

Wäre gut, wenn ohne benutzerdefinierte Klasse wie der JSON so viele innere Objekte nicht nur ID und Name enthält. – balaji

+0

@balaji gibt es einen Konverter dafür: [json2csharp] (http://json2csharp.com/) – Nico

0

Sie könnten eine Art lokal erstellen Managed und dann json auf diese Art deserialisieren. Sie können dann linq verwenden, um die eindeutige Liste zu erhalten. Hier ist eine Konsolenanwendung, die das demonstriert;

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Newtonsoft.Json; 

namespace ConsoleApplication28 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var json = 
       "{\r\n\"managedObjects\": [\r\n{\r\n \"id\": \"13289\",  \r\n \"name\": \"xxx\"  \r\n},\r\n{\r\n \"id\": \"13290\",  \r\n \"name\": \"yyy\" \r\n},\r\n{\r\n \"id\": \"13289\",  \r\n \"name\": \"xxx\" \r\n}]\r\n}"; 

      var managedObjectCollection = JsonConvert.DeserializeObject<ManagedObjectCollection>(json); 

      var distinctManagedObjects = managedObjectCollection.managedObjects.GroupBy(a => a.id).Select(b => b.First()); 

      foreach (var distinctManagedObject in distinctManagedObjects) 
      { 
       Console.WriteLine("Id: {0}, Name: {1}", distinctManagedObject.id, distinctManagedObject.name); 
      } 

      Console.ReadLine(); 
     } 

     class ManagedObjectCollection 
     { 
      public IEnumerable<ManagedObject> managedObjects { get; set; } 
     } 
     class ManagedObject 
     { 
      public int id { get; set; } 
      public string name { get; set; } 
     } 
    } 
} 

Ich schätze, dass Sie ein vereinfachtes Beispiel aber für ein komplexeres Beispiel zur Verfügung gestellt haben würden Sie müssen einfach nur die Klassen erstellen/zu erweitern, zu denen Sie wurden Deserialisieren.

0

Sie benötigen die folgenden Klassen:

public class ManagedObject 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 
} 

public class RootObject 
{ 
    public List<ManagedObject> ManagedObjects { get; set; } 
} 

class MyComparer : IEqualityComparer<ManagedObject> 
{ 
    public bool Equals(ManagedObject x, ManagedObject y) 
    { 
     return x.Id.Equals(y.Id); 
    } 

    public int GetHashCode(ManagedObject obj) 
    { 
     return obj.Id.GetHashCode(); 
    } 
} 

Dann können Sie Ihre json deserialisieren wie folgt:

var test = JsonConvert.DeserializeObject<RootObject>(json); 

und die Duplikate aus seiner Managed Liste entfernen:

var newManagedObject = test.ManagedObjects.Distinct(new MyComparer()).ToList(); 
test.ManagedObjects = newManagedObject; 

A aber etwas unordentlich.