gson löst eine MalformedJsonException aus

72

Ich verwende gson , um einen json- String in ein Java-Objekt zu konvertieren . Der Wert von result2 ist genau der gleiche wie der Wert von result1 . (Vom Debugger kopiert; Backslashs hinzugefügt)

Die folgende Ausnahme wird beim Konvertieren von Ergebnis1 ausgelöst: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Erwartete EOF in Zeile 1, Spalte 170

Das Konvertieren von result2 funktioniert einwandfrei .

Die json-Zeichenfolge ist gemäß jsonlint.com gültig.

public static Userinfo getUserinfo()
{
    String result1 = http.POST("https://www.bitstamp.net/api/balance/",
                                postdata, true);
    String result2 = "{\"btc_reserved\": \"0\", \"fee\": \"0.5000\", \"btc_available\": \"0.10000000\", \"usd_reserved\": \"0\", \"btc_balance\": \"0.10000000\", \"usd_balance\": \"30.00\", \"usd_available\": \"30.00\"}";
    Gson gson = new Gson();
    Userinfo userinfo1 = gson.fromJson(result1, Userinfo.class); //throws Exception
    Userinfo userinfo2 = gson.fromJson(result2, Userinfo.class); //works fine

    return userinfo1;
}
private class Userinfo {

    public Userinfo(){
    }

    public float usd_balance;
    public float btc_balance ;
    public float usd_reserved;
    public float btc_reserved;
    public float usd_available;
    public float btc_available;
    public float fee;
    public float last_update;
}
Nicht
quelle

Antworten:

105

Ich vermute, dass result1 am Ende einige Zeichen enthält, die Sie im Debugger nicht sehen können, die auf das schließende }Zeichen folgen . Wie lang ist result1versus result2? Ich werde bemerken, dass es, result2wie Sie zitiert haben, 169 Zeichen hat.

Gson führt , dass bestimmte Fehler , wenn gibt es zusätzliche Zeichen nach dem Ende des Objekts , das keine Leerzeichen sind, und definiert Leerzeichen sehr eng (wie die JSON - Spezifikation der Fall ist) - nur \t, \n, \r, und Raum zählen als Leerzeichen. Beachten Sie insbesondere, dass nachfolgende NUL ( \0) - Zeichen nicht als Leerzeichen gelten und diesen Fehler verursachen .

Wenn Sie nicht leicht herausfinden können, was die zusätzlichen Zeichen am Ende verursacht, und sie entfernen können, können Sie GSON auch anweisen, im milden Modus zu analysieren:

Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(result1));
reader.setLenient(true);
Userinfo userinfo1 = gson.fromJson(reader, Userinfo.class);
Daniel Martin
quelle
1
Vielen Dank! Meine HTTP-Klasse hat die JSON-Zeichenfolge in einen 256-Byte-Zeichenpuffer heruntergeladen, der dann in eine Zeichenfolge konvertiert wurde (Ergebnis1). Aus diesem Grund hatte result1 eine Länge von 255 statt 169.
Nicht
Ich hatte das gleiche Problem; Die ganze EOF-Sache in der Ausnahme warf mich, mein Problem war schlicht und einfach schlecht geformter JSON.
Kong
3
Ich hatte das gleiche Problem, aber ich habe meinen JSON über einen FileChannel erhalten. Ich war mir ziemlich sicher, dass die Codierung in Ordnung war. Was ich getan habe, war, die trim () -Methode für den String red from file auf der Festplatte aufzurufen. Dies löste das Problem.
3
@ThePaul - Sie hatten wahrscheinlich zusätzliche NUL-Zeichen (dh '\ 0') am Ende Ihrer Zeichenfolge. String.trim () entfernt nicht nur Leerzeichen, sondern auch alle Zeichen unter 32, während GSON diese Zeichen als nachgestellten Müll zählt. (Und es beschwert sich dann "Ich habe die schließende Klammer gesehen, sollte also als nächstes einen EOF sehen, aber ich habe stattdessen einige andere Sachen gesehen")
Daniel Martin
Stellen Sie sicher, dass Sie den richtigen JSON-Reader importieren. Andere Bibliotheken haben gleichnamige Klassen
Joe Maher,
20

Nach meiner jüngsten Erfahrung JsonReader#setLenientist der Parser im Grunde genommen sehr tolerant, selbst um fehlerhafte JSON-Daten zuzulassen.

Bei bestimmten Daten, die von Ihren vertrauenswürdigen RESTful-APIs abgerufen wurden, kann dieser Fehler jedoch durch nachgestellte Leerzeichen verursacht werden. In solchen Fällen würden einfach trimdie Daten den Fehler vermeiden:

String trimmed = result1.trim();

Dann gson.fromJson(trimmed, T)könnte es funktionieren. Sicherlich deckt dies nur einen Sonderfall ab, also YMMV.

Ryenus
quelle
2
Hallo @ryenus, wenn ich zwei Wörter mit Leerzeichen dazwischen habe, was dann tun?
Qasim
5
Was ist, wenn Leerzeichen in der Zeichenfolgenantwort eine Rolle spielen? Tirmming ist in diesem Fall nicht gut. Sie verlieren die Integrität Ihrer Daten.
Anis
4

Im Debugger müssen Sie keine Schrägstriche hinzufügen, das Eingabefeld versteht die Sonderzeichen.

Im Java-Code müssen Sie den Sonderzeichen entkommen

Mark Bakker
quelle
Ich habe den Wert von result1 aus dem Debugger kopiert und anschließend Backslashes hinzugefügt, um den Sonderzeichen in result2 zu entgehen;)
Non
Könnte es sein, dass ein Leerzeichen oder \ n \ r vor oder an die JSON-Zeichenfolge angehängt ist. Es sollte etwas Einfaches sein
Mark Bakker
Was ist das Ergebnis von result1.equals (result2)?
Programmierer Bruce
@ProgrammerBruce: result1.equals (result2) = false. Beide Zeichenfolgen enthielten dieselben Zeichen, aber result1 war länger als result2 (verursacht durch meine http-Klasse; siehe oben).
Nicht