«Ожидается BEGIN_OBJECT, но в строке 1 столбца 1 было STRING»

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, возвращенную вашим почтовым запросом.
Адриан Леонхард,
Опубликуйте

Ответы:

163

Даже не видя свою строку JSON, вы можете сказать по сообщению об ошибке, что это неправильная структура для анализа в экземпляр вашего класса.

Gson ожидает, что ваша строка JSON будет начинаться с открывающей скобки объекта. например

{

Но строка, которую вы ему передали, начинается с открытых кавычек

"
bhspencer
источник
1
И само название метода подсказывает, почему. parseStringToObjectпредполагает, что он ожидает объект JSON, который всегда начинается с {.
yshavit
12
'[' будет указывать на начало массива Json, а не объекта Json.
bhspencer
я знал это .. но что мы должны сделать для синтаксического анализа ??
Аджай Мистри
@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 (); return jsonString; }}
Хосейн Акаджани 02
17

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

Учитывая все это, правильное исправление на стороне клиента

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

Если вы хотите узнать, почему JSON, который вы получили от сервера, неправильный, вы можете заглянуть в свой блок catch на исключение. Но даже если это ваша проблема, клиент не обязан исправлять JSON, который он получает из Интернета.

В любом случае, клиент должен решить, что делать, если JSON станет плохим. Две возможности: отклонить JSON, ничего не делать и повторить попытку.

Если вы собираетесь повторить попытку, я настоятельно рекомендую установить флаг внутри блока try / catch, а затем реагировать на этот флаг вне блока try / catch. Вложенный метод try / catch, вероятно, является причиной того, как Gson ввел нас в этот беспорядок, когда наша трассировка стека и исключения не совпадают.

Другими словами, хотя я признаю, что это выглядит не очень элегантно, я бы рекомендовал

boolean failed = false;

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

if (failed)
{
  //...
Джессика Пеннелл
источник
Я хочу добавить, так как получаются представления, которые я для простоты использовал логическое значение; в «реальном мире» вы, вероятно, захотите проверить наличие строки, в которой вы сохранили данные исключения, которые вы собрали в отдельных блоках try / catch, по сути воспроизводя историю транзакции самому себе, чтобы вы могли принимать разумные решения относительно следует ли повторять попытку и отправлять полезные выходные данные, когда вы в конечном итоге решите потерпеть неудачу.
Джессика Пеннелл
5

В Retrofit2, когда вы хотите отправить свои параметры в необработанном виде, вы должны использовать скаляры.

сначала добавьте это в свой градиент:

    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 в тело запроса на модернизацию?

Raj008
источник
3

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

вам может потребоваться что-то сделать try..catch..для этого странного ответа, чтобы избежать сбоя.

BrantYu
источник
3

Я пришел, чтобы поделиться решением. Ошибка произошла у меня после принудительного зависания нотбука. возможное решение clean preject.

Уоллес Роберто
источник
3

Убедитесь, что у вас есть DESERIALIZED объекты, такие как DATE / DATETIME и т. Д. Если вы напрямую отправляете JSON без десериализации, это может вызвать эту проблему.

Рави Вадже
источник
СЕРИАЛИЗИРОВАННЫЙ перед отправкой?
ratzip 06
@ratzip Извините, я имел в виду, что мы должны добавить десериализатор (логику) для таких объектов, как DATE | DATETIME. Я столкнулся с этой проблемой, когда хотел сопоставить 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для преобразования моего BaseModelтуда и обратно JsonObject. Смешивание 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.

YazidEF
источник
0

Не используйте jsonObject.toStringобъект JSON.

Соломон Фиссехай
источник
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)
Дэйв о Грейди
источник
0

У меня был случай, когда я читал из рукописного файла json. JSON идеален. Однако произошла эта ошибка. Поэтому я пишу из java-объекта в json-файл, а затем читаю из этого json-файла. все в порядке. Я не видел никакой разницы между рукописным json и java-объектом. Пробовал дальшеCompare не видит разницы. Наконец я заметил, что два размера файлов немного различаются, и я использовал инструмент winHex и обнаружил лишние вещи. Итак, решение для моей ситуации - сделать копию хорошего json-файла, вставить в него содержимое и использовать.

введите описание изображения здесь

Фэн Чжан
источник