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

I have this method:

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

And I want to parse a JSON with:

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

But I get an error message:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1

This question is related to java json parsing gson

The answer is


I have come to share an solution. The error happened to me after forcing the notbook to hang up. possible solution clean preject.


if your json format and variables are okay then check your database queries...even if data is saved in db correctly the actual problem might be in there...recheck your queries and try again.. Hope it helps


Don't use jsonObject.toString on a JSON object.


In my situation, I have a "model", consist of several String parameters, with the exception of one: it is byte array byte[]. Some code snippet:

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

The last line above is when the

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

is triggered. Searching through the SO, I realised I need to have some form of Adapter to convert my BaseModel to and fro a JsonObject. Having mixed of String and byte[] in a model does complicate thing. Apparently, Gson don't really like the situation.

I end up making an Adapter to ensure byte[] is converted to Base64 format. Here is my Adapter class:

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

To convert JSONObject to model, I used the following:

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

Similarly, to convert the model to JSONObject, I used the following:

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

What the code is doing is basically to push the intended class/object (in this case, byte[] class) through the Adapter whenever it is encountered during the convertion to/fro JSONObject.


Maybe your JSON Object is right,but the response that you received is not your valid data.Just like when you connect the invalid WiFi,you may received a strange response < html>.....< /html> that GSON can not parse.

you may need to do some try..catch.. for this strange response to avoid crash.


Don't forget to convert your object into Json first using Gson()

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

Then you can easily convert it back into an object using this awesome library

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

In Retrofit2, When you want to send your parameters in raw you must use Scalars.

first add this in your 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);

}

my 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", "[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) {
    }
}

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


I had a similar problem recently and found an interesting solution. Basically I needed to deserialize following nested JSON String into my 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\":\"[email protected]\",\"title\":\"server\",\"phone\":\"0000000000\"}}}"

I ended up using regex to remove the open quotes from beginning and the end of JSON and then used apache.commons unescapeJava() method to unescape it. Basically passed the unclean JSON into following method to get back a cleansed one:

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

    return StringEscapeUtils.unescapeJava(noQuotes);
}

then used Google GSON to parse it into my own Object:

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

I had a case where I read from a handwritten json file. The json is perfect. However, this error occurred. So I write from a java object to json file, then read from that json file. things are fine. I could not see any difference between the handwritten json and the one from java object. Tried beyondCompare it sees no difference. I finally noticed the two file sizes are slightly different, and I used winHex tool and detected extra stuff. So the solution for my situation is, make copy of the good json file, paste content into it and use.

enter image description here


Make sure you have DESERIALIZED objects like DATE/DATETIME etc. If you are directly sending JSON without deserializing it then it can cause this problem.


In my case, I am Returning JSON Object as

{"data":"","message":"Attendance Saved Successfully..!!!","status":"success"}

Resolved by changing it as

{"data":{},"message":"Attendance Saved Successfully..!!!","status":"success"}

Here data is a sub JsonObject and it should starts from { not ""


In my case, my custom http-client didn't support the gzip encoding. I was sending the "Accept-Encoding: gzip" header, and so the response was sent back as a gzip string and couldn't be decoded.

The solution was to not send that header.


Invalid JSON from the server should always be an expected use case. A million things can go wrong during transmission. Gson is a bit tricky, because its error output will give you one problem, and the actual exception you catch will be of a different type.

With all that in mind, the proper fix on the client side is

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

If you want to know why the JSON you received from the server is wrong, you can look inside your catch block at the exception. But even if it is your problem, it's not the client's responsibility to fix JSON it is receiving from the internet.

Either way, it is the client's responsibility to decide what to do when it gets bad JSON. Two possibilities are rejecting the JSON and doing nothing, and trying again.

If you are going to try again, I highly recommend setting a flag inside the try / catch block and then responding to that flag outside the try / catch block. Nested try / catch is likely how Gson got us into this mess with our stack trace and exceptions not matching up.

In other words, even though I'll admit it doesn't look very elegant, I would recommend

boolean failed = false;

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

if (failed)
{
  //...

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to json

Use NSInteger as array index Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) HTTP POST with Json on Body - Flutter/Dart Importing json file in TypeScript json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 190) Angular 5 Service to read local .json file How to import JSON File into a TypeScript file? Use Async/Await with Axios in React.js Uncaught SyntaxError: Unexpected token u in JSON at position 0 how to remove json object key and value.?

Examples related to parsing

Got a NumberFormatException while trying to parse a text file for objects Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) Python/Json:Expecting property name enclosed in double quotes Correctly Parsing JSON in Swift 3 How to get response as String using retrofit without using GSON or any other library in android UIButton action in table view cell "Expected BEGIN_OBJECT but was STRING at line 1 column 1" How to convert an XML file to nice pandas dataframe? How to extract multiple JSON objects from one file? How to sum digits of an integer in java?

Examples related to gson

Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $ Gson library in Android Studio how to parse JSON file with GSON Convert Map to JSON using Jackson "Expected BEGIN_OBJECT but was STRING at line 1 column 1" Representing null in JSON Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 How to parse JSON Array (Not Json Object) in Android Parsing JSON array into java.util.List with Gson Using GSON to parse a JSON array