"Previsto BEGIN_OBJECT ma era STRING alla riga 1 colonna 1"


126

Ho questo metodo:

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

E voglio analizzare un JSON con:

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();
    }
}

Ma ricevo un messaggio di errore:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: previsto BEGIN_OBJECT ma era STRING alla riga 1 colonna 1


2
Pubblica la stringa JSON restituita dalla tua richiesta di post.
Adrian Leonhard

Pubblica la tua stringa JSON
bhspencer

Risposte:


163

Anche senza vedere la tua stringa JSON puoi dire dal messaggio di errore che non è la struttura corretta da analizzare in un'istanza della tua classe.

Gson si aspetta che la tua stringa JSON inizi con una parentesi graffa di apertura dell'oggetto. per esempio

{

Ma la stringa che hai passato inizia con virgolette aperte

"

1
E il nome stesso del metodo suggerisce perché. parseStringToObjectsuggerisce che si aspetta un oggetto JSON, che inizia sempre con {.
yshavit

12
'[' indicherebbe l'inizio di un Json Array non un oggetto Json.
bhspencer

lo sapevo .. ma cosa dobbiamo fare per analizzarlo ??
Ajay Mistry

@AjayMistry Non è chiaro cosa stai chiedendo senza ulteriori dettagli. Suggerisco di pubblicare il tuo problema specifico in una nuova domanda con un esempio del JSON che stai cercando di analizzare.
bhspencer

1
Caro @bhspencer Sto usando retrofit in apk Android per ottenere un semplice JSON come {"ip":"192.167.1.15"}da Restful EJB web service with jboss EAP 7.1nel backend. Tuttavia ottengo "BEGIN_OBJECT previsto ma era STRING alla riga 1 colonna 1" Per favore aiutami ... Questo è il mio servizio web: @Stateless @Path ("/ getflashcard") public class 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

JSON non valido dal server dovrebbe sempre essere un caso d'uso previsto. Un milione di cose possono andare storte durante la trasmissione. Gson è un po 'complicato, perché il suo output di errore ti darà un problema e l'eccezione effettiva che catturi sarà di un tipo diverso.

Con tutto questo in mente, la soluzione corretta dal lato client è

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

Se vuoi sapere perché il JSON che hai ricevuto dal server è sbagliato, puoi guardare all'interno del tuo blocco catch nell'eccezione. Ma anche se è un tuo problema, non è responsabilità del cliente correggere il JSON che riceve da Internet.

In ogni caso, è responsabilità del cliente decidere cosa fare quando diventa cattivo JSON. Due possibilità sono rifiutare il JSON e non fare nulla e riprovare.

Se hai intenzione di riprovare, ti consiglio vivamente di impostare un flag all'interno del blocco try / catch e quindi di rispondere a quel flag al di fuori del blocco try / catch. Try / catch annidato è probabilmente il motivo per cui Gson ci ha portato in questo pasticcio con la nostra traccia dello stack e le eccezioni che non corrispondono.

In altre parole, anche se ammetto che non sembra molto elegante, lo consiglierei

boolean failed = false;

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

if (failed)
{
  //...

Vorrei aggiungere poiché si tratta di ottenere visualizzazioni che ho usato un valore booleano per semplicità; nel "mondo reale" probabilmente vorrai testare la presenza di una stringa in cui hai memorizzato i dati delle eccezioni che hai raccolto all'interno dei singoli blocchi try / catch, essenzialmente riproducendo a te stesso la cronologia della transazione in modo da poter prendere decisioni intelligenti su se riprovare e inviare un output utile quando alla fine decidi di fallire.
Jessica Pennell

5

In Retrofit2, quando vuoi inviare i tuoi parametri in raw devi usare Scalars.

prima aggiungi questo nel tuo gradle:

    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);

}

my 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", "sample@gmail.com");
            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) {
    }
}

Riferimento: [ Come POSTARE l'intero JSON grezzo nel corpo di una richiesta di retrofit?


3

Forse hai JSON Objectragione, ma la risposta che hai ricevuto non è un tuo dato valido. Proprio come quando colleghi l'invalido WiFi, potresti ricevere una strana risposta < html>.....< /html>che GSONnon può essere analizzata.

potresti dover fare qualcosa try..catch..per questa strana risposta per evitare il crash.


3

Sono venuto per condividere una soluzione. L'errore è accaduto a me dopo aver forzato il blocco del blocco note. possibile soluzione clean preject.


3

Assicurati di avere oggetti DESERIALIZZATI come DATE / DATETIME ecc. Se stai inviando direttamente JSON senza deserializzarlo, allora può causare questo problema.


SERIALIZZATO prima dell'invio?
ratzip

@ratzip Scusa, volevo dire che dovremmo aggiungere un deserializzatore (logica) per oggetti come DATE | APPUNTAMENTO. Stavo affrontando questo problema quando volevo mappare un JsonObject su un oggetto JAVA.
Ravi Wadje

3

Nella mia situazione, ho un "modello", composto da diversi parametri String, ad eccezione di uno: è un array di byte byte[]. Alcuni frammenti di codice:

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

L'ultima riga sopra è quando il file

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

E 'attivato. Cercando attraverso il SO, mi sono reso conto che ho bisogno di una qualche forma Adapterper convertire il mio BaseModelavanti e indietro un JsonObject. Avere mescolato Stringe byte[]in un modello complica le cose. A quanto pare, Gsonnon mi piace molto la situazione.

Finisco per fare un Adapterper assicurarmi che byte[]venga convertito in Base64formato. Ecco la mia Adapterclasse:

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));
    }
}

Per convertire JSONObject in modello, ho usato quanto segue:

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

Allo stesso modo, per convertire il modello in JSONObject, ho utilizzato quanto segue:

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

Ciò che il codice sta facendo è fondamentalmente spingere il previsto class/object(in questo caso, la byte[]classe) attraverso Adapterogni volta che viene incontrato durante la conversione da / a JSONObject.



0

Nel mio caso, restituisco l'oggetto JSON come

{"data": "", "message": "Presenze salvate con successo .. !!!", "status": "success"}

Risolto cambiandolo come

{"data": {}, "message": "Presenze salvate con successo .. !!!", "status": "success"}

Qui i dati sono un JsonObject secondario e dovrebbero iniziare da {non ""


0

se il tuo formato json e le tue variabili sono a posto, controlla le query del database ... anche se i dati vengono salvati correttamente nel db il problema reale potrebbe essere lì ... ricontrolla le tue query e riprova .. Spero che aiuti


0

Non dimenticare di convertire prima il tuo oggetto in Json usando Gson ()

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

Quindi puoi riconvertirlo facilmente in un oggetto usando questa fantastica libreria

      val fromUser = Gson().fromJson(fromUserJson, User::class.java)

0

Ho avuto un caso in cui ho letto da un file JSON scritto a mano. Il json è perfetto. Tuttavia, si è verificato questo errore. Quindi scrivo da un oggetto java in un file json, quindi leggo da quel file json. le cose vanno bene. Non ho potuto vedere alcuna differenza tra il json scritto a mano e quello dall'oggetto java. Provato oltre Il confronto non vede alcuna differenza. Alla fine ho notato che le due dimensioni dei file sono leggermente diverse e ho usato lo strumento winHex e ho rilevato cose extra. Quindi la soluzione per la mia situazione è fare una copia del buon file json, incollare il contenuto e usarlo.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.