Laden...

Json Meldung mit Array aus Elementen verschiedener Typen parsen

Erstellt von Pippen vor einem Jahr Letzter Beitrag vor einem Jahr 803 Views
P
Pippen Themenstarter:in
18 Beiträge seit 2022
vor einem Jahr
Json Meldung mit Array aus Elementen verschiedener Typen parsen

Hallo zäme
Meine selbst programmierte PLC schickt auf Abfrage via Mqtt eine Json Meldung mit einem Array, das aus Elementen verschiedener Typen besteht. Jedes dieser Elemente entspricht einer Klasse, die ich im C# Programm bereits implementiert habe. Jede dieser Klassen ist von einer Basisklasse abgeleitet. Die Basisklasse enthält nur ein einziges Property, das den Klassentyp der abgeleiteten Klasse als enum beinhaltet.
Bis jetzt habe ich zum Parsen der Json Meldungen "JsonConvert.DeserializeObject<>()" von Json.NET eingesetzt. Ich glaube hier kann ich diese Methode nicht einsetzen, da ich ja keine Klasse angeben kann, die immer passt.

Wie parse ich am besten eine solche JSON Meldung?

16.833 Beiträge seit 2008
vor einem Jahr

Bei typisierten Sprachen wie C# kann eine solche (De)Serialisierung nur gegen eine fest stehende Struktur funktionieren.
Hast Du eine dynamische Struktur musst Du entweder a) mit dynamic arbeiten, was also eine untypisierte Programmierung erfordert und damit auch alle Nachteile hat oder b) Du musst einen eigenen Parser für die Struktur bauen.

dynamic findet man eher in einfachen, risikoarmen Situationen; eigener Parser mit einer typisierten Endstruktur in komplexeren Fällen.
OOP kann Dir dabei helfen (zB durch Interfaces), dass eine Property verschiedene Elemente darstellen kann (Single Value vs Array).

Das Vorgehen in diesem Fall ist aber durchaus "simpel". Hat man bei Messaging-Systemen oft.
Deine Json im Endeffekt ist nichts anderes als ein Container


{
  "type" : "MyTypeA"
   "data" : dynamicBody
}

  • data stellt dabei den dynamischen Inhalt dar, dieses Feld existiert immer
  • type ist die Beschreibung, was in data steckt. Dieses Feld existiert immer und der Type hat immer die gleiche Struktur.

Dann kannst im Endeffekt beide Vorgehensmodelle mischen.


string type = myDynamicJson.Type;
string body = myDynamicJson.Body;
if(type == "MyTypeA")
{
  MyClassForTypeA body = JsonConvert.DeserializeObject<MyClassForTypeA>(body);
}


P
Pippen Themenstarter:in
18 Beiträge seit 2022
vor einem Jahr

Hallo
Danke für Deine Antwort.

Verstehe ich Dich also richtig: Ich soll meine Json Meldung auf diese Dir vorgeschlagene Struktur umbauen?
Dass es in der "ersten Ebene" diese zwei Keys "type" und "data" gibt und im data dann der dynamische Teil.
Oder kann das auch ohne Umbau der Struktur funktionieren?

P
Pippen Themenstarter:in
18 Beiträge seit 2022
vor einem Jahr

Etwas habe ich aber noch vergessen:
Diese JSON Meldung besteht ja aus einem Array solcher "Untermeldungen"/Objekte und jedes Objekt kann von einem anderen Typen sein.
Ich müsste also eine Möglichkeit haben, einzelne Teile aus dem Stream herauszuholen. Gibt es solche Möglichkeiten?


[{"type":"MyTypeA", "data": dynamicBody}, 
 {"type":"MyTypeB", "data": dynamicBody}, 
 ...]

16.833 Beiträge seit 2008
vor einem Jahr

Verstehe ich Dich also richtig: Ich soll meine Json Meldung auf diese Dir vorgeschlagene Struktur umbauen?

Nein, hab ich nirgends gesagt. Das war lediglich ein Beispiel, wie man sowas umsetzen kann.
Natürlich musst Du das noch auf Deinen Fall adaptieren.

P
441 Beiträge seit 2014
vor einem Jahr

Es gibt einige Möglichkeiten, wie du vorgehen kannst. Die von Abt geschilderte hätte eine Änderung der Datenstruktur zur Folge.
Eine andere wäre z.B. mithilfe von JsonObject (Docs) oder JsonDocument (Docs) und dem JSON DOM zu schauen, was der korrekte Typ ist.

Alternativen gibt es noch einige - eigene JsonConverter z.B.

D
152 Beiträge seit 2013
vor einem Jahr

Mit .NET 7 ist für System.Text.Json Type Hierarchies hinzugekommen.

Das könnte ggf. passen, für Json.NET gibt es meine ich so etwas ähnliches.

16.833 Beiträge seit 2008
vor einem Jahr

Die von Abt geschilderte hätte eine Änderung der Datenstruktur zur Folge.

Mh.. ich dachte nicht. Dann verstehe ich

Jede dieser Klassen ist von einer Basisklasse abgeleitet. Die Basisklasse enthält nur ein einziges Property, das den Klassentyp der abgeleiteten Klasse als enum beinhaltet.

falsch.
Für mich liest sich das so, dass die Info im Json existiert, welche Klasse benötigt wird.
Man muss das also nur auslesen (ohne Serialisierung) und mit der Info, dann kann die entsprechende Klasse serialisiert werden.

P
441 Beiträge seit 2014
vor einem Jahr

Oh, du hast Recht - ich habe mich da verlesen. Ich hatte interpretiert, dass die Eigenschaften der Klasse und das enum auf derselben Ebene liegen und nicht als Body Property..

P
Pippen Themenstarter:in
18 Beiträge seit 2022
vor einem Jahr

Kurzes Update:

Ich habe jetzt rausgefunden, wie ich es machen kann:
Ich kann (mit Json.Net) die Parse Methode verwenden, um zu einem JObject zu kommen.


JObject item;

Mit diesem kann ich dann so zu einzelnen Values der entsprechenden Key's kommen:


item["Key"]


Dann kann ich mit


item.ToObject<>()


das Object deserialisieren.

Allen danke für die Unterstützung.