【问题标题】:"Expected BEGIN_OBJECT but was STRING at line 1 column 1"“预期为 BEGIN_OBJECT,但在第 1 行第 1 列为 STRING”
【发布时间】:2015-04-09 17:13:04
【问题描述】:

我有这个方法:

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

【问题讨论】:

  • 发布您的 post 请求返回的 JSON 字符串。
  • 发布您的 JSON 字符串

标签: java json parsing gson


【解决方案1】:

只需使用 Gson。

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

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

Gson.toJson() returns String datatype.

【讨论】:

    【解决方案2】:

    我使用的是旧版本的改造库。所以我必须做的就是在将代码升级到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>
    

    【讨论】:

      【解决方案3】:

      我的问题与我的代码无关

      从其他项目复制一些文件后遇到此问题

      在指向 Gson 库的堆栈中

      在 android studio 4.2.1 中,当我尝试 file-> 无效并重新启动时,这个问题没有解决

      在第一次构建重新启动后出现同样的错误,但在第二次构建中解决了这个问题

      我不明白为什么会这样

      【讨论】:

        【解决方案4】:

        在我的情况下,即使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
        );
        

        一切都解决了。

        【讨论】:

          【解决方案5】:

          使用字符串 begin & end 和 {}。

          比如

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

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

          这对我有用。

          【讨论】:

            【解决方案6】:
            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();
                            }
            

            }

            【讨论】:

              【解决方案7】:

              我在 Android

              中使用 Retrofit 发出带有一些参数的 POST 请求

              我遇到了什么:

              我在 Android Studio logcat 中遇到的错误:

              java.lang.IllegalStateException: 应为 BEGIN_OBJECT 但为 STRING 在第 2 行第 1 列路径 $

              [但它在 VOLLY 库中运行良好]

              当我用谷歌搜索它时...... 你知道[显然 json 期待一个 OBJECT 但是......]

              但是当我更改我的服务以返回一个简单的字符串 [ 比如 print_r("don't lost hope") ] 或 完全注意到

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

              java.lang.IllegalStateException: 应为 BEGIN_OBJECT 但为 STRING 在第 2 行第 1 列路径 $

              ]

              请稍等,我正在发送一条简单的消息或不发送任何回复,但工作室仍在 告诉我“......预期为 BEGIN_OBJECT 但为 STRING......” 出了点问题

              第 4 天: 我终于停下来寻找“快速解决方案”并真正阅读了一些堆栈溢出问题 和文章仔细。

              我得到了什么:

              Logging interceptor

              它将向您显示来自您的服务器的任何数据[甚至是生态消息],这些数据未显示在 Andorid工作室logcat, 这样你就可以找到问题了。

              我发现我正在使用@Body 发送数据-

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

              但是没有参数到达服务器,一切都是空的[我发现使用日志拦截器]

              然后我简单地搜索了一篇文章“如何使用 Retrofit 发出 POST 请求” here's one

              解决方案:

              从这里我将方法更改为:

              @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 但为 STRING 在第 2 行第 1 列路径 $

              这根本没有任何意义。

              所以总是详细调试,然后找到哪里有问题,然后修复。

              【讨论】:

                【解决方案8】:

                就我而言,我的自定义 http 客户端不支持 gzip 编码。我正在发送“Accept-Encoding: gzip”标头,因此响应以 gzip 字符串的形式发回,无法解码。

                解决方案是不发送该标头。

                【讨论】:

                  【解决方案9】:

                  我最近遇到了类似的问题,并找到了一个有趣的解决方案。基本上我需要将以下嵌套的 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 将其解析为我自己的 Object:

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

                  【讨论】:

                  • 对我来说就是这样。我将它作为 Gson 序列化发送出去,但我无法反序列化同一个实例。因此,它在运输过程中发生了变化。您是偶然使用 PubNub 还是这种转义通用模式的格式?
                  • @gcr 可能不是很常见,但我使用这种方法已经有一段时间了,没有发现任何问题。
                  【解决方案10】:

                  我有一个案例,我从一个手写的 json 文件中读取。 json是完美的。但是,发生了这个错误。所以我从一个java对象写入json文件,然后从那个json文件中读取。事情很好。我看不出手写的 json 和来自 java 对象的有任何区别。尝试了beyondCompare,它没有发现任何区别。 我终于注意到这两个文件大小略有不同,我使用了 winHex 工具并检测到了额外的东西。 所以我的情况的解决方案是,复制好的json文件,将内容粘贴到其中并使用。

                  【讨论】:

                    【解决方案11】:

                    别忘了先使用 Gson() 将你的对象转换成 Json

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

                    然后您可以使用这个很棒的库轻松地将其转换回对象

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

                    【讨论】:

                      【解决方案12】:

                      在我的情况下,我有一个“模型”,由几个字符串参数组成,除了一个:它是字节数组byte[]。 部分代码sn-p:

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

                      代码所做的基本上是通过Adapter 推送预期的class/object(在本例中为byte[] 类),只要在与JSONObject 的转换过程中遇到它。

                      【讨论】:

                        【解决方案13】:

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

                        参考:[How to POST raw whole JSON in the body of a Retrofit request?

                        【讨论】:

                          【解决方案14】:

                          如果您的 json 格式和变量没问题,请检查您的数据库查询...即使数据正确保存在 db 中,实际问题也可能存在...重新检查您的查询并重试.. 希望对您有所帮助

                          【讨论】:

                            【解决方案15】:

                            确保您有 DESERIALIZED 对象,例如 DATE/DATETIME 等。如果您直接发送 JSON 而不对其进行反序列化,则可能会导致此问题。

                            【讨论】:

                            • 发送前已序列化?
                            • @ratzip 对不起,我的意思是我们应该为像 DATE | 这样的对象添加一个反序列化器(逻辑)。约会时间。当我想将 JsonObject 映射到 JAVA 对象时,我遇到了这个问题。
                            【解决方案16】:

                            就我而言,我将 JSON 对象返回为

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

                            改成这样解决了

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

                            这里的数据是一个子JsonObject,它应该从{而不是“”开始

                            【讨论】:

                              【解决方案17】:

                              我来分享一个解决方案。强制笔记本挂断后,错误发生在我身上。可能的解决方案clean preject

                              【讨论】:

                                【解决方案18】:

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

                                【讨论】:

                                  【解决方案19】:

                                  即使没有看到您的 JSON 字符串,您也可以从错误消息中看出它不是被解析为您的类实例的正确结构。

                                  Gson 期望您的 JSON 字符串以对象左大括号开头。例如

                                  {
                                  

                                  但是你传递给它的字符串以一个开引号开始

                                  "
                                  

                                  【讨论】:

                                  • 这个方法的名字就说明了原因。 parseStringToObject 建议它需要一个 JSON 对象,该对象始终以 { 开头。
                                  • '[' 表示 Json 数组的开始,而不是 Json 对象。
                                  • 我知道.. 但是我们必须做些什么来解析它??
                                  • @AjayMistry 如果没有更多详细信息,不清楚你在问什么。我建议在一个新问题中发布您的具体问题,并附上您尝试解析的 JSON 示例。
                                  • 亲爱的@bhspencer 我在android apk 中使用改造来从后端的Restful EJB web service with jboss EAP 7.1 获取一个简单的json,比如{"ip":"192.167.1.15"}。但是我得到“预期 BEGIN_OBJECT 但在第 1 行第 1 列是 STRING”请帮助我...这是我的 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();返回 jsonString; } }
                                  【解决方案20】:

                                  来自服务器的无效 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)
                                  {
                                    //...
                                  

                                  【讨论】:

                                  • 我想添加,因为这是为了简单起见我使用布尔值获得的视图;在“现实世界”中,您可能希望测试是否存在一个字符串,该字符串存储了您在单个 try/catch 块中收集的异常数据,本质上是向您自己重放事务的历史记录,以便您做出明智的决定是否重试,并在您最终决定失败时发送有用的输出。
                                  【解决方案21】:

                                  也许你的JSON Object是对的,但你收到的回复不是你的有效数据。就像你连接无效的WiFi时,你可能会收到GSON无法解析的奇怪回复&lt; html&gt;.....&lt; /html&gt; .

                                  您可能需要为这个奇怪的响应做一些try..catch.. 以避免崩溃。

                                  【讨论】:

                                    猜你喜欢
                                    • 1970-01-01
                                    • 2023-01-01
                                    • 1970-01-01
                                    • 2023-03-14
                                    • 2019-07-27
                                    • 2017-05-12
                                    相关资源
                                    最近更新 更多