2017-12-21 9 views
0

Ich schreibe ein Programm, um Daten zwischen unserem Studentenaktensystem und dem Finanzsystem zu integrieren. Das SRS ist eine cloudbasierte Lösung, während das Finanzsystem on-prem ist. Daten müssen aus dem SRS mithilfe seiner RESTful-API extrahiert werden. Ich plane dann, die zurückgegebenen Ressourcen in eine Staging-Datenbank für die Integration mit dem Finanzsystem zu schreiben. Nach ein wenig Recherche habe ich mich entschieden, RestSharp als Grundlage für meine Lösung zu verwenden.Deserialisierung der REST-Ressource zum generischen Objekt

Nach dem Recommended Usage Leitfaden konnte ich eine Lösung, die erfolgreich Anfragen und Deserialisierung der Antwortdaten in meine Klassen erhalten. Allerdings habe ich eine kleine Geschwindigkeitsbegrenzung und brauche ein wenig Hilfe, um wieder in Gang zu kommen.

Die SRS-Rest-API enthält die Ressource PostalAddressOccupancy. Gemäß der SRS-API-Dokumentation hat folgende Struktur:

enter image description here

Mein Problem mit dem Insassen Eigenschaft ist. Dies kann, wie durch den gemischten Typ angezeigt, jeder einer Anzahl von anderen Ressourcentypen sein (dh Student, Staff, Guardian usw.).

Ich kann dies leicht in meinem Datenmodell mit Generika darstellen. ZB

public class PostalAddressOccupancy<T> 
{ 
    public DateTime EffectiveDate { get; set; } 
    public DateTime EndDate { get; set; } 
    public string EntityType { get; set; } 
    public string Href { get; set; } 
    public string Id { get; set; } 
    public bool IsCorrespondenceAddress { get; set; } 
    public T Occupant { get; set; } 
    public PostalAddress PostalAddress { get; set; } 
    public string PostalAddressType { get; set; } 

    public static PostalAddressOccupancy<T> GetPostalAddressOccupancy(string id) 
    { 
     var request = new RestRequest 
     { 
      Resource = "PostalAddressOccupancy/{Id}", 
      RootElement = "postalAddressOccupancy" 
     }; 

     request.AddParameter("Id", id, ParameterType.UrlSegment); 

     RestApiClient restApiClient = new RestApiClient("SRS API"); 
     return restApiClient.Execute<PostalAddressOccupancy<T>>(request); 
    } 

    public static List<PostalAddressOccupancy<T>> GetPostalAddressOccupancies() 
    { 
     List<PostalAddressOccupancy<T>> list = new List<PostalAddressOccupancy<T>>(); 

     var request = new RestRequest 
     { 
      Resource = "PostalAddressOccupancy", 
      RootElement = "postalAddressOccupancies" 
     }; 

     RestApiClient restApiClient = new RestApiClient("SRS API"); 

     foreach (var pao in restApiClient.Execute<List<PostalAddressOccupancy<T>>>(request)) 
     { 
      list.Add(GetPostalAddressOccupancy(pao.Href.Split('/').Last())); 
     } 

     return list; 
    } 
} 

Mein Problem ist, wie RestSharp zu bekommen, um richtig zu verstehen, welche Art von Insassen in den Antwortdaten zurückgegeben werden. Mit der Methode GetPostalAddressOccupancies oben erhalte ich eine Liste von Objekten, bei denen alles außer dem Insassen korrekt deserialisiert ist. Dies wird als Basisobjekttyp zurückgegeben, dessen Eigenschaften als Schlüssel/Wert-Paare enthalten sind.

Muss ich meine Klasse oder generische Eigenschaft mit einigen Tags dekorieren, um einen Hinweis auf die RestSharp-Deserializer zu geben?

Ich habe auch festgestellt, dass Ressourcen Basiseigenschaften (zB EntityType) enthalten. Somit kann ein Insassentyp dadurch identifiziert werden, aber ich bin mir nicht sicher, wie das helfen könnte.

+0

Was ist 'RestApiClient'? Es scheint nicht ein Teil von [restsharp] (https://github.com/restsharp/RestSharp/search?utf8=%E2%9C%93&q=RestApiClient&type=) zu sein. – dbc

Antwort

0

Unter der Haube verwendet RestSharp SimpleJson für JSON-Serialisierung. Im Gegensatz zu Json.NET verfügt dieser Serializer nicht über integrierte Unterstützung für die Deserialisierung von polymorphen Eigenschaften, benutzerdefinierte Konverter oder die Ersatzersetzung.

Also was Sie tun müssen, ist Ihre Antwort in ein Zwischenobjekt analysieren - speziell JsonObject - dann identifizieren Sie den Typ der Insassen auf der Grundlage der vorhandenen Eigenschaften, dann deserialize auf einen endgültigen Typ.

Erstens, es wird viel einfacher sein, eine nicht-generische Basisklasse zu extrahieren für PostalAddressOccupancy<T> wie so:

public abstract class PostalAddressOccupancy 
{ 
    public DateTime EffectiveDate { get; set; } 
    public DateTime EndDate { get; set; } 
    public string EntityType { get; set; } 
    public string Href { get; set; } 
    public string Id { get; set; } 
    public bool IsCorrespondenceAddress { get; set; } 
    public PostalAddress PostalAddress { get; set; } 
    public string PostalAddressType { get; set; } 

    public abstract object GetOccupant(); 
} 

public class PostalAddressOccupancy<T> : PostalAddressOccupancy 
{ 
    public T Occupant { get; set; } 

    public override object GetOccupant() 
    { 
     return Occupant; 
    } 
} 

public class PostalAddress 
{ 
    // Or whatever. Type was not included in the question. 
    public string Address { get; set; } 
} 

Nun stellen Sie haben eine Vielzahl von Insassentypen, einschließlich:

public class Student 
{ 
    public string Name { get; set; } 
    public string StudentId { get; set; } 
} 

public class Staff 
{ 
    public string Name { get; set; } 
    public string StaffId { get; set; } 
} 

dann können Sie gegeben deserialisieren ein zu einem PostalAddressOccupancy<T>IRestResponse wo T könnte Student oder Staff sein, die folgende Methode verwenden, die auf dem Grundstück nam sieht ES tatsächlich in der JSON und wählt die entsprechende letzte Art:

using SimpleJson; 
using RestSharp; 

public static class PostalAddressOccupancyExtensions 
{ 
    public static PostalAddressOccupancy DeserializePostalAddressOccupancy(this RestSharp.IRestResponse response) 
    { 
     var addressObj = (JsonObject)SimpleJson.SimpleJson.DeserializeObject(response.Content); 
     var type = PostalAddressOccupancyExtensions.InferPostalAddressOccupancyType(addressObj); 
     return (PostalAddressOccupancy)SimpleJson.SimpleJson.DeserializeObject(response.Content, type); 
    } 

    static Type InferPostalAddressOccupancyType(JsonObject root) 
    { 
     var occupantObj = root["Occupant"]; 
     if (occupantObj is JsonObject) 
     { 
      var occupant = (JsonObject)occupantObj; 
      // Add logic to recognize other cases as required. 
      if (occupant.ContainsKey("StudentId")) 
      { 
       return typeof(PostalAddressOccupancy<Student>); 
      } 
      else if (occupant.ContainsKey("StaffId")) 
      { 
       return typeof(PostalAddressOccupancy<Staff>); 
      } 
     } 
     // Or throw an exception, if you prefer. 
     return typeof(PostalAddressOccupancy<>).MakeGenericType(new[] { occupantObj.GetType() }); 
    } 
} 

Beachten Sie, dass einen nicht-generischen Basistyp bedeutet, dass die Rückkehr Signatur etwas anderes als object sein kann. Beispielarbeit .Net fiddle.

Beachten Sie, dass, wenn Sie bereit sind, verwenden Sie zusätzliche Optionen haben würde. Z.B. Sie könnte:

+1

Danke dafür. Ich werde es am nächsten Tag ausprobieren –

Verwandte Themen