2012-06-28 10 views
5

ich habe eine JSON-Datei mit vielen Elementen wie diese:Lesen mehrerer Elemente aus JSON-Datei

{ 
"code" : "hfuiew89", 
"type" : "location", 
"coordinates" : [ { "lat" : 40.9861, "lon" : 29.1046, "index" : 1 }, 
      { "lat" : 40.9976, "lon" : 29.1153, "index" : 2 }, 
      { "lat" : 40.9809, "lon" : 29.2194, "index" : 3 }] 
} 
{ 
"code" : "klsdsjh", 
"type" : "location", 
"relatedTags" : [ "kolmha" ], 
"coordinates" : [ { "lat" : 40.9808, "lon" : 29.1605, "index" : 1 }, 
       { "lat" : 40.9965, "lon" : 29.1672, "index" : 2 }] 
} 

Ich möchte, dass die Datei mit Gson lesen, aber alle Beispiele, die ich nur für ein Element gefunden. daher nach dem Lesen der ersten, wirft 'Expected EOF' Ausnahme. Wie kann ich das überwinden?

+2

JSON ist * gemeint * eine Einheit zu sein (sein, dass ein Objekt oder ein Array) - und was Sie haben mehrere Objekte ist. Was Sie wirklich in dieser Situation wollen, ist ein Array auf der obersten Ebene, mit jedem Objekt als Element darin. Kannst du die * Generation * dieses JSON beeinflussen, oder bleibst du bei diesem Format stecken? –

Antwort

3

Greg hat recht, das ist inkorrektes JSON, und Sie sollten versuchen, ein gültiges JSON zu generieren, das "[" am Anfang voranstellt, "]" anfügt und jedes Element durch ein Komma trennt (", "), so dass es ein JSON-Array von JSON-Objekten ist.

Wenn Sie jedoch das Format, das Sie haben, nicht ändern können, betrachten Sie es als "eine Zeichenfolge, die eine Verkettung wohlgeformter JSON-Fragmente enthält". Nähern Sie sich auf diese Weise, brechen Sie die große Zeichenfolge in kleinere, gültige JSON-Zeichenfolgen und parsen Sie sie einzeln.

Um die große Zeichenfolge in einzelne Fragmente zu zerlegen, können Sie einfach die Klammern zählen. Mit einem "Pre-Parser", der Daten in einen Puffer (einen StringBuilder?) Kopiert, erhöht er jedes Mal einen Zähler, wenn er auf ein "{" trifft, und verringert den Wert jedes Mal, wenn ein "}" auftritt Die Pufferzeichenfolge an Gson zum Analysieren, löschen Sie den Puffer und gehen Sie an das Ende der Datei.

Sie können sogar diesen Vorparser verwenden, um ihn in gültiges json umzuwandeln, indem Sie einfach ein "," anfügen, wenn der Zähler Null erreicht, und alles an gson übergeben für ein einzelnes Parsing, aber das könnte bedeuten, alles in ram zu laden und ich weiß nicht, wie groß deine Datei ist.

+0

Damit können Sie einfach Ihre Datei als ein Array von JSON-Objekten erstellen. Allerdings können Speicherprobleme auftreten, wenn zu viele Entitäten im Array vorhanden sind.Andernfalls ist eine getrennte Zeichenfolge von JSON-Entitäten besser und Sie können nur einen Teil der Datei gleichzeitig laden. – Drizzt321

+0

Ja, das war es, was ich auszudrücken versuchte: Ein einzelnes großes json-Array und ein einzelner Aufruf zum Parsen könnte einfacher erscheinen, könnte aber auch bedeuten, alles in ram zu laden; während man "Schritt für Schritt" geht, könnte man Entitäten nacheinander behandeln ... das ist wieder SAX gegen DOM, aber jetzt, wo es JSON heißt, klingt es viel mehr k00l. –

+0

Haha, so wahr. Obwohl JSON weniger ausführlich erscheint (zum Beispiel keine schließenden Tags), ist es auch ein sehr einfaches Mittel, um Daten an Javascript zu übergeben, was heutzutage der letzte Schrei ist und daher wahrscheinlich einer der Gründe für den großen Aufstieg von JSON ist. – Drizzt321

9

Für was es wert ist ...

Die folgende Aussage ist falsch. Gson hat kein eingebautes Feature, um einfach die Deserialisierung einer solchen JSON-Sequenz zu handhaben. (Siehe Kommentare.)

Wenn der Wechsel von JSON-zu/von Java-APIs eine Option ist, verfügt Jackson über eine solche Funktion, wie unten gezeigt.

input.json

{ 
"name":"A" 
} 
{ 
"name":"B" 
} 

JacksonFoo.java

import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; 
import static com.fasterxml.jackson.annotation.PropertyAccessor.FIELD; 

import java.io.File; 
import java.util.Iterator; 

import com.fasterxml.jackson.databind.ObjectMapper; 

public class JacksonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    ObjectMapper mapper = new ObjectMapper().setVisibility(FIELD, ANY); 
    Iterator<Thing> thingsIterator = mapper.reader(Thing.class).readValues(new File("input.json")); 
    while (thingsIterator.hasNext()) 
    { 
     System.out.println(thingsIterator.next()); 
    } 
    } 
} 

class Thing 
{ 
    private String name; 

    @Override 
    public String toString() 
    { 
    return String.format("Thing: name=%s", name); 
    } 
} 

Ausgang:

Thing: name=A 
Thing: name=B 

Update: Eine ähnliche Lösung mit Gson.

GsonFoo.java

import java.io.FileReader; 

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.JsonStreamParser; 

public class GsonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    Gson gson = new GsonBuilder().create(); 

    JsonStreamParser parser = new JsonStreamParser(new FileReader("input.json")); 
    while(parser.hasNext()) 
    { 
     System.out.println(gson.fromJson(parser.next(), Thing.class)); 
    } 
    } 
} 
+2

Dieser Beitrag ist falsch. Gson hat dieses (falsche) Feature. Es heißt JsonStreamParser und die Dokumentation ist hier: http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/JsonStreamParser.html –

+0

Ah, ordentlich. Ich wurde durch die Verwendung des Wortes "Stream" in der GSON API geworfen. Ich nahm einfach an, dass "Stream" sich auf das synchrone Analysieren von JSON-Streaming-Token bezieht, im Gegensatz zum Binden von JSON-Daten an Objekte/Arrays. –

+0

Aktualisierte Antwort entsprechend. –

Verwandte Themen