“预期的 BEGIN _ OBJECT 但在第1行第1列是 STRING”

我有个方法:

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

但我收到一条错误消息:

例外: java.lang. IllegalStateException: 预期的 BEGIN _ OBJECT,但在第1行第1列是 STRING

513616 次浏览

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

Gson 希望您的 JSON 字符串以对象开头的大括号开头。

{

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

"

也许您的 JSON Object是正确的,但是您收到的响应不是您的有效数据。就像当您连接无效的 WiFi时,您可能会收到一个奇怪的 < html>.....< /html>响应,而 GSON无法解析。

你可能需要做一些 try..catch..为这种奇怪的反应,以避免崩溃。

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

在卢克菲特2中,当你想原始地发送你的参数时,你必须使用标量。

首先在你的分级中加上这个:

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


}

我的样本活动:

   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 在一个改造请求的主体?

不要对 JSON 对象使用 jsonObject.toString

确保您有像 DATE/DATETIME 等的 DESERIALIZED 对象。如果您直接发送 JSON 而不反序列化它,那么它可能会导致这个问题。

我来分享一个解决方案。这个错误发生在我强迫笔记本挂起之后。可能的解决方案。

在我的例子中,我将返回 JSON 对象作为

{“数据”: “”,“信息”: “保存出勤率。” 成功... ...”,“状态”: “成功”}

通过将其更改为

{“数据”: {} ,“消息”: “已保存出勤率。” 成功... ...”,“状态”: “成功”}

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

如果你的 json 格式和变量是正确的,然后检查你的数据库查询... 即使数据被正确地保存在数据库中,实际的问题可能在那里... 重新检查你的查询,再试一次。.希望能有帮助

在我的情况下,我有一个“模型”,由几个 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。在模型中混合了 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);

代码所做的基本上就是在转换到/from JSONObject 期间遇到 class/object(在本例中是 byte[]类)时,将预期的 class/object通过 Adapter

不要忘记首先使用 Gson ()将对象转换为 Json

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

然后,您可以轻松地将其转换回一个对象使用这个令人敬畏的库

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

我曾经看过一个手写的 json 文件。Json 太完美了。但是,出现了此错误。所以我从一个 java 对象写入 json 文件,然后读取该 json 文件。一切都很好。我看不出手写的 json 和来自 java 对象的 json 之间有什么区别。相比之下,它看不出有什么不同。 最后,我注意到这两个文件的大小略有不同,我使用了 winHex 工具并检测到了额外的内容。 因此,我的解决方案是,复制好的 json 文件,将内容粘贴到其中并使用。

enter image description here

我最近也遇到过类似的问题,并且找到了一个有趣的解决方案。基本上,我需要将嵌套的 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\"}}}"

最后,我使用 regex 从 JSON 的开头和结尾删除打开的引号,然后使用 ApacheCommons 无法逃脱 Java ()方法取消转义。基本上将不干净的 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));

在我的例子中,我的自定义 http-client 不支持 gzip 编码。我正在发送“ Accept-Encoding: gzip”头文件,因此响应被作为 gzip 字符串发送回来,无法解码。

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

我正在使用 仿生人中的 翻新发出带有一些参数的 POST 请求

我所面对的:

我在 Android Studio logcat 中得到的错误是:

IllegalStateException: 应该是 BEGIN _ OBJECT 但是是 STRING 在第2行第1行路径 $

[但它与 VOLLY 图书馆工作良好]

我谷歌了一下。 你知道[显然 json 期待一个物体,但是... ]

但是,当我更改服务以返回一个简单的字符串[如 print _ r (“ don’t lose hope”))]或 完全没有

在邮差杂志上印得很好 但是在 Android 工作室的 logcat 中,它仍然是同样的错误[

IllegalStateException: 应该是 BEGIN _ OBJECT 但是是 STRING 在第2行第1行路径 $

]

暂停现在,我发送一个简单的消息或没有发送任何回应,仍然是工作室 告诉我“ ... 预期的开始 _ 对象,但是字符串...” 出事了

第四天: 最后,我停下来寻找“快速解决方案”,并真正阅读了一些堆栈溢出问题 和物品。

我得到了什么:

日志拦截器

它将显示来自您的服务器的任何数据(甚至生态消息) ,这些数据没有显示在 安多利工作室的日志, 这样你就能找到问题所在。

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

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

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

然后我简单地搜索了一篇文章“如何使用 Afterfit 发出 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);

一切都很好。

结论:

我不明白为什么翻新会出现这个错误

IllegalStateException: 应该是 BEGIN _ OBJECT 但是是 STRING 在第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也给了它一个有效的响应,但是我是这样使用 Interface 的

@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中,当我尝试 file-> 无效并重新启动时,这个问题没有得到解决

还有

重新启动后,在第一次构建得到了相同的错误,但在第二次构建这个问题解决了

我不明白为什么会这样

我用的是旧版的翻新图书馆。所以我要做的就是把我的代码从这里升级到 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>