“Dự kiến ​​là BEGIN_OBJECT nhưng là STRING ở dòng 1 cột 1”


126

Tôi có phương pháp này:

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

Và tôi muốn phân tích cú pháp JSON với:

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

Nhưng tôi nhận được thông báo lỗi:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT được mong đợi nhưng lại là STRING ở dòng 1 cột 1


2
Đăng chuỗi JSON được trả về bởi yêu cầu bài đăng của bạn.
Adrian Leonhard

Đăng chuỗi JSON của bạn
bhspencer

Câu trả lời:


163

Ngay cả khi không nhìn thấy chuỗi JSON của bạn, bạn có thể biết từ thông báo lỗi rằng nó không phải là cấu trúc chính xác để được phân tích cú pháp thành một phiên bản của lớp của bạn.

Gson đang mong đợi chuỗi JSON của bạn bắt đầu bằng dấu ngoặc nhọn mở đối tượng. ví dụ

{

Nhưng chuỗi bạn đã chuyển đến nó bắt đầu bằng một dấu ngoặc kép mở

"

1
Và chính cái tên của phương pháp đã gợi ý lý do tại sao. parseStringToObjectgợi ý rằng nó mong đợi một đối tượng JSON, luôn bắt đầu bằng {.
yshavit

12
'[' sẽ chỉ ra điểm bắt đầu của Mảng Json không phải là đối tượng Json.
bhspencer

tôi biết điều đó .. nhưng chúng ta phải làm gì để phân tích cú pháp đó ??
Ajay Mistry

@AjayMistry Không rõ bạn đang hỏi gì nếu không có thêm chi tiết. Tôi khuyên bạn nên đăng vấn đề cụ thể của bạn trong một câu hỏi mới với ví dụ về JSON mà bạn đang cố gắng phân tích cú pháp.
bhspencer

1
Thưa @bhspencer Tôi đang sử dụng trang bị thêm trong apk android để có được một json đơn giản như {"ip":"192.167.1.15"}từ Restful EJB web service with jboss EAP 7.1trong backend. Tuy nhiên, tôi nhận được “Dự kiến ​​là BEGIN_OBJECT nhưng bị STRING ở dòng 1 cột 1” Vui lòng giúp tôi ... Đây là dịch vụ web của tôi: @Stateless @Path ("/ getflashcard") lớp công khai GetFlashcard {@Interceptors (Validator.class) @GET @Productiones (MediaType.APPLICATION_JSON) public String getFlashcard () {String jsonString = new JSONObject (). Put ("ip", "192.167.1.15"). ToString (); trả về jsonString; }}
Hosein Aqajani

17

JSON không hợp lệ từ máy chủ phải luôn là trường hợp sử dụng được mong đợi. Một triệu thứ có thể gặp trục trặc trong quá trình truyền. Gson hơi phức tạp, vì đầu ra lỗi của nó sẽ gây ra cho bạn một vấn đề và ngoại lệ thực tế bạn bắt được sẽ thuộc một loại khác.

Với tất cả những điều đó, cách khắc phục phù hợp ở phía khách hàng là

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

Nếu bạn muốn biết lý do tại sao JSON bạn nhận được từ máy chủ bị sai, bạn có thể xem xét bên trong khối bắt của mình ở ngoại lệ. Nhưng ngay cả khi đó là vấn đề của bạn, khách hàng không có trách nhiệm phải sửa JSON mà nó đang nhận được từ internet.

Dù bằng cách nào, khách hàng có trách nhiệm quyết định phải làm gì khi nó gặp lỗi JSON. Có hai khả năng là từ chối JSON và không làm gì cả và thử lại.

Nếu bạn định thử lại, tôi thực sự khuyên bạn nên đặt một cờ bên trong khối try / catch và sau đó trả lời cờ đó bên ngoài khối try / catch. Thử / bắt lồng nhau có thể là cách Gson đưa chúng ta vào mớ hỗn độn này với dấu vết ngăn xếp và ngoại lệ của chúng ta không khớp với nhau.

Nói cách khác, mặc dù tôi thừa nhận rằng nó trông không được thanh lịch cho lắm, nhưng tôi khuyên bạn nên

boolean failed = false;

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

if (failed)
{
  //...

Tôi muốn thêm vì điều này đang nhận được các chế độ xem mà tôi đã sử dụng boolean cho đơn giản; trong "thế giới thực", bạn có thể sẽ muốn kiểm tra sự hiện diện của một chuỗi nơi bạn lưu trữ dữ liệu ngoại lệ mà bạn đã thu thập bên trong các khối thử / bắt riêng lẻ, về cơ bản là phát lại lịch sử giao dịch cho chính bạn để bạn có thể đưa ra quyết định thông minh có nên thử lại hay không và gửi kết quả hữu ích khi cuối cùng bạn quyết định thất bại.
Jessica Pennell

5

Trong Retrofit2, Khi bạn muốn gửi các tham số của mình ở dạng thô, bạn phải sử dụng Scalars.

trước tiên hãy thêm cái này vào gradle của bạn:

    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 của tôi:

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

Tham khảo: [ Làm cách nào để ĐĂNG toàn bộ JSON thô trong nội dung của một yêu cầu Trang bị thêm?


3

Có lẽ bạn JSON Objectlà đúng, nhưng câu trả lời mà bạn nhận được không phải là data.Just hợp lệ của bạn như khi bạn kết nối không hợp lệ WiFi, bạn có thể nhận được một phản ứng kỳ lạ < html>.....< /html>GSONkhông thể phân tích cú pháp.

bạn có thể cần thực hiện một số thao tác try..catch..đối với phản hồi kỳ lạ này để tránh sự cố.


3

Tôi đã đến để chia sẻ một giải pháp. Lỗi đã xảy ra với tôi sau khi buộc treo sổ ghi chú. giải pháp khả thi clean preject.


3

Đảm bảo rằng bạn có các đối tượng MÔ TẢ như DATE / DATETIME, v.v. Nếu bạn đang trực tiếp gửi JSON mà không giải mã hóa nó thì có thể gây ra sự cố này.


ĐÃ XỬ LÝ trước khi gửi?
ratzip

@ratzip Xin lỗi, ý tôi là chúng ta nên thêm bộ giải mã (logic) cho các đối tượng như DATE | NGÀY GIỜ. Tôi đã gặp phải vấn đề này khi tôi muốn ánh xạ một JsonObject tới một đối tượng JAVA.
Ravi Wadje

3

Trong tình huống của tôi, tôi có một "mô hình", bao gồm một số tham số Chuỗi, ngoại trừ một tham số: đó là mảng byte byte[]. Một số đoạn mã:

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

Dòng cuối cùng ở trên là khi

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

được kích hoạt. Tìm kiếm qua SO, tôi nhận ra rằng tôi cần phải có một số hình thức Adapterđể chuyển đổi BaseModelsang và chuyển đổi một JsonObject. Việc kết hợp giữa Stringbyte[]trong một mô hình sẽ làm mọi thứ phức tạp. Rõ ràng, Gsonkhông thực sự thích tình hình.

Tôi kết thúc việc thực hiện một Adapterđể đảm bảo byte[]được chuyển đổi sang Base64định dạng. Đây là Adapterlớp học của tôi :

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

Để chuyển đổi JSONObject thành mô hình, tôi đã sử dụng như sau:

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

Tương tự, để chuyển đổi mô hình thành JSONObject, tôi đã sử dụng như sau:

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

Những gì mã đang làm về cơ bản là để đẩy dự định class/object(trong trường hợp này là byte[]lớp) thông qua Adapterbất cứ khi nào nó gặp phải trong quá trình chuyển đổi sang / fro JSONObject.



0

Trong trường hợp của tôi, tôi đang Trả lại Đối tượng JSON dưới dạng

{"data": "", "message": "Điểm danh đã Lưu thành công .. !!!", "status": "success"}

Đã giải quyết bằng cách thay đổi nó thành

{"data": {}, "message": "Điểm danh đã Lưu thành công .. !!!", "status": "success"}

Ở đây dữ liệu là một JsonObject con và nó phải bắt đầu từ {not ""


0

nếu định dạng json và các biến của bạn ổn thì hãy kiểm tra các truy vấn cơ sở dữ liệu của bạn ... ngay cả khi dữ liệu được lưu trong db một cách chính xác thì vấn đề thực sự có thể nằm trong đó ... hãy kiểm tra lại các truy vấn của bạn và thử lại .. Hy vọng nó sẽ hữu ích


0

Đừng quên chuyển đổi đối tượng của bạn thành Json trước bằng cách sử dụng Gson ()

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

Sau đó, bạn có thể dễ dàng chuyển đổi nó trở lại thành một đối tượng bằng cách sử dụng thư viện tuyệt vời này

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

0

Tôi đã gặp một trường hợp khi tôi đọc từ một tệp json viết tay. Json là hoàn hảo. Tuy nhiên, lỗi này đã xảy ra. Vì vậy, tôi ghi từ một đối tượng java vào tệp json, sau đó đọc từ tệp json đó. mọi thứ vẫn ổn. Tôi không thể thấy bất kỳ sự khác biệt nào giữa json viết tay và json từ đối tượng java. Đã thử vượt quá So sánh nó không thấy sự khác biệt. Cuối cùng tôi nhận thấy hai kích thước tệp hơi khác nhau và tôi đã sử dụng công cụ winHex và phát hiện thêm những thứ khác. Vì vậy, giải pháp cho tình huống của tôi là tạo bản sao của tệp json tốt, dán nội dung vào đó và sử dụng.

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.