Laden...

Wie kann ich mehrdimensionales JSON auf Key-Existenz überprüfen?

Erstellt von Exception234 vor 3 Jahren Letzter Beitrag vor 3 Jahren 783 Views
E
Exception234 Themenstarter:in
10 Beiträge seit 2020
vor 3 Jahren
Wie kann ich mehrdimensionales JSON auf Key-Existenz überprüfen?

Huhu,

ich nutze Newtonsoft.Json um den content der customfields aus folgendem Object zu ermitteln:

total	"2"
issues	
 0	
  id	"1"
  fields	
   customfield_1	"one"
   customfield_2
    value:          "one"
    id:             "1"
 1	
  id	"2"
  fields	
   customfield_1	"two"
   customfield_2
    value:          "two"
    id:             "2"

Es fehlt jedoch eine Möglichkeit verschachtelte Schlüssel auf Existenz abzufragen. Z.B. so

Object.ContainsKey("total"));

Die Klasse JObject bietet die Möglichkeit nur für Schlüssel in erster Ebene. JToken scheinbar gar nicht. Meine Codevariante funktioniert leider nicht.

if (jObject["issues"] != null)
{
	foreach (JToken issue in jObject["issues"])
	{
		if (issue["fields"] != null)
        {
			foreach (string customfield in myCustomfields)
			{
				if (issue["fields"][customfield] != null)
				{
					if (issue["fields"][customfield]["id"] != null)
					{
                        //get content                  
					}
					if (issue["fields"][customfield]["value"] != null)
					{
                         //get content              
					}
				}
			}			
		}
	}
}

Bliebe noch die Möglichkeit mit String Operationen drauf los zugehen ... weiß jemand, ob es auch eleganter funktioniert?

Danke Euch

H
48 Beiträge seit 2020
vor 3 Jahren

Warum serialisierst du nicht einfach das Objekt?

E
Exception234 Themenstarter:in
10 Beiträge seit 2020
vor 3 Jahren

Achso: Das tatsächliche Object ist recht groß und ich brauche nur sehr wenig vom Inhalt. Ich hatte auf performante Boardmittel von JSON gehofft um gezielt zu navigieren

2.078 Beiträge seit 2012
vor 3 Jahren

Ich hatte auf performante Boardmittel von JSON gehofft um gezielt zu navigieren

Wenn es dir wirklich um Performance und Speicherauslastung geht, musst Du umdenken.
Sobald Du frei navigieren können willst, wird es langsam, stattdessen musst Du Token für Token lesen und je nach Situation entscheiden, wie Du damit umgehst.
Das hat natürlich den Nachteil, dass der Code komplexer wird. Dein Code-Snippet funktioniert so nicht mehr, stattdessen brauchst Du Schleifen, die so lange überspringen (oder hinein springen), bis sie dort gelandet sind, wo Du hin willst.

Für XML gibt's da den XmlReader, damit hab ich mal das Lesen von einem 600MB-XML deutlich beschleunigt, ein ehemaliger Kollege hatte Spaß mit einem 10GB-XML (kein Witz)
In Newtonsoft.Json scheint dafür die JsonTextReader-Klasse gedacht zu sein, selber genutzt habe ich sie aber noch nicht.

Und dann gibt's noch System.Text.Json, das wurde von Microsoft entwickelt, um eine möglichst performante Möglichkeit zu bieten, JSON zu lesen.
Ob das wirklich so gut ist, weiß ich nicht, ich hab's nur anfangs mal ausprobiert und für einfache Fälle konnte es (damals) noch nicht bei Newtonsoft.Json mithalten. Wie das heute aussieht, musst Du ausprobieren.

By the way:
Von welcher Größenordnung reden wir hier?

E
Exception234 Themenstarter:in
10 Beiträge seit 2020
vor 3 Jahren

Klingt vernünftig. Die Varianten schau ich mir mal an. 300MB sollte die Grenze sein - da wäre noch viel Luft zu deinem Wert. Danke

5.657 Beiträge seit 2006
vor 3 Jahren

Meine Codevariante funktioniert leider nicht.

Wenn du beim nächsten Mal schreibst, was nicht funktioniert, kann man dir auch dabei helfen, den Fehler zu finden. "Funktioniert nicht" ist keine Fehlerbeschreibung, mit der irgendjemand etwas anfangen kann.

Siehe [Hinweis] Wie poste ich richtig?, besonders Punkt 5

Weeks of programming can save you hours of planning

T
2.219 Beiträge seit 2008
vor 3 Jahren

Klingt eigentlich nach dem falschen Ansatz.
Wenn dies gültiges Json ist, müsstest du im einfachsten Fall nur eine Klasse anlegen, die den aufbau des Json Objekt hat.
Dann kannst du das Json zu einer Instanz der Klasse deserialisieren.
Dann kannst du direkt mit der Klasse arbeiten.

Wenn du aktuell mit 300 MB Json arbeitest, sollten da weit unter 100 MB RAM für die Instanz nötig sein.
Dann musst du dich auch nicht mit dem durcharbeiten des Json kümmern.
Du musst dann nur die innere Liste eines Objekts durchlaufen und die entsprechenden Einträge ermitteln.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

H
48 Beiträge seit 2020
vor 3 Jahren

300 MB Json zu serialisieren um auf ein paar Felder zuzugreifen ist dämlich ja aber du kannst doch einfach auf das Feld direkt zugreifen

using System;
using Newtonsoft.Json.Linq;

public class Program
{
	public static void Main()
	{
		var json = @"{
  ""total"": 1,
  ""issues"": {
    ""id"": 1,
    ""fields"": {
      ""field1"": 1,
      ""field2"": 2
    }
  }
}";
		
		JObject data = JObject.Parse(json);
		Console.WriteLine("Total: " + data["total"]);
	}
}

Willst du wissen ob das feld existiert dann prüfe einfach auf null
if (data["existiertnicht"] != null) oder eben ContainsKey

wenn es dir um den Joken in deiner umständlcihen beschreibung geht dann kannst du auch da einfach auf null prüfen.
JObjekt ist unter der Haube ein Dictionary (IDictionary<string, JToken) daher gibt es hier ein Contains und beim JToken eben nicht

https://dotnetfiddle.net/ZGyAWR