Read JSON File Problem

doktordoom

Mitglied
Hallo,
ich versuche aktuell mittels GSON *.json Files zu schreiben und zu lesen. Das Schreiben hat schon funktioniert.
Das test.json File findet Ihr unten. Das Lesen macht mir aktuell ein paar Probleme. Bei dem Parsen/Lesen in ein JSON Element oder Object lande ich immer in einer Exception. Das test.json file habe ich erfolgreich validieren lassen durch eine Website. Am Ende würde ich am Anfang erst einmal Node.Name parsen und in ein Liste speichern können.

Code:
public static List<String> getNodes( java.io.File f) throws FileNotFoundException
    {
        List<String> SearchList = new ArrayList<>();

                
        try {
           // Gson gson = new Gson();
            // Creates a FileWriter
            FileReader file = new FileReader(f.getPath());

            // Creates a BufferedWriter
            BufferedReader input = new BufferedReader(file);
            
            
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = input.readLine()) != null) {
              sb.append(line);
            }
            String json = sb.toString();
            System.out.println(json);
            
            JsonElement jsonElement = (JsonElement) new JSONParser().parse(json);
            JsonObject jsonObject = jsonElement.getAsJsonObject();
            
            //    JsonObject JsonObejct = new Gson().fromJson(json, JsonObject.class);
            jsonObject = jsonObject.getAsJsonObject("Node.Name");
            
          //  ArrayList arrName = new Gson().fromJson(JsonArray, ArrayList.class);

            
            //ArrayList  jsonObjList = gson.fromJson(input, ArrayList.class);

            // print user object
            System.out.println(jsonObject);
            
            
            // Closes the writer
            input.close();
          }

          catch (Exception e) {
            e.getStackTrace();
          }
        return SearchList;
    }





Java:
[{"Node0":"Properties[ Node.Name = Papier, Node.Visible = false ]","Node1":"Properties[ Node.Name = Qualität, Node.Visible = false ]","Node2":"Properties[ Node.Name = Layout, Node.Visible = false ]"}]
 
Das Problem dürfte wohl sein, dass Du ein Array hast und du das als ein Objekt ansprechen willst. Aber Du musst da halt erst das Array durchgehen.

Also erst ein getAsJsonArray machen um dann zu dem ersten Node zu gehen.

Und generell ist die Frage: Gson bietet halt super das lesen / schreiben in /von den Entity Klassen. Statt da also die Struktur selbst durchzugehen, sollte man sich eine entsprechende Entity Klasse bauen und dann kannst Du das direkt einlesen. Wobei das JSON schon seltsam aussieht - Du hast gesagt, dass Du es selbst erzeugt hast, daher: Wieso hast Du es so erzeugt und nicht einfach etwas wie

JSON:
[
    {
        "Name": "Papier",
        "Visible": "false"
    },
    {
        "Name": "Qualität",
        "Visible": "false"
    },
    ...
]
 
Hi,
ich habe eben nochmal nachgesehen. Oft sieht man den Wald vor lauter Bäumen nicht. Danke für die tipps. Über die Struktur habe ich gestern Abend auch nach gedacht.
 
Es ist schön, eine Rückmeldung zu bekommen, aber ich habe jetzt keine Ahnung wo Du nun stehst und was Du aus den Aussagen gemacht hast.

Daher einfach einmal ganz kurz auf die Schnelle etwas gebaut:
Java:
public class Node {
    @SerializedName("Name")
    private String name;
    @SerializedName("Visible")
    private boolean visible;
    
    // Konstruktoren, Getter / Setter und für den Test: equals / hashcode
    // Kann ja von der IDE erzeugt werden!
}

Da sieht dann eine Serialisierung / Deserialisierung so aus:
Java:
public class NodeTest {
    @Test
    public void testSerialization() {
        Node[] nodes = new Node[] {
                new Node("Papier", false),
                new Node("Qualität", false)
        };

        Gson gson = new Gson();

        String json = gson.toJson(nodes);
        System.out.println(json);

        // Zurück in ein Array
        Node[] nodes2 = gson.fromJson(json, Node[].class);

        // Oder in eine Liste
        List<Node> nodesList = gson.fromJson(json, new TypeToken<List<Node>>(){}.getType());

        // Liste kann man natürlich auch serialisieren
        String json2 = gson.toJson(nodesList);
        System.out.println(json2);

        assertTrue(Arrays.equals(nodes, nodes2));
        assertEquals(json, json2);
    }
}

Das ist also wirklich extrem einfach!

Diese @SerializedName(...) sind nur notwendig, wenn Du halt eine ganz exakte Schreibweise willst und diese nicht mit den Namen überein stimmt. Also ohne das, wäre das ein "name" und mit der Annotation eben "Name".

Ansonsten ist es immer die Erstellung einer Gson Instanz. (Wenn man spezielle Serialisierungen hätte, dann könnte man die da auch noch setzen.)

Und dann sind das einfache toJson und fromJson Aufrufe. Dabei ist es egal, ob Array oder List - das geht beides. Bei List muss man dann nur mit einem TypeToken arbeiten.

Man kann da auch noch deutlich mehr mit machen ... ich habe z.B. in JAdventure einmal aufgezeigt, wie man da auch abgeleitete Klassen serialisieren kann. Für so einfache Dinge brauchst Du das aber absolut nicht - aber da sieht man dann z.B. paar Annotations und wie man so Adapter schreiben kann: https://jadventure.de/Anhang/E1-gson/ (Oder in der Lektion 2 mal lesen ... Videos sind noch hoffen - hoffe ich am Sonntag endlich dazu zu kommen, so dass Lektion 2 auch endlich abgeschlossen ist 🙂 )
 
Hi @KonradN,
mein Problem war das ich GSON und simple json in die Maven gepackt habe. Dadurch bin ich bei der Syntax durcheinander gekommen.
Also "JSONArray" & "JsonArray" haben zu einer exception geführt. Aktuell habe die Syntaxt der Json Datei in einem String. Das ist aber nicht mein Ziel. Ich würde gerne durch ein Schlüsselwort oder KeyValue, auf mein Ziel Value wie z.B. Papier zugreifen. Also wie bei einem Dictonary in Pyton oder einfach einer Delegation. Was eigentlich auch der Parser machen sollte. Aber aktuell funktioniert das noch nicht.
 
Key/Value wäre ja Map und die lässt sich ebenso serialisieren.
Beispiel von SO:

Also wichtig: man braucht kein Adapter oder so!
 
Hi @KonradN,
ich habe dein Vorschlag ausprobiert bekomme aber mit vielen ausprobieren immer die selbe Exception.

"com.google.gson.JsonParseException: The JsonDeserializer MapTypeAdapter failed to deserialize json object [{"{Name0":"Papier,Visible :false}","{Name1":"Qualität,Visible :false}","{Name2":"Layout,Visible :false}"}] given the type java.util.Map<java.lang.String, java.lang.String>"




Java:
public static List<String> getNodes(java.io.File f) throws FileNotFoundException
    {
        List<String> SearchList = new ArrayList<>();
        Gson gson = new Gson();
                
        try {

            // Creates a FileWriter
            FileReader file = new FileReader(f.getPath());

            // Creates a BufferedWriter
            BufferedReader input = new BufferedReader(file);
            
            
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = input.readLine()) != null) {
              sb.append(line);
            }
            String json = sb.toString();

            java.lang.reflect.Type type2 = new TypeToken<Map<String, String>>(){}.getType();
            Map<String, String> myMap = gson.fromJson(json, type2);
            
                    
            System.out.println(myMap.get("Name0"));
      
            
            // Closes the writer
            input.close();
          }

          catch (Exception e) {
            e.getStackTrace();
            System.out.println(e);
          }
        return SearchList;
    }
 
Das JSON muss natürlich passen. Wenn du eine Map deserialisieren willst, das muss es auch so geschrieben worden sein.

Wenn das Format nicht geändert werden kann, dann musst du da ggf einen eigenen Adapter bauen oder du gehst hin und baust deine Entities so, dass sie dem JSON entsprechen. (Sowas am Besten immer testen, in dem du serialisierst und schaust, was raus kommt)

Aber das JSON, dass du gepostet hast sieht ganz dubios aus!
 
Hi @KonradN,
Danke für dein Support. Der parser funktioniert jetzt wie gewollt. Unten ein Auszug was geschrieben wurde.

Java:
[
  {
    "Node.Name": "Papier",
    "Is.Visible": false
  },
  {
    "Node.Name": "Qualität",
    "Is.Visible": false
  },
  {
    "Node.Name": "Layout",
    "Is.Visible": false
  }
]
 

Neue Themen


Zurück
Oben