簡體   English   中英

“應為 BEGIN_OBJECT 但在第 1 行第 1 列為 STRING”

[英]"Expected BEGIN_OBJECT but was STRING at line 1 column 1"

我有這個方法:

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 但在第 1 行第 1 列為 STRING

即使沒有看到您的 JSON 字符串,您也可以從錯誤消息中看出,將其解析為類實例的結構不正確。

Gson 期望您的 JSON 字符串以對象左大括號開頭。 例如

{

但是您傳遞給它的字符串以開放引號開頭

"

來自服務器的無效 JSON 應該始終是預期的用例。 在傳輸過程中,有一百萬件事情可能會出錯。 Gson 有點棘手,因為它的錯誤輸出會給你帶來一個問題,而你捕獲的實際異常將屬於不同的類型。

考慮到所有這些,客戶端的正確修復是

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

如果你想知道為什么你從服務器收到的 JSON 是錯誤的,你可以在你的 catch 塊中查看異常。 但即使這是您的問題,修復從 Internet 接收的 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)
{
  //...

我最近遇到了類似的問題,並找到了一個有趣的解決方案。 基本上我需要將以下嵌套的 JSON 字符串反序列化到我的 POJO 中:

"{\"restaurant\":{\"id\":\"abc-012\",\"name\":\"good restaurant\",\"foodType\":\"American\",\"phoneNumber\":\"123-456-7890\",\"currency\":\"USD\",\"website\":\"website.com\",\"location\":{\"address\":{\"street\":\" Good Street\",\"city\":\"Good City\",\"state\":\"CA\",\"country\":\"USA\",\"postalCode\":\"12345\"},\"coordinates\":{\"latitude\":\"00.7904692\",\"longitude\":\"-000.4047208\"}},\"restaurantUser\":{\"firstName\":\"test\",\"lastName\":\"test\",\"email\":\"test@test.com\",\"title\":\"server\",\"phone\":\"0000000000\"}}}"

我最終使用正則表達式從 JSON 的開頭和結尾刪除開放引號,然后使用apache.commons unescapeJava()方法對其進行轉義。 基本上將不干凈的 JSON 傳遞給以下方法以取回一個干凈的 JSON:

private String removeQuotesAndUnescape(String uncleanJson) {
    String noQuotes = uncleanJson.replaceAll("^\"|\"$", "");

    return StringEscapeUtils.unescapeJava(noQuotes);
}

然后使用 Google GSON 將其解析為我自己的對象:

MyObject myObject = new.Gson().fromJson(this.removeQuotesAndUnescape(uncleanJson));

在 Retrofit2 中,當您想以原始格式發送參數時,您必須使用標量。

首先在你的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);

}

我的 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?

我來分享一個解決方案。 強制筆記本掛斷后,錯誤發生在我身上。 可能的解決方案clean preject

也許您的JSON Object是正確的,但您收到的響應不是您的有效數據。就像當您連接無效WiFi時,您可能會收到GSON無法收到的奇怪響應< html>.....< /html>解析。

你可能需要做一些嘗試try..catch..來避免這種奇怪的反應以避免崩潰。

確保您有 DESERIALIZED 對象,例如 DATE/DATETIME 等。如果您直接發送 JSON 而不對其進行反序列化,則可能會導致此問題。

在我的情況下,我有一個“模型”,由幾個字符串參數組成,除了一個:它是字節數組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 轉換。 在模型中混合使用Stringbyte[]確實會使事情復雜化。 顯然, 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);

代碼所做的基本上是在與 JSONObject 之間的轉換過程中遇到預期的class/object (在本例中為byte[]類)通過Adapter推送。

不要在 JSON 對象上使用jsonObject.toString

就我而言,我將 JSON 對象返回為

{"data":"","message":"考勤保存成功..!!!","status":"success"}

通過將其更改為解決

{"data":{},"message":"考勤保存成功..!!!","status":"success"}

這里的數據是一個子 JsonObject,它應該從 { 而不是 ""

如果您的 json 格式和變量沒問題,請檢查您的數據庫查詢...即使數據正確保存在 db 中,實際問題可能在那里...重新檢查您的查詢並重試.. 希望它有所幫助

不要忘記首先使用 Gson() 將您的對象轉換為 Json

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

然后你可以使用這個很棒的庫輕松地將它轉換回一個對象

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

我有一個案例,我從一個手寫的 json 文件中讀取。 json是完美的。 但是,發生了這個錯誤。 所以我從一個java對象寫入json文件,然后從那個json文件中讀取。 事情很好。 我看不出手寫的 json 和來自 java 對象的有任何區別。 嘗試了beyondCompare,它沒有發現任何區別。 我終於注意到這兩個文件大小略有不同,我使用了 winHex 工具並檢測到了額外的東西。 所以我的情況的解決方案是,復制好的 json 文件,將內容粘貼到其中並使用。

在此處輸入圖像描述

就我而言,我的自定義 http-client 不支持 gzip 編碼。 我正在發送“Accept-Encoding: gzip”標頭,因此響應以 gzip 字符串的形式發回,無法解碼。

解決方案是不發送該標頭。

我正在使用Android中的Retrofit發出帶有一些參數的 POST 請求

我所面臨的:

我在 Android Studio logcat 中遇到的錯誤:

java.lang.IllegalStateException:應為 BEGIN_OBJECT,但在第 2 行第 1 列路徑 $

[但它在 VOLLY 庫中運行良好]

當我用谷歌搜索它時......你知道[顯然 json 期待一個 OBJECT 但是......]

但是當我更改我的服務以返回一個簡單的字符串 [ 比如 print_r("don't lost hope") ] 或根本沒有注意到

它在 Postman 中打印得很好,但在 Android studio logcat 中,它仍然是 SAME ERROR [

java.lang.IllegalStateException:應為 BEGIN_OBJECT,但在第 2 行第 1 列路徑 $

]

等一下,我正在發送一條簡單的消息或不發送任何響應,但工作室仍然告訴我“......預期 BEGIN_OBJECT 但是 STRING......”有些事情是錯誤的

第 4 天:我終於停下來尋找“快速解決方案”並認真閱讀了一些堆棧溢出問題和文章。

我得到了什么:

日志攔截器

它將向您顯示來自您的服務器的任何數據[甚至生態消息],這些數據未在 Andorid studios logcat 中顯示,這樣您就可以找到問題。

我發現我正在使用@Body 發送數據,例如-

@Headers("Content-Type: application/json")
@POST("CreateNewPost")
Call<Resp> createNewPost(@Body ParaModel paraModel);

但沒有參數到達服務器,一切都是空的[我發現使用日志攔截器]

然后我只是搜索了一篇文章“如何使用 Retrofit 發出 POST 請求” 這是一篇

解決方案:

從這里我改變了我的方法:

@POST("CreateNewPost")
@FormUrlEncoded
Call<Resp> createNewPost(
    @Field("user_id") Integer user_id,
    @Field("user_name") String user_name, 
    @Field("description") String description,
    @Field("tags") String tags);

一切都很好。

結論:

我不明白改造為什么會出現這個錯誤

java.lang.IllegalStateException:應為 BEGIN_OBJECT,但在第 2 行第 1 列路徑 $

這根本沒有任何意義。

所以總是詳細調試,然后找到哪里有泄漏,然后修復。

This error solved for by replacing .toString method to .string on the response

toString => string (add in try{...code..}catche(IOException e))

below code is working for me 

try {
     MainModelResponse model;
     Gson gson = new GsonBuilder().create();
     if (response.code() == ConstantValues.SUCCESS_OK) {
         model = gson.fromJson(response.body().string(), MainModelResponse.class);
     } else {
       model = gson.fromJson(response.errorBody().string(), MainModelResponse.class);
                    }
                    moduleData.postValue(model);
                }catch (IllegalStateException | JsonSyntaxException | IOException exception){
                    exception.printStackTrace();
                }

}

使用以 {}開頭和結尾的字符串。

final String jsStr = "{\"metric\":\"opentsdb_metric\",\"tags\":{\"testtag\":\"sunbotest\"},\"aggregateTags\":[],\"dps\":{\"1483399261\":18}}";

DataPoint dataPoint = new Gson().fromJson(jsStr, DataPoint.class);

這對我有用。

在我的情況下,即使Json Validator給它一個有效的響應,對象也很好,但我使用的是這樣的接口

@POST(NetworkConstants.REGISTER_USER)
Call<UserResponse> registerUser(
        @Query("name") String name,
        @Query("email") String email,
        @Query("password") String password,
        @Query("created_date") Long creationDate
);

然后我將代碼更改為

@FormUrlEncoded
@POST(NetworkConstants.REGISTER_USER)
Call<UserResponse> registerUser(
        @Field("name") String name,
        @Field("email") String email,
        @Field("password") String password,
        @Field("created_date") Long creationDate
);

一切都解決了。

我的問題與我的代碼無關

從其他項目復制一些文件后出現此問題

在指向 Gson 庫的堆棧中

在 android studio 4.2.1 中,當我嘗試文件-> 無效並重新啟動時,這個問題沒有解決

在第一次構建重新啟動后得到相同的錯誤,但在第二次構建這個問題解決了

我不明白為什么會這樣

我使用的是舊版本的改造庫。 所以我必須做的是在將代碼升級到com.squareup.retrofit2:retrofit:2.9.0后更改我的代碼:

@POST(AppConstants.UPLOAD_TRANSACTION_DETAIL)
fun postPremiumAppTransactionDetail(
   @Query("name") planName:String,
   @Query("amount") amount:String,
   @Query("user_id") userId: String,
   @Query("sub_id") planId: String,
   @Query("folder") description:String,
   @Query("payment_type") paymentType:String):
Call<TransactionResponseModel>

對此:

@FormUrlEncoded
@POST(AppConstants.UPLOAD_TRANSACTION_DETAIL)
fun postPremiumAppTransactionDetail(
   @Field("name") planName:String,
   @Field("amount") amount:String,
   @Field("user_id") userId: String,
   @Field("sub_id") planId: String,
   @Field("folder") description:String,
   @Field("payment_type") paymentType:String):
Call<TransactionResponseModel>

只需使用 Gson。

Example eg = new Example();
eg.setName("");
eg.setTitle("");

Gson gson = new Gson();
String value = gson.toJson(eg);

Gson.toJson() 返回字符串數據類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM