"Erwartet BEGIN_OBJECT, war aber STRING in Zeile 1 Spalte 1"

126

Ich habe diese Methode:

public static Object parseStringToObject(String json) {
    String Object = json;
    Gson gson = new Gson();
    Object objects = gson.fromJson(object, Object.class);
    parseConfigFromObjectToString(object);
    return objects;
}

Und ich möchte einen JSON analysieren mit:

public static void addObject(String IP, Object addObject) {
    try {
        String json = sendPostRequest("http://" + IP + ":3000/config/add_Object", ConfigJSONParser.parseConfigFromObjectToString(addObject));
        addObject = ConfigJSONParser.parseStringToObject(json);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

Aber ich bekomme eine Fehlermeldung:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Erwartet BEGIN_OBJECT, aber STRING in Zeile 1, Spalte 1

Crapo Wolf
quelle
2
Veröffentlichen Sie die von Ihrer Post-Anfrage zurückgegebene JSON-Zeichenfolge.
Adrian Leonhard
Veröffentlichen Sie

Antworten:

163

Auch ohne Ihre JSON-Zeichenfolge zu sehen, können Sie anhand der Fehlermeldung erkennen, dass es nicht die richtige Struktur ist, um in eine Instanz Ihrer Klasse analysiert zu werden.

Gson erwartet, dass Ihre JSON-Zeichenfolge mit einer Klammer zum Öffnen von Objekten beginnt. z.B

{

Die Zeichenfolge, die Sie übergeben haben, beginnt jedoch mit offenen Anführungszeichen

"
bhspencer
quelle
1
Und der Name der Methode legt nahe, warum. parseStringToObjectschlägt vor, ein JSON-Objekt zu erwarten, das immer mit beginnt {.
Yshavit
12
'[' würde den Start eines Json-Arrays anzeigen, nicht eines Json-Objekts.
Bhspencer
Ich wusste das .. aber was müssen wir tun, um das zu analysieren?
Ajay Mistry
@ AjayMistry Es ist nicht klar, was Sie ohne weitere Details fragen. Ich schlage vor, Ihr spezifisches Problem in einer neuen Frage mit einem Beispiel für den JSON zu veröffentlichen, den Sie analysieren möchten.
Bhspencer
1
Lieber @bhspencer ich Retrofit in android apk bin mit einem einfachen json wie erhalten {"ip":"192.167.1.15"}von Restful EJB web service with jboss EAP 7.1im Backend. Ich erhalte jedoch "Erwartetes BEGIN_OBJECT, war aber STRING in Zeile 1, Spalte 1". Bitte helfen Sie mir ... Dies ist mein Webdienst: @Stateless @Path ("/ getflashcard") öffentliche Klasse GetFlashcard {@Interceptors (Validator.class) @GET @Produces (MediaType.APPLICATION_JSON) public String getFlashcard () {String jsonString = new JSONObject (). Put ("ip", "192.167.1.15"). ToString (); return jsonString; }}
Hosein Aqajani
17

Ungültiger JSON vom Server sollte immer ein erwarteter Anwendungsfall sein. Eine Million Dinge können während der Übertragung schief gehen. Gson ist etwas knifflig, da die Fehlerausgabe Ihnen ein Problem bereitet und die tatsächliche Ausnahme, die Sie abfangen, von einem anderen Typ ist.

In Anbetracht dessen ist die richtige Lösung auf der Client-Seite

try
{
  gson.fromJSON(ad, Ad.class);
  //...
}
catch (IllegalStateException | JsonSyntaxException exception)
{
  //...

Wenn Sie wissen möchten, warum der vom Server empfangene JSON falsch ist, können Sie sich die Ausnahme in Ihrem catch-Block ansehen. Aber selbst wenn es Ihr Problem ist, liegt es nicht in der Verantwortung des Kunden, JSON zu reparieren, das er aus dem Internet empfängt.

In jedem Fall liegt es in der Verantwortung des Kunden, zu entscheiden, was zu tun ist, wenn JSON fehlerhaft wird. Zwei Möglichkeiten sind, den JSON abzulehnen, nichts zu tun und es erneut zu versuchen.

Wenn Sie es erneut versuchen möchten, empfehle ich dringend, ein Flag innerhalb des Try / Catch-Blocks zu setzen und dann auf dieses Flag außerhalb des Try / Catch-Blocks zu reagieren. Verschachtelter Versuch / Fang ist wahrscheinlich, wie Gson uns in dieses Chaos mit unserer Stapelverfolgung und Ausnahmen gebracht hat, die nicht übereinstimmen.

Mit anderen Worten, obwohl ich zugeben werde, dass es nicht sehr elegant aussieht, würde ich empfehlen

boolean failed = false;

try
{
  gson.fromJSON(ad, Ad.class);
  //...
}
catch (IllegalStateException | JsonSyntaxException exception)
{
  failed = true;
  //...
}

if (failed)
{
  //...
Jessica Pennell
quelle
Ich möchte hinzufügen, da dies Ansichten erhält, dass ich der Einfachheit halber einen Booleschen Wert verwendet habe. In der "realen Welt" möchten Sie wahrscheinlich auf das Vorhandensein einer Zeichenfolge testen, in der Sie Ausnahmedaten gespeichert haben, die Sie in einzelnen Try / Catch-Blöcken gesammelt haben, und im Wesentlichen den Verlauf der Transaktion für sich selbst wiedergeben, damit Sie intelligente Entscheidungen treffen können ob Sie es erneut versuchen und nützliche Ausgaben senden möchten, wenn Sie sich schließlich für einen Fehlschlag entscheiden.
Jessica Pennell
5

Wenn Sie in Retrofit2 Ihre Parameter in RAW senden möchten, müssen Sie Skalare verwenden.

füge dies zuerst in dein gradle ein:

    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.3.0'

    public interface ApiInterface {

    String URL_BASE = "http://10.157.102.22/rest/";

    @Headers("Content-Type: application/json")
    @POST("login")
    Call<User> getUser(@Body String body);

}

meine SampleActivity:

   public class SampleActivity extends AppCompatActivity implements Callback<User> {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiInterface.URL_BASE)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiInterface apiInterface = retrofit.create(ApiInterface.class);


        // prepare call in Retrofit 2.0
        try {
            JSONObject paramObject = new JSONObject();
            paramObject.put("email", "[email protected]");
            paramObject.put("pass", "4384984938943");

            Call<User> userCall = apiInterface.getUser(paramObject.toString());
            userCall.enqueue(this);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onResponse(Call<User> call, Response<User> response) {
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
    }
}

Referenz: [ Wie kann ich den gesamten JSON im Hauptteil einer Nachrüstanforderung POSTEN?

Raj008
quelle
3

Vielleicht haben Sie JSON ObjectRecht, aber die Antwort, die Sie erhalten haben, sind nicht Ihre gültigen Daten. Genau wie beim Verbinden des Ungültigen erhalten WiFiSie möglicherweise eine seltsame Antwort < html>.....< /html>, GSONdie nicht analysiert werden kann.

Möglicherweise müssen Sie einige try..catch..Maßnahmen für diese seltsame Reaktion ergreifen, um einen Absturz zu vermeiden.

BrantYu
quelle
3

Ich bin gekommen, um eine Lösung zu teilen. Der Fehler ist mir passiert, nachdem ich das Notbook zum Auflegen gezwungen habe. mögliche Lösung clean preject.

Wallace Roberto
quelle
3

Stellen Sie sicher, dass Sie DESERIALISIERTE Objekte wie DATE / DATETIME usw. haben. Wenn Sie JSON direkt senden, ohne es zu deserialisieren, kann dies zu diesem Problem führen.

Ravi Wadje
quelle
Vor dem Senden SERIALISIERT?
Ratzip
@ratzip Sorry, ich meinte, wir sollten einen Deserializer (Logik) für die Objekte wie DATE | hinzufügen TERMINZEIT. Ich hatte dieses Problem, als ich ein JsonObject einem JAVA-Objekt zuordnen wollte.
Ravi Wadje
3

In meiner Situation habe ich ein "Modell", das aus mehreren String-Parametern besteht, mit einer Ausnahme: Es ist ein Byte-Array byte[]. Einige Codefragmente:

String response = args[0].toString();
Gson gson = new Gson();
BaseModel responseModel = gson.fromJson(response, BaseModel.class);

Die letzte Zeile oben ist, wenn die

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column

wird ausgelöst. Beim Durchsuchen des SO wurde mir klar, dass ich eine Form haben muss Adapter, um mein BaseModelJsonObject hin und her zu konvertieren. Das Mischen von Stringund byte[]in einem Modell macht die Sache komplizierter. Anscheinend Gsonmag die Situation nicht wirklich.

Am Ende mache ich ein, Adapterum sicherzustellen, dass byte[]es in das Base64Format konvertiert wird . Hier ist meine AdapterKlasse:

public class ByteArrayToBase64Adapter implements JsonSerializer<byte[]>, JsonDeserializer<byte[]> {

    @Override
    public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        return Base64.decode(json.getAsString(), Base64.NO_WRAP);
    }

    @Override
    public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(Base64.encodeToString(src, Base64.NO_WRAP));
    }
}

Um JSONObject in ein Modell zu konvertieren, habe ich Folgendes verwendet:

Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64Adapter()).create();
BaseModel responseModel = customGson.fromJson(response, BaseModel.class);

Um das Modell in JSONObject zu konvertieren, habe ich Folgendes verwendet:

Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64Adapter()).create();
String responseJSon = customGson.toJson(response);

Was der Code tut, ist im Grunde, die beabsichtigte class/object(in diesem Fall byte[]Klasse) durch die zu schieben , Adapterwann immer sie während der Konvertierung zu / von JSONObject angetroffen wird.

YazidEF
quelle
0

Nicht jsonObject.toStringfür ein JSON-Objekt verwenden.

Solomon Fissehaye
quelle
0

In meinem Fall gebe ich JSON-Objekt als zurück

{"data": "", "message": "Teilnahme erfolgreich gespeichert .. !!!", "status": "success"}

Gelöst durch Ändern als

{"data": {}, "message": "Teilnahme erfolgreich gespeichert .. !!!", "status": "success"}

Hier sind Daten ein Sub-JsonObject und sollten von {not "" ausgehen.

RAJESH KUMAR ARUMUGAM
quelle
0

Wenn Ihr JSON-Format und Ihre Variablen in Ordnung sind, überprüfen Sie Ihre Datenbankabfragen. Selbst wenn die Daten korrekt in der Datenbank gespeichert sind, liegt möglicherweise das eigentliche Problem darin. Überprüfen Sie Ihre Abfragen erneut und versuchen Sie es erneut. Ich hoffe, es hilft

Shabbir Ahmed
quelle
0

Vergessen Sie nicht, Ihr Objekt zuerst mit Gson () in Json zu konvertieren.

  val fromUserJson = Gson().toJson(notificationRequest.fromUser)

Dann können Sie es mit dieser fantastischen Bibliothek ganz einfach wieder in ein Objekt konvertieren

      val fromUser = Gson().fromJson(fromUserJson, User::class.java)
Dave o Grady
quelle