JSON-Objekte richtig parsen

Tueftler

Mitglied
Hallo,
zum Auslesen von json-Daten verwende ich json simple. Beim Parser steh ich vor der Schwierigkeit, dass die key/value Beispiele im Internet immer nur Keys mit eindeutigem Namen haben. Ich will jedoch einen jason-String parsen, der verschachtelt ist, wobei die keys in verschiedenen Blöcken denselben Namen haben können. Wie mach ich das?
Beispiel für einen verschachtelten String (values muss man sich dazudenken);
Code:
[
  {
    "lang":
    "hits": [
      {
        "type":
        "opendict":
        "roms": [
          {
            "headword":
            "headword_full":
            "wordclass":
            "arabs": [
              {
                "header":
                "translations": [
                  {
                    "source":
                    "target": "wollen wir (ein)mal sehen"
                  },
                  {
                    "source":
                    "target":
                  },
                ]
              },
              {
                "header":
                "translations": [
                  {
                    "source":
                    "target":
                  },
                  {
                    "source":
                    "target":
                  },
                ]
              },
            ]
          }
        ]
      }
    ]
  }
]
 

Tueftler

Mitglied
White_Fox:
Richtig! Aber wenn es sich vermeiden lässt, will ich auch keinen Parser schreiben, sondern nur richtig anwenden! Beispiel in meinem Listing: Wenn ich das zweite Target in der zweiten Translation auslesen will, kann ich nicht schreiben:

JSONObject jsonObject = (JSONObject) parser.parse(jsonString);
String target = (String) jsonObject.get("target");

denn woher soll der get wissen, welches target von den vieren im Listing gemeint ist?

MoxxiManagarm:
"Ein "normales" key-value Paar ist ein JSONObject" OK, aber ein JSONObject kann viele key-value Paare und zusätzlich noch ein JASONArray enthalten, oder sehe ich das falsch?
Wenn ich oben geschrieben habe "Die values muss man sich dazudenken", dann war damit gemeint, die keys (Am Ende mit Doppelpunkt) sind geschrieben, die values hab ich weggelassen. Mit meinen (zugegeben rudimentären ) JSON-Kenntnissen kann ich in meinem Listing kein Array entdecken. Gibt es trotzdem da eins?
In den diversen JSON-Beschreibungen werden die key-value-Paare eines JSONObjects als MAP-ähnliche Sammlung bezeichnet, doch bei der MAP sind die keys eine SET-Collection, es gibt keine doppelten Einträge, bei meinem Listing oben, das aus dem realen Leben stammt, aber wohl. Das kann nur funktionieren, wenn der Parser die eckigen und geschweiften Klammern zu interpretieren weiß. Dann aber muss es auch Zugriffsmethoden auf die unterschiedlichen Blöcke geben und genau die such ich. Eine andere Möglichkeit: json simple heißt so, weil man nur mit einfachen json-Strukturen arbeiten kann, dann müsste ich eine andere lib nehmen. Aber das weiß ich nicht.
 
Zuletzt bearbeitet:

MoxxiManagarm

Top Contributor
oder sehe ich das falsch?
Jain, du hast recht ich habe mich etwas falsch ausgedrückt. Ein JSONObject ist eine Menge von keys und values. Die meisten values, die du als key-value-Paar bezeichnest sind aber Datentypen wie boolean und String. Ein Value kann aber auch ein anderen JSONObject oder ein JSONArray sein.

Mit meinen (zugegeben rudimentären ) JSON-Kenntnissen kann ich in meinem Listing kein Array entdecken. Gibt es trotzdem da eins?
Du hast ganz viele Arrays ^^ Jedes []-Paar signalisiert eins. Dein gesamtes JSON ist ein Array, hat aber nur ein JSONObject mit den keys lang und hits. lang hat den value vermutlich vom typ string. hit hingegen hat einen JSONArray value. Auch dieses Array hat in deinem JSON nur einen Eintrag mit den keys type, opendict und roms. type und opendict sind vermutlich wieder strings, aber roms hat wieder ein JSONArray value. Auch dieses enthält nur ein JSONObject. Entgegen den übergeordneten Arrays hat hier das enthaltene JSONArray mit dem key arabs 2 enthaltene JSONObject. Weiter tiefer findest du noch das JSONArray translations, welches jeweils auch 2 JSONObject enthält.

PS.: Ich persönlich finde json simple ist für solche komplexen Strukturen nicht gemacht. json simple enthält leicht viel code mit Object cast.
 
Zuletzt bearbeitet:

White_Fox

Top Contributor
Aber wenn es sich vermeiden lässt, will ich auch keinen Parser schreiben, sondern nur richtig anwenden!
Ich hab unlängst mit Gson rumhantiert und fand das eigentlich ganz gut. Hier ist der Test:

Java:
public class JSONBTest {
    
    class Testclass{
        int someMember;
        int newMember;
        String s1;
        String anotherString;
    }
    
    public static void main(String[] args) {
        
//        Testclass tc = new Testclass();
//        tc.s1 = "Blah!";
//        tc.someMember = 23;
//       
//        Gson gson = new Gson();
//        System.out.println(gson.toJson(tc));
    
        // result from code above
        String deserializedString = "{\"someMember\":23,\"s1\":\"Blah!\"}";
        Type t = new TypeToken<Testclass>(){}.getType();
        Gson gson = new Gson();
        Testclass tc = gson.fromJson(deserializedString, t);
        
        System.out.println("someMember: " + tc.someMember);
        System.out.println("newMember: " + tc.newMember);
        System.out.println("s1: " + tc.s1);
        System.out.println("anotherString: " + tc.anotherString);
    }
}

Das ist ein etwas liebloser Test (und heißt JSONB weil ich ursprünglich das versuchen wollte, habs dann aber doch mit GSON gemacht). Der auskommentierte Code hat den "deserializedString" erstellt, ich habe erst den auskommentierten Teil laufen lassen und die Ausgabe rauskopiert.
Ich habe die Klasse nach dem ersten Test bewußt verändert (zwei Membervariablen habe ich hinzugefügt) weil ich mal sehen wollte wie GSON sich anstellt wenn ich Objekt speicher, die Klasse dann erweitere, und danach aus dem String wieder meine Klasse heraushole.
 

mihe7

Top Contributor
Nehmen wir mal
JSON:
{
  "search": [
    { "url": "https://startpage.com" },
    { "url": "https://duckduckgo.com" }
  ],
  "programming": [
    { "url": "https://stackoverflow.com" },
    { "url": "https://www.java-forum.org" }
  ]
}
an. Dann kann man sich das mal mit den jeweiligen Typen darstellen, wobei "a => b" bedeutet, dass a auf b abgebildet wird:
Code:
JsonObject{
  "search" => JsonArray[
    JsonObject{ "url" => "https://startpage.com" },
    JsonObject{ "url" => "https://duckduckgo.com" }
  ],
  "programming" => JsonArray[
    JsonObject{ "url" => "https://stackoverflow.com" },
    JsonObject{ "url" => "https://www.java-forum.org" }
  ]
}
Du hast ein JsonObject, das die beiden Schlüssel "search" und "programming" auf je ein JsonArray abbildet. In den Arrays befinden sich dann beliebig viele Einträge, die hier alle aus je einem JsonObject bestehen. Diese JsonObjects bilden nun jeweils einen Schlüssel "url" auf einen String ab. Das ist kein Problem, weil es sich ja um verschiedene Objekte handelt.

Und genauso arbeitest Du damit, z. B. mit JSON-P aka JSR 374. Skizze:
Java:
public List<String> getAllUrls(JsonObject bookmarks, String ... types) {
    List<String> result = new ArrayList<>();

    for (String type : types) {
        JsonArray bookmarkArray = bookmarks.getJsonArray(type);
        for (int i = 0, n = bookmarkArray.size(); i < n; i++) {
            JsonObject bookmark = bookmarkArray.getJsonObject(i);
            result.add(bookmark.getString("url"));
        }
    }

    return result;
}
Wenn Du jetzt getAllUrls(bookmarks, "search", "programming") aufrufst, wird über die beiden angegebenen Schlüssel mit der äußeren Schleife iteriert. Für jeden Schlüssel wird das zugehörige JsonArray abgerufen. Mit der inneren Schleife wird über alle JsonObjects des gerade betrachteten JsonArrays iteriert und dabei jeweils der Eintrag mit dem Schlüssel "url" abgerufen und zum Ergebnis hinzugefügt. Das entspricht genau der Struktur oben.
 

Tueftler

Mitglied
Zunächst mal ein Danke schön an MoxxiManagarm und Mihe7, ihr habt mich auf die richtige Schiene gesetzt. Zum Schluss noch eine vielleicht blöde Frage: Das ganze JSON ist ein JSONArray. Wenn ich den json-String parse und das Ergebnis statt zunächst auf JSONObject direkt auf JSONArray caste, bekomme ich eine Laufzeit-Fehlermeldung "Unexpected token END OF FILE at position 2.".
Wenn ich auf JSONObject caste, fehlt mir der Name, um mit einem get das Array aus dem Object rauszuholen und iterieren lässt sich das JSONObject wegen fehlendem Iterator auch nicht. Wie aber komme ich sonst an das Array ran?
 

mihe7

Top Contributor
Wenn ich den json-String parse und das Ergebnis statt zunächst auf JSONObject direkt auf JSONArray caste, bekomme ich eine Laufzeit-Fehlermeldung "Unexpected token END OF FILE at position 2.".
Ein Cast ist lediglich ein "Hinweis" an den Compiler, für ein Objekt einen bestimmten Typ anzunehmen. Zur Laufzeit kannst Du dadurch höchstens eine ClassCastException bekommen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
OnDemand Json Objekt leeres Array beim lesen Netzwerkprogrammierung 9
C JSON, API ... Anfänger braucht eure Hilfe Netzwerkprogrammierung 10
X Response eines RESTful-Service mit JSON Netzwerkprogrammierung 8
F Neuer Json aus teilen eines vorhandenen Json Netzwerkprogrammierung 0
F GSON wenn das Json verschiedene Klassen enthält Netzwerkprogrammierung 1
J Json von Html request einlesen Netzwerkprogrammierung 0
O Client zwischen XML und JSON auswählen lassen Netzwerkprogrammierung 2
A Server Antwort enthält JSON Objekt/Array Netzwerkprogrammierung 8
C Android: Json-POST Request zu REST Webservice Netzwerkprogrammierung 2
B Authentifikation und anschliesendes auslesen von JSON Netzwerkprogrammierung 2
L Socket Wie kann man in Java die Anzahl der Objekte in einem InputStream sehen ohne ihn durchgehen zu müssen Netzwerkprogrammierung 1
E Objekte versenden, Client-Server Netzwerkprogrammierung 25
A RMI RMI - Thread Objekte übertragen und auf anderer Machine weiterlaufen lassen Netzwerkprogrammierung 0
C List Deserialisierung entfernt Objekte Netzwerkprogrammierung 2
F HTTP Serialisierte Objekte aus Datei von Server Netzwerkprogrammierung 1
H Socket Objekte über Socket? Allgemeine Verständnisprobleme in Sachen Socket Netzwerkprogrammierung 3
V Socket Objekte werden nicht aktualisiert Netzwerkprogrammierung 2
S Socket Über UDP Objekte verschicken Netzwerkprogrammierung 9
B Eigene Objekte per RMI übergeben Netzwerkprogrammierung 2
S Kapselung der Netz-Objekte Netzwerkprogrammierung 3
B verschiedene Serialisierte Objekte identifizieren? Netzwerkprogrammierung 5
T Objekte im NIO unblocking mode versenden Netzwerkprogrammierung 11
C Socket ObjectInputStream liest nur Objekte der jeweiligen Programminstanz Netzwerkprogrammierung 5
G Frage zu Servlets und deren Objekte + Bilder in Servlets anzeigen? Netzwerkprogrammierung 11
G Objekte per TCP verschicken + Thread Netzwerkprogrammierung 4
T Laufen Objekte, die vom Cajo-Server geliefert werden, lokal auf dem Client? Netzwerkprogrammierung 4
T Inputstream -> verschiedene Objekte lesen Netzwerkprogrammierung 3
I Objekte über das Netzwerk Netzwerkprogrammierung 5
M Messenger - String oder Objekte Netzwerkprogrammierung 4
S Netzwerk und Objekte Netzwerkprogrammierung 5
S RMI 1.) Entfernte Objekte "Zwischenspeichern" 2.) Threadsicherheit Netzwerkprogrammierung 2
T rmi ssl zu große Objekte übergeben -> Exception Netzwerkprogrammierung 10
A Konflikt: Blocking und Non-Blocking bei Objekte versenden Netzwerkprogrammierung 4
N RMI und Datenbank Objekte Netzwerkprogrammierung 3
P Objekte über DatagramSocket versenden Netzwerkprogrammierung 12
R Mittels BufferedReader Objekte lesen? Netzwerkprogrammierung 5
M Objekte senden zwischen Java und PHP mit SOAP Netzwerkprogrammierung 9
A Objekte in übergebenen Objekten mit WebServices? Netzwerkprogrammierung 6
A RMI wie kann ich objekte übergeben? Netzwerkprogrammierung 5
P Serialialiserte Objekte übers Netzwerk verschicken Netzwerkprogrammierung 9
S Objekte zwischen Client und Server über Sockets senden Netzwerkprogrammierung 2
D FTP ListNames() funktinoniert nicht richtig Netzwerkprogrammierung 2
D TCP Socket funktioniert nicht richtig Netzwerkprogrammierung 3
Dit_ Antwort des Server richtig interpretieren Netzwerkprogrammierung 10
C Java Chat funktioniert nicht richtig Netzwerkprogrammierung 6
I flush() scheint nicht richtig zu arbeiten (socket -> getOutputStream -> OutputStremWriter ..) Netzwerkprogrammierung 2
B Socket Daten empfangen funktioniert nicht richtig - wo liegt der Fehler? Netzwerkprogrammierung 7
P Bilder: FTP-Upload funktioniert nicht richtig Netzwerkprogrammierung 2
N wie richtig for,muliert? Netzwerkprogrammierung 10
B Socket wird nicht richtig geschlossen Netzwerkprogrammierung 2
P Download funtioniert nicht richtig. Netzwerkprogrammierung 2
N Sock will nicht richtig beenden Netzwerkprogrammierung 7

Ähnliche Java Themen


Oben