"Se esperaba BEGIN_OBJECT, pero estaba STRING en la línea 1, columna 1"


126

Tengo este método:

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

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

Pero recibo un mensaje de error:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: se esperaba BEGIN_OBJECT pero era STRING en la línea 1, columna 1


2
Publique la cadena JSON devuelta por su solicitud de publicación.
Adrian Leonhard

Publique su cadena JSON
bhspencer

Respuestas:


163

Incluso sin ver su cadena JSON, puede saber por el mensaje de error que no es la estructura correcta para analizarla en una instancia de su clase.

Gson espera que su cadena JSON comience con una llave de apertura de objeto. p.ej

{

Pero la cadena que le ha pasado comienza con comillas abiertas

"

1
Y el mismo nombre del método sugiere por qué. parseStringToObjectsugiere que espera un objeto JSON, que siempre comienza con {.
yshavit

12
'[' indicaría el inicio de una matriz Json, no un objeto Json.
bhspencer

lo sabía ... pero ¿qué tenemos que hacer para analizar eso?
Ajay Mistry

@AjayMistry No está claro lo que estás preguntando sin más detalles. Sugiero publicar su problema específico en una nueva pregunta con un ejemplo del JSON que está intentando analizar.
bhspencer

1
Estimado @bhspencer, estoy usando la actualización en la apk de Android para obtener un json simple como {"ip":"192.167.1.15"}desde Restful EJB web service with jboss EAP 7.1el backend. Sin embargo, obtengo el mensaje "Se esperaba BEGIN_OBJECT pero era STRING en la línea 1, columna 1". Ayúdenme ... Este es mi servicio 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 no válido del servidor siempre debe ser un caso de uso esperado. Un millón de cosas pueden salir mal durante la transmisión. Gson es un poco complicado, porque su salida de error le dará un problema, y ​​la excepción real que detecte será de un tipo diferente.

Con todo eso en mente, la solución adecuada por parte del cliente es

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

Si desea saber por qué el JSON que recibió del servidor es incorrecto, puede mirar dentro de su bloque de captura en la excepción. Pero incluso si es su problema, no es responsabilidad del cliente reparar el JSON que recibe de Internet.

De cualquier manera, es responsabilidad del cliente decidir qué hacer cuando el JSON se vuelve incorrecto. Dos posibilidades son rechazar el JSON y no hacer nada y volver a intentarlo.

Si va a intentarlo de nuevo, le recomiendo que coloque una bandera dentro del bloque try / catch y luego responda a esa bandera fuera del bloque try / catch. El try / catch anidado es probablemente la forma en que Gson nos metió en este lío con el seguimiento de la pila y las excepciones que no coinciden.

En otras palabras, aunque admito que no se ve muy elegante, recomendaría

boolean failed = false;

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

if (failed)
{
  //...

Quiero agregar, dado que esto es obtener vistas, usé un booleano para simplificar; en el "mundo real", es probable que desee probar la presencia de una cadena en la que almacenó los datos de excepción que recopiló dentro de bloques de prueba / captura individuales, esencialmente reproduciendo el historial de la transacción para usted mismo para que pueda tomar decisiones inteligentes en cuanto a si volver a intentarlo y enviar resultados útiles cuando finalmente decida fallar.
Jessica Pennell

5

En Retrofit2, cuando desee enviar sus parámetros en bruto, debe utilizar Scalars.

primero agregue esto en su 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);

}

mi 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) {
    }
}

Referencia: [ ¿Cómo PUBLICAR JSON completo sin procesar en el cuerpo de una solicitud de modificación?


3

Tal vez JSON Objecttenga razón, pero la respuesta que recibió no es su información válida. Al igual que cuando conecta el inválido WiFi, puede recibir una respuesta extraña < html>.....< /html>que GSONno puede analizar.

es posible que deba hacer algo try..catch..para esta extraña respuesta para evitar un bloqueo.


3

Vengo a compartir una solución. El error me sucedió después de forzar el cierre del notbook. posible solución clean preject.


3

Asegúrese de tener objetos DESERIALIZADOS como DATE / DATETIME, etc. Si está enviando JSON directamente sin deserializarlo, puede causar este problema.


SERIALIZADO antes de enviar?
ratzip

@ratzip Lo siento, quise decir que deberíamos agregar un deserializador (lógica) para los objetos como FECHA | FECHA Y HORA. Me enfrentaba a este problema cuando quería asignar un JsonObject a un objeto JAVA.
Ravi Wadje

3

En mi situación, tengo un "modelo", que consta de varios parámetros de cadena, con la excepción de uno: es una matriz de bytes byte[]. Algún fragmento de código:

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

La última línea de arriba es cuando el

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

se activa. Buscando a través del SO, me di cuenta de que necesito tener alguna forma de Adapterconvertir mi BaseModelde un lado a otro en un JsonObject. Haber mezclado Stringy byte[]en un modelo complica la cosa. Aparentemente, Gsonno me gusta mucho la situación.

Termino haciendo un Adapterpara asegurar que byte[]se convierta a Base64formato. Aquí está mi Adapterclase:

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

Para convertir JSONObject en modelo, utilicé lo siguiente:

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

De manera similar, para convertir el modelo a JSONObject, utilicé lo siguiente:

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

Lo que está haciendo el código es básicamente empujar lo deseado class/object(en este caso, la byte[]clase) a través del Adaptersiempre que se encuentre durante la conversión a / fro JSONObject.



0

En mi caso, estoy devolviendo el objeto JSON como

{"data": "", "message": "Asistencia guardada correctamente ... !!!", "status": "success"}

Resuelto cambiándolo como

{"data": {}, "message": "¡¡¡La asistencia se guardó correctamente ... !!!", "status": "success"}

Aquí los datos son un objeto JsonObject secundario y deberían comenzar desde {no ""


0

si su formato y variables json están bien, verifique las consultas de su base de datos ... incluso si los datos se guardan en la base de datos correctamente, el problema real podría estar allí ... vuelva a verificar sus consultas e intente nuevamente .. Espero que ayude


0

No olvide convertir su objeto en Json primero usando Gson ()

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

Luego, puede convertirlo fácilmente en un objeto usando esta increíble biblioteca

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

0

Tuve un caso en el que leí de un archivo json escrito a mano. El json es perfecto. Sin embargo, ocurrió este error. Entonces escribo desde un objeto java a un archivo json, luego leo desde ese archivo json. las cosas estan bien. No pude ver ninguna diferencia entre el json escrito a mano y el del objeto java. Probado beyondCompare no ve ninguna diferencia. Finalmente noté que los dos tamaños de archivo son ligeramente diferentes, utilicé la herramienta winHex y detecté cosas adicionales. Entonces, la solución para mi situación es hacer una copia del buen archivo json, pegar el contenido en él y usar.

ingrese la descripción de la imagen aquí

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.