"BEGIN_OBJECT attendu, mais était STRING à la ligne 1 colonne 1"

126

J'ai cette méthode:

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

Et je veux analyser un JSON avec:

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

Mais j'obtiens un message d'erreur:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT attendu mais était STRING à la ligne 1 colonne 1

Crapo Wolf
la source
2
Publiez la chaîne JSON renvoyée par votre demande de publication.
Adrian Leonhard
Publiez votre chaîne JSON
bhspencer

Réponses:

163

Même sans voir votre chaîne JSON, vous pouvez dire à partir du message d'erreur que ce n'est pas la structure correcte à analyser dans une instance de votre classe.

Gson s'attend à ce que votre chaîne JSON commence par une accolade ouvrante d'objet. par exemple

{

Mais la chaîne que vous lui avez passée commence par des guillemets ouverts

"
bhspencer
la source
1
Et le nom même de la méthode suggère pourquoi. parseStringToObjectsuggère qu'il attend un objet JSON, qui commence toujours par {.
yshavit
12
'[' indiquerait le début d'un tableau Json et non un objet Json.
bhspencer
je savais que .. mais que devons-nous faire pour analyser cela ??
Ajay Mistry
@AjayMistry Ce que vous demandez n'est pas clair sans plus de détails. Je suggère de publier votre problème spécifique dans une nouvelle question avec un exemple du JSON que vous essayez d'analyser.
bhspencer
1
Cher @bhspencer J'utilise retrofit dans Android APK pour obtenir d' un simple JSON comme {"ip":"192.167.1.15"}de Restful EJB web service with jboss EAP 7.1dans le backend. Cependant, j'obtiens "BEGIN_OBJECT attendu mais était STRING à la ligne 1 colonne 1" S'il vous plaît, aidez-moi ... Voici mon service 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

Le JSON non valide du serveur doit toujours être un cas d'utilisation attendu. Un million de choses peuvent mal tourner pendant la transmission. Gson est un peu délicat, car sa sortie d'erreur vous posera un problème, et l'exception réelle que vous attrapez sera d'un type différent.

Avec tout cela à l'esprit, la solution appropriée du côté client est

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

Si vous voulez savoir pourquoi le JSON que vous avez reçu du serveur est incorrect, vous pouvez regarder à l'intérieur de votre bloc catch à l'exception. Mais même si c'est votre problème, il n'est pas de la responsabilité du client de corriger le JSON qu'il reçoit d'Internet.

Dans tous les cas, il est de la responsabilité du client de décider quoi faire en cas de mauvais JSON. Deux possibilités sont de rejeter le JSON et de ne rien faire, et de réessayer.

Si vous comptez réessayer, je vous recommande fortement de définir un indicateur à l'intérieur du bloc try / catch, puis de répondre à cet indicateur en dehors du bloc try / catch. L'essai / capture imbriquée est probablement la façon dont Gson nous a mis dans ce désordre avec notre trace de pile et les exceptions ne correspondant pas.

En d'autres termes, même si j'admets que cela n'a pas l'air très élégant, je recommanderais

boolean failed = false;

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

if (failed)
{
  //...
Jessica Pennell
la source
Je veux ajouter puisque cela obtient des vues que j'ai utilisé un booléen pour la simplicité; dans le "monde réel", vous voudrez probablement tester la présence d'une chaîne dans laquelle vous avez stocké les données d'exception que vous avez collectées à l'intérieur de blocs try / catch individuels, en rejouant essentiellement l'historique de la transaction pour vous permettre de prendre des décisions intelligentes quant à s'il faut réessayer et envoyer une sortie utile lorsque vous décidez finalement d'échouer.
Jessica Pennell
5

Dans Retrofit2, lorsque vous souhaitez envoyer vos paramètres bruts, vous devez utiliser Scalars.

ajoutez d'abord ceci dans votre note:

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

}

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

Référence: [ Comment POSTER JSON entier brut dans le corps d'une demande de Retrofit?

Raj008
la source
3

Peut-être que vous avez JSON Objectraison, mais la réponse que vous avez reçue ne correspond pas à vos données valides. Tout comme lorsque vous connectez l'invalide WiFi, vous pouvez recevoir une réponse étrange < html>.....< /html>qui GSONne peut pas analyser.

vous devrez peut-être en faire quelques-uns try..catch..pour cette réponse étrange afin d'éviter un crash.

BrantYu
la source
3

Je suis venu partager une solution. L'erreur m'est arrivée après avoir forcé le notbook à raccrocher. solution possible clean preject.

Wallace Roberto
la source
3

Assurez-vous que vous avez des objets DÉSERIALISÉS comme DATE / DATETIME, etc. Si vous envoyez directement JSON sans le désérialiser, cela peut causer ce problème.

Ravi Wadje
la source
SERIALISÉ avant l'envoi?
ratzip
@ratzip Désolé, je voulais dire que nous devrions ajouter un désérialiseur (logique) pour les objets comme DATE | DATETIME. J'étais confronté à ce problème lorsque je voulais mapper un JsonObject à un objet JAVA.
Ravi Wadje
3

Dans ma situation, j'ai un "modèle", composé de plusieurs paramètres String, à l'exception d'un: c'est un tableau d'octets byte[]. Un extrait de code:

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

La dernière ligne ci-dessus est quand le

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

est déclenché. En cherchant dans le SO, j'ai réalisé que je devais avoir une forme de Adapterconversion de mon BaseModelaller et retour dans un JsonObject. Avoir mélangé Stringet byte[]dans un modèle complique les choses. Apparemment, Gsonje n'aime pas vraiment la situation.

Je finis par faire un Adapterpour m'assurer qu'il byte[]est converti au Base64format. Voici ma 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));
    }
}

Pour convertir JSONObject en modèle, j'ai utilisé ce qui suit:

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

De même, pour convertir le modèle en JSONObject, j'ai utilisé ce qui suit:

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

Ce que fait le code est essentiellement de pousser la classe voulue class/object(dans ce cas, la byte[]classe) à Adapterchaque fois qu'elle est rencontrée lors de la conversion vers / depuis JSONObject.

YazidEF
la source
0

Ne pas utiliser jsonObject.toStringsur un objet JSON.

Solomon Fissehaye
la source
0

Dans mon cas, je renvoie un objet JSON en tant que

{"data": "", "message": "Présence enregistrée avec succès .. !!!", "status": "success"}

Résolu en le changeant comme

{"data": {}, "message": "Présence enregistrée avec succès .. !!!", "status": "success"}

Ici, les données sont un sous JsonObject et elles devraient commencer à partir de {pas ""

RAJESH KUMAR ARUMUGAM
la source
0

si votre format json et vos variables sont corrects, vérifiez vos requêtes de base de données ... même si les données sont correctement enregistrées dans la base de données, le problème réel peut être là-dedans ... revérifiez vos requêtes et réessayez .. J'espère que cela vous aidera

Shabbir Ahmed
la source
0

N'oubliez pas de convertir d'abord votre objet en Json en utilisant Gson ()

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

Ensuite, vous pouvez facilement le reconvertir en objet en utilisant cette bibliothèque géniale

      val fromUser = Gson().fromJson(fromUserJson, User::class.java)
dave o grady
la source
0

J'ai eu un cas où j'ai lu à partir d'un fichier json manuscrit. Le json est parfait. Cependant, cette erreur s'est produite. J'écris donc à partir d'un objet java vers un fichier json, puis je lis à partir de ce fichier json. tout va bien. Je n'ai pas vu de différence entre le json manuscrit et celui de l'objet java. Essayé au-delàComparez il ne voit aucune différence. J'ai finalement remarqué que les deux tailles de fichiers étaient légèrement différentes, et j'ai utilisé l'outil winHex et détecté des trucs supplémentaires. Donc, la solution pour ma situation est de faire une copie du bon fichier json, d'y coller le contenu et de l'utiliser.

entrez la description de l'image ici

Feng Zhang
la source