Verwenden von JSON-Patch zum Hinzufügen von Werten zu einem Wörterbuch

8

Überblick

Ich versuche, einen Webdienst mit ASP.NET Core zu schreiben, mit dem Clients den Status eines Mikrocontrollers abfragen und ändern können. Dieser Mikrocontroller enthält eine Reihe von Systemen, die ich in meiner Anwendung modelliere - zum Beispiel ein PWM-System, ein Aktor-Eingabesystem usw.

Die Komponenten dieser Systeme haben alle bestimmte Eigenschaften , die mit einer JSON-Korrektur Anfrage abgefragt oder geändert werden können. Zum Beispiel kann die 4. PWM auf dem Mikro über eine HTTP-Anfrage mit {"op":"replace", "path":"/pwms/3/enabled", "value":true} aktiviert werden. Um dies zu unterstützen, verwende ich die AspNetCore.JsonPatch Bibliothek.

Mein Problem ist, dass ich versuche, die JSON-Patch-Unterstützung für ein neues "CAN-Datenbank" -System zu implementieren, das einen Definitionsnamen logisch einer bestimmten CAN-Nachrichtendefinition zuordnen sollte, und ich nicht sicher, wie man das macht.

Details

Das folgende Diagramm modelliert das CAN-Datenbanksystem. Eine CanDatabase -Instanz sollte logisch ein Wörterbuch der Form IDictionary<string, CanMessageDefinition> enthalten.

Um das Erstellen neuer Nachrichtendefinitionen zu unterstützen, sollte meine Anwendung Benutzern erlauben, JSON-Patch-Anfragen wie folgt zu senden:

%Vor%

Hier würde my_new_definition die Definition Name definieren und das mit value verknüpfte Objekt sollte zu einem CanMessageDefinition Objekt deserialisiert werden. Dies sollte dann als neues Schlüssel-Wert-Paar im CanDatabase -Wörterbuch gespeichert werden.

Das Problem ist, dass path einen Eigenschaftspfad angeben sollte, der für statisch typisierte Objekte ... na ja, statisch wäre (eine Ausnahme davon ist, dass man referenzieren kann) Array-Elemente zB /pwms/3 wie oben).

Was ich versucht habe

A. Der Ansatz Leeroy Jenkins

Vergessen Sie die Tatsache, dass ich weiß es wird nicht funktionieren - Ich habe versucht, die Implementierung unten (die statische Eingabe nur verwendet, obwohl ich dynamische JSON Patch-Pfade unterstützen muss) nur um zu sehen, was passiert.

Implementierung

%Vor%

Test

%Vor%

Ergebnis

Ein InvalidCastException wird an der Stelle geworfen, an der ich versuche, die angegebenen Änderungen auf JsonPatchDocument anzuwenden.

Seite:

%Vor%

Ausnahme:

%Vor%

B. Verlassen Sie sich auf dynamisches JSON-Patching

Ein vielversprechender Angriffsplan schien sich auf dynamisches JSON-Patching zu stützen, bei dem Patch-Operationen auf Instanzen von %Code%. Dadurch können Sie JSON-Patch-Dokumente zum Hinzufügen, Entfernen oder Ersetzen von Eigenschaften verwenden, da Sie mit einem dynamisch typisierten Objekt arbeiten.

Implementierung

%Vor%

Test

%Vor%

Ergebnis

Durch diese Änderung kann dieser Teil meines Tests ausgeführt werden, ohne dass Ausnahmen ausgelöst werden, aber JSON Patch weiß nicht, wie ExpandoObject as deserialisiert werden soll. Dies führt dazu, dass die Daten im Wörterbuch als value gespeichert werden a JObject :

Wäre es möglich, JSON Patch zu sagen, wie man die Informationen zufällig deserialisiert? Vielleicht etwas in Richtung der Verwendung eines Attributs CanMessageDefinition in JsonConverter ?

%Vor%

Zusammenfassung

  • Ich muss JSON-Patch-Anfragen unterstützen, die einem Wörterbuch Werte hinzufügen
  • Ich habe versucht, die rein statische Route herunterzufahren, die fehlgeschlagen ist
  • Ich habe versucht, dynamisches JSON-Patching zu verwenden
    • Dies hat teilweise funktioniert, aber meine Daten wurden als Definitions type anstatt des beabsichtigten Typs
    • gespeichert
    • Gibt es ein Attribut (oder eine andere Technik), das ich auf meine Eigenschaft anwenden kann, um es auf den richtigen Typ (nicht einen anonymen Typ) zu deserialisieren?
Tagc 16.01.2017, 15:26
quelle

1 Antwort

1

Da es keinen offiziellen Weg dafür zu geben scheint, habe ich eine Temporary Solution ™ (eine Lösung, die gut genug funktioniert, damit ich sie für immer aufbewahre) entwickelt.

>

Um den Eindruck zu erwecken, dass JSON Patch wörterbuchartige Operationen handhabt, habe ich eine Klasse namens DynamicDeserialisationStore erstellt, die von DynamicObject und nutzt die Unterstützung von JSON Patch für dynamische Objekte.

Genauer gesagt überschreibt diese Klasse Methoden wie TrySetMember , TrySetIndex , TryGetMember usw., um sich im Wesentlichen wie ein Wörterbuch zu verhalten, mit der Ausnahme, dass sie alle diese Operationen an Rückrufe ihres Konstruktors delegiert.

Implementierung

Der folgende Code enthält die Implementierung von DynamicDeserialisationStore . Es implementiert IDictionary<string, object> (das ist die Signatur, die JSON Patch benötigt, um mit dynamischen Objekten zu arbeiten), aber ich implementiere nur das Minimum der Methoden, die ich benötige.

Das Problem mit der Unterstützung von dynamischen Objekten durch JSON Patch besteht darin, dass Eigenschaften auf JObject instances gesetzt werden, d. h. die Deserialisierung wird nicht automatisch durchgeführt, wie dies beim Festlegen statischer Eigenschaften der Fall wäre, da der Typ nicht abgeleitet werden kann. DynamicDeserialisationStore wird für den Objekttyp parametrisiert, der versucht, diese JObject Instanzen automatisch zu deserialisieren, wenn sie gesetzt sind.

Die Klasse akzeptiert Callbacks, um grundlegende Dictionary-Operationen zu behandeln, anstatt ein internes Dictionary selbst zu verwalten, weil ich in meinem "echten" Systemmodell-Code kein Wörterbuch verwende (aus verschiedenen Gründen) - ich lasse es einfach so aussehen an Kunden.

%Vor%

Tests

Die Tests für diese Klasse sind unten aufgeführt. Ich erstelle ein falsches Systemmodell (siehe Bild) und führe verschiedene JSON-Patch-Operationen darauf aus.

Hier ist der Code:

%Vor%     
Tagc 23.01.2017, 11:47
quelle

Tags und Links