“Diharapkan BEGIN_OBJECT tetapi STRING di baris 1 kolom 1”

126

Saya memiliki metode ini:

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

Dan saya ingin mengurai JSON dengan:

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

Tapi saya mendapatkan pesan kesalahan:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Diharapkan BEGIN_OBJECT tetapi STRING pada baris 1 kolom 1

Crapo Wolf
sumber
2
Posting string JSON yang dikembalikan oleh permintaan posting Anda.
Adrian Leonhard
Posting string JSON Anda
bhspencer

Jawaban:

163

Bahkan tanpa melihat string JSON Anda, Anda dapat mengetahui dari pesan kesalahan bahwa itu bukan struktur yang benar untuk diurai menjadi instance kelas Anda.

Gson mengharapkan string JSON Anda dimulai dengan kurung kurawal buka objek. misalnya

{

Tapi string yang Anda berikan padanya dimulai dengan tanda kutip terbuka

"
bhspencer
sumber
1
Dan nama metode tersebut menunjukkan alasannya. parseStringToObjectmenyarankan bahwa ia mengharapkan objek JSON, yang selalu dimulai dengan {.
yshavit
12
'[' akan menunjukkan awal Array Json, bukan objek Json.
bhspencer
saya tahu itu .. tapi apa yang harus kita lakukan untuk mengurai itu ??
Ajay Mistry
@AjayMistry Tidak jelas apa yang Anda tanyakan tanpa detail lebih lanjut. Saya sarankan untuk memposting masalah khusus Anda dalam pertanyaan baru dengan contoh JSON yang Anda coba parse.
bhspencer
1
@Bhspencer yang terhormat, saya menggunakan retrofit di apk android untuk mendapatkan json sederhana seperti {"ip":"192.167.1.15"}dari Restful EJB web service with jboss EAP 7.1di backend. Namun saya mendapatkan "Diharapkan BEGIN_OBJECT tetapi STRING di baris 1 kolom 1" Tolong bantu saya ... Ini adalah layanan web saya: @Stateless @Path ("/ getflashcard") kelas publik 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 yang tidak valid dari server harus selalu menjadi kasus penggunaan yang diharapkan. Sejuta hal bisa salah selama transmisi. Gson agak rumit, karena keluaran kesalahannya akan memberi Anda satu masalah, dan pengecualian sebenarnya yang Anda tangkap akan dari jenis yang berbeda.

Dengan semua itu, perbaikan yang tepat di sisi klien adalah

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

Jika Anda ingin tahu mengapa JSON yang Anda terima dari server salah, Anda dapat melihat ke dalam blok catch Anda di pengecualian. Tetapi meskipun itu masalah Anda, itu bukan tanggung jawab klien untuk memperbaiki JSON yang diterimanya dari internet.

Either way, itu adalah tanggung jawab klien untuk memutuskan apa yang harus dilakukan ketika mendapat JSON buruk. Dua kemungkinan adalah menolak JSON dan tidak melakukan apa pun, dan mencoba lagi.

Jika Anda akan mencoba lagi, saya sangat menyarankan untuk mengatur bendera di dalam blok coba / tangkap dan kemudian menanggapi bendera itu di luar blok coba / tangkap. Percobaan / tangkap bersarang kemungkinan besar adalah bagaimana Gson membawa kita ke dalam kekacauan ini dengan pelacakan tumpukan dan pengecualian yang tidak cocok.

Dengan kata lain, meskipun saya akui tidak terlihat elegan, saya akan merekomendasikan

boolean failed = false;

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

if (failed)
{
  //...
Jessica Pennell
sumber
Saya ingin menambahkan karena ini mendapatkan tampilan yang saya gunakan boolean untuk kesederhanaan; di "dunia nyata" Anda mungkin ingin menguji keberadaan string tempat Anda menyimpan data pengecualian yang Anda kumpulkan di dalam blok coba / tangkap individu, yang pada dasarnya memutar ulang riwayat transaksi kepada diri Anda sendiri sehingga Anda dapat membuat keputusan cerdas untuk apakah akan mencoba lagi, dan mengirim keluaran yang berguna saat Anda akhirnya memutuskan untuk gagal.
Jessica Pennell
5

Di Retrofit2, Ketika Anda ingin mengirim parameter Anda dalam bentuk mentah, Anda harus menggunakan Scalars.

pertama tambahkan ini di gradle Anda:

    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 saya:

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

Referensi: [ Bagaimana cara POST seluruh JSON mentah dalam isi permintaan Retrofit?

Raj008
sumber
3

Mungkin Anda JSON Objectbenar, tetapi respons yang Anda terima bukanlah data Anda yang valid. Sama seperti ketika Anda menghubungkan yang tidak valid WiFi, Anda mungkin menerima respons aneh < html>.....< /html>yang GSONtidak dapat diurai.

Anda mungkin perlu melakukan beberapa try..catch..respon aneh ini untuk menghindari crash.

BrantYu
sumber
3

Saya datang untuk berbagi solusi. Kesalahan terjadi pada saya setelah memaksa notbook untuk menutup telepon. solusi yang mungkin clean preject.

Wallace Roberto
sumber
3

Pastikan Anda memiliki objek DESERIALISASI seperti DATE / DATETIME dll. Jika Anda langsung mengirim JSON tanpa deserialisasi maka hal ini dapat menyebabkan masalah ini.

Ravi Wadje
sumber
SERIALISASI sebelum mengirim?
ratzip
@ratzip Maaf, maksud saya kita harus menambahkan deserializer (logika) untuk objek seperti DATE | TANGGAL WAKTU. Saya menghadapi masalah ini ketika saya ingin memetakan JsonObject ke objek JAVA.
Ravi Wadje
3

Dalam situasi saya, saya memiliki "model", terdiri dari beberapa parameter String, dengan pengecualian satu: itu adalah array byte byte[]. Beberapa cuplikan kode:

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

Baris terakhir di atas adalah saat

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

dipicu. Mencari melalui SO, saya menyadari bahwa saya perlu memiliki beberapa bentuk Adapteruntuk mengubah saya BaseModelke sana kemari menjadi JsonObject. Memiliki campuran Stringdan byte[]dalam model memang memperumit. Rupanya, Gsontidak terlalu suka situasinya.

Saya akhirnya membuat Adapteruntuk memastikan byte[]diubah ke Base64format. Ini Adapterkelas saya :

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

Untuk mengonversi JSONObject menjadi model, saya menggunakan yang berikut ini:

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

Demikian pula, untuk mengonversi model ke JSONObject, saya menggunakan yang berikut ini:

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

Apa yang kode lakukan pada dasarnya adalah untuk mendorong yang dimaksudkan class/object(dalam hal ini, byte[]kelas) melalui Adaptersetiap kali ditemui selama konversi ke / dari JSONObject.

YazidEF
sumber
0

Jangan gunakan jsonObject.toStringpada objek JSON.

Solomon Fissehaye
sumber
0

Dalam kasus saya, saya Mengembalikan Objek JSON sebagai

{"data": "", "message": "Kehadiran Berhasil Disimpan .. !!!", "status": "berhasil"}

Diselesaikan dengan mengubahnya sebagai

{"data": {}, "message": "Kehadiran Berhasil Disimpan .. !!!", "status": "berhasil"}

Di sini data adalah sub JsonObject dan harus dimulai dari {bukan ""

RAJESH KUMAR ARUMUGAM
sumber
0

jika format dan variabel json Anda baik-baik saja, periksa kueri database Anda ... bahkan jika data disimpan dalam db dengan benar, masalah sebenarnya mungkin ada di sana ... periksa kembali kueri Anda dan coba lagi .. Semoga membantu

Shabbir Ahmed
sumber
0

Jangan lupa untuk mengonversi objek Anda menjadi Json terlebih dahulu menggunakan Gson ()

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

Kemudian Anda dapat dengan mudah mengubahnya kembali menjadi objek menggunakan pustaka yang mengagumkan ini

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

Saya punya kasus di mana saya membaca dari file json tulisan tangan. Json itu sempurna. Namun, kesalahan ini terjadi. Jadi saya menulis dari objek java ke file json, lalu membaca dari file json itu. semuanya baik-baik saja. Saya tidak bisa melihat perbedaan antara json tulisan tangan dan yang dari objek java. Mencoba BeyondCompare tidak melihat perbedaan. Saya akhirnya memperhatikan dua ukuran file yang sedikit berbeda, dan saya menggunakan alat winHex dan mendeteksi hal-hal tambahan. Jadi solusi untuk situasi saya adalah, buat salinan file json yang bagus, tempelkan konten ke dalamnya dan gunakan.

masukkan deskripsi gambar di sini

Feng Zhang
sumber