2015-05-04 10 views
26

ich mit dem Ernte-API spielte und ich versuche, automatisch so einfach wie möglich die Objekte auf der Karte, leider, wenn ich eine Anfrage wie GET /projects tue erzeugt es ein Ergebnis in etwa so:dynamisch auf eine Eigenschaft in RestSharp Deserialisieren

[{ 
    project: { 
     name: "Test" 
    } 
}, 
{ 
    project: { 
     name: "Test 2" 
}] 

In RestSharp, kann es nicht direkt tun:

client.Execute<List<Project>>(request) 

Weil es für eine Eigenschaft Project genannt aussehen wird. Also muß ich eine andere Klasse machen, die die Eigenschaft hat, und es so nennen:

client.Execute<List<ProjectContainer>>(request) 

Ich will nicht eine ‚Container‘ Klasse für jede Einheit machen, so dass ich dachte, dass ich eine clevere Lösung gefunden eine Klasse mache ich auf alle verwenden können:

public class ListContainer<T> where T : IHarvestEntity 
{ 
    public T Item { get; set; } 
} 

Aber natürlich hat der Deserializer keine Ahnung, braucht es die Entität-Namen zuzuordnen (oder „Projekt“) auf die Eigenschaft Item. In der Restsharp-Dokumentation habe ich festgestellt, dass ich [DeserializeAs(Name = "CustomProperty")] verwenden kann, um dem Deserializer mitzuteilen, welches Feld dieser Eigenschaft zugeordnet werden soll. Attribute erlauben jedoch nur Konstanten, was bedeutet, dass ich nicht tun kann:

Kennt jemand eine clevere Lösung für diese? Also muss ich nicht 10 verschiedene Container-Klassen erstellen?

Antwort

6

Ich empfehle Ihnen, das XPath-Äquivalent für Json zu verwenden. Mit Json.NET können Sie die Zeichenfolge parse erstellen und ein dynamisches Objekt erstellen.

Mit SelectToken können Sie Werte abfragen oder Linq verwenden.

Der Code sieht ungefähr so ​​aus (ich habe es nicht getestet):

// execute the request 
RestResponse response = client.Execute(request); 
var content = response.Content; // raw content as string 

JObject o = JObject.Parse(content); 

IList<string> projectNames = o.SelectToken("project").Select(s => (string)s.name).ToList(); 

Sie können die Pfade codieren oder die Pfade festlegen, irgendwie, das Sie mögen.

--- --- Bearbeiten

Hier ist ein Beispiel, das ich getestet, den JSON-String in eine Liste von Projekten zu konvertieren.

var projects = JArray.Parse(response.Content).Select(r => new Project(r["project"]["name"].Value<string>())).ToList(); 
+0

Dynamische Objekt gegeben werden könnte, ist wahrscheinlich die Antwort auf die Frage, aber viele Entwickler würde Sie warnen, einfach die XYZModel-Klassen zu implementieren und diese zu verwenden; Sie erhalten alle Vorteile und Garantien Ihres Compilers und riskieren (dieselbe Klasse von) Laufzeitausnahmen nicht. –

+1

Demokratisch denke ich, ich sollte Ihnen die Prämie geben, aber ich fühle, dass die Antwort von Mikko die Frage richtiger für meine Situation beantwortet. Weil ich in Ihrem Beispiel die automatische Zuordnung zur Entity verliere, was die ganze Idee dahinter ist. Liege ich damit falsch? – Chris

+0

Mapping auf ein Objekt ist möglich, mit dem Projekt-Objekt aus der Antwort von Mikko: var Projekt = neues Projekt (o.SelectToken ("Projekt"). SelectToken ("Name"). Wert) –

2

Um es wirklich einfach zu halten, können Sie List<dynamic> verwenden und Zugriff auf die Eigenschaft/Eigenschaften von Namen mit einem Einzeiler.

var names = client.Execute<List<dynamic>>(request).Data.Select(
       item => item["project"]["name"]).ToList(); // list of names 

Wenn dies nicht ausreicht, dann könnten Sie Ihren eigenen Mapper improvisiert und eine Sammlung von z extrahierenProject Instanzen:

var projects = client.Execute<List<dynamic>>(request).Data.Select(
       item => Map<Project>(item)).ToList(); // list of Project instances 

wo Map Methode so etwas wie

public T Map<T>(dynamic item) where T : class 
{ 
    // inline for clarity 
    var mappings = new Dictionary<Type,Func<dynamic,object>> 
     { 
      { typeof(Project), map => new Project(map["project"]["name"]) } 
     }; 

    return (T)mappings[typeof(T)].Invoke(item); 
} 

Project definiert als

public class Project 
{ 
    public Project(string name) 
    { 
     Name = name; 
    } 
    public string Name { get; set; } 
}