"Очікується BEGIN_OBJECT, але було STRING у колонці 1 рядка 1"


126

У мене є цей метод:

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

І я хочу розібрати JSON з:

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

Але я отримую повідомлення про помилку:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Очікується BEGIN_OBJECT, але було STRING у колонці 1 рядка 1


2
Опублікуйте рядок JSON, повернуту вашим запитом на пошту.
Адріан Леонгард

Опублікуйте свій рядок JSON
bhspencer

Відповіді:


163

Навіть не бачачи рядка JSON, ви можете сказати з повідомлення про помилку, що це не правильна структура, яку слід розбирати на екземпляр вашого класу.

Gson очікує, що ваш рядок JSON розпочнеться з дужки відкриття об'єкта. напр

{

Але рядок, який ви перейшли до нього, починається з відкритих лапок

"

1
І сама назва методу говорить про те, чому. parseStringToObjectприпускає, що він очікує об'єкт JSON, який завжди починається з {.
yshavit

12
'[' вказує на початок масиву Json, а не об'єкта Json.
bhspencer

я це знав .. але що ми повинні зробити для розбору, що ??
Ajay Mistry

@AjayMistry Не зрозуміло, про що ви питаєте, без більш детальної інформації. Я пропоную опублікувати вашу конкретну проблему в новому запитанні з прикладом JSON, який ви намагаєтеся розібрати.
bhspencer

1
Шановний @bhspencer Я використовую переоснащення в Android APK , щоб отримати простий JSON , як {"ip":"192.167.1.15"}від Restful EJB web service with jboss EAP 7.1у внутрішньому інтерфейсі. Однак я отримую "Очікувано, BEGIN_OBJECT, але було STRING у рядку 1 колонки 1". Будь ласка, допоможіть мені ... Це моя веб-служба: @Stateless @Path ("/ getflashcard") публічний клас GetFlashcard {@Interceptors (Validator.class) @GET @Produces (MediaType.APPLICATION_JSON) public String getFlashcard () {String jsonString = new JSONObject (). Put ("ip", "192.167.1.15"). ToString (); повернути jsonString; }}
Хосейн Акаджані

17

Недійсний JSON з сервера завжди має бути випадком очікуваного використання. Мільйон речей може піти не так під час передачі. Gson трохи складний, оскільки його вихід з помилками дасть вам одну проблему, а фактичний виняток, який ви потрапляєте, буде іншого типу.

Зважаючи на це, належне виправлення на стороні клієнта

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

Якщо ви хочете знати, чому JSON, який ви отримали від сервера, невірний, ви можете заглянути всередину свого блоку вилову за винятком. Але навіть якщо це ваша проблема, клієнт не зобов'язаний виправляти JSON, який він отримує з Інтернету.

Так чи інакше, відповідальність за клієнт - вирішити, що робити, коли йому стає погано JSON. Дві можливості - відкинути JSON і нічого не робити, і спробувати ще раз.

Якщо ви збираєтеся спробувати ще раз, настійно рекомендую встановити прапор всередині блоку спробу / лову, а потім відповісти на цей прапор поза блоком спробувати. Вкладений спробу / ловити, ймовірно, як Gson ввів нас у цю кашу з нашим слідом стека та винятками, які не збігаються.

Іншими словами, хоч я і визнаю, що це виглядає не дуже елегантно, я б рекомендував

boolean failed = false;

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

if (failed)
{
  //...

Я хочу додати, оскільки це отримання уявлень про те, що я використовував булевий для простоти; у "реальному світі" ви, ймовірно, захочете перевірити наявність рядка, де ви зберігали дані виключень, які ви зібрали в окремих блоках спробу / лову, по суті відтворюючи історію транзакції собі, щоб ви могли приймати розумні рішення щодо чи намагатися повторно, і надсилати корисні результати, коли врешті-решт вирішите вийти з ладу.
Джессіка Пеннелл

5

У Retrofit2, Коли ви хочете відправити параметри в сирому вигляді, ви повинні використовувати Scalars.

спочатку додайте це у свою ступінь:

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

}

моя 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) {
    }
}

Довідка: [ Як розмістити цілий JSON в тілі запиту на вдосконалення?


3

Можливо, ви JSON Objectправі, але відповідь, яку ви отримали, не є вашими дійсними даними. Так само, як під час підключення недійсного WiFi, ви можете отримати дивну відповідь, < html>.....< /html>яка GSONне може проаналізувати.

Вам може знадобитися зробити щось try..catch..для цієї дивної реакції, щоб уникнути аварії.


3

Я прийшов поділитися рішенням. Помилка трапилася зі мною після того, як змусив нотбук повіситися. можливе рішення clean preject.


3

Переконайтеся, що у вас є ДЕЗЕРІАЛІЗОВАНІ об’єкти, такі як ДАТА / ДАТЕТІМА тощо. Якщо ви безпосередньо надсилаєте JSON, не деаріалізуючи його, це може спричинити цю проблему.


СЕРІАЛІЗОВАНО перед надсиланням?
ratzip

@ratzip Вибачте, я мав на увазі, що ми повинні додати десеріалізатор (логіку) для таких об’єктів, як DATE | ДАТА, ЧАС. З цією проблемою я стикався, коли хотів зобразити JsonObject на об'єкт JAVA.
Раві Вадже

3

У моїй ситуації у мене є "модель", що складається з декількох параметрів String, за винятком одного: це байтовий масив byte[]. Деякі фрагменти коду:

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

Останній рядок вище, коли

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

спрацьовує. Шукаючи через SO, я зрозумів, що мені потрібно мати певну форму, Adapterщоб перетворити мій BaseModelJOSObject і назад. Змішання Stringта byte[]моделювання робить все складніше. Мабуть, Gsonситуація не дуже подобається.

У кінцевому підсумку роблю Adapterпереконайтеся byte[], що перетворюється у Base64формат. Ось мій Adapterклас:

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

Для перетворення JSONObject в модель я використав наступне:

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

Так само для перетворення моделі в JSONObject я використав наступне:

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

Що робить код, це в основному для проштовхування призначеного class/object(у даному випадку byte[]класу) за допомогою Adapterкожного разу, коли він стикається під час перетворення в / назад JSONObject.



0

У моєму випадку я повертаю об’єкт JSON як

{"data": "", "message": "Відвідування збережено успішно .. !!!", "status": "success"}

Вирішено, змінивши його як

{"data": {}, "message": "Відвідування збережено успішно .. !!!", "status": "success"}

Тут дані - це підрозділ JsonObject, і він повинен починатися з {not ""


0

якщо ваш формат json і змінні в порядку, то перевірте запити до вашої бази даних ... навіть якщо дані збережені в db правильно, справжня проблема може бути там ... перевірте свої запити та повторіть спробу. Сподіваюся, це допоможе


0

Не забудьте перетворити об’єкт у Json спочатку за допомогою Gson ()

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

Тоді ви можете легко перетворити його назад в об’єкт за допомогою цієї дивовижної бібліотеки

      val fromUser = Gson().fromJson(fromUserJson, User::class.java)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.