13
public interface UserService {
    @POST(Constants.Api.URL_REGISTRATION)
    @FormUrlEncoded
    BaseWrapper registerUser(@Field("first_name") String firstname, @Field("last_name") String lastname, @Field("regNumber") String phone, @Field("regRole") int role);


 public BaseWrapper registerUser(User user) {
        return getUserService().registerUser(user.getFirstName(), user.getLastName(), user.getPhone(), user.getRole());
    }

This create Exception

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

Big thanks for help.

Bastien Viatge
  • 315
  • 3
  • 15
androidAnonDev
  • 459
  • 3
  • 5
  • 13

7 Answers7

46

Let's look at the error you are receiving.

Expected BEGIN_OBJECT

Your JSON is an object, and all JSON objects are enclosed in curly braces ({}). BEGIN_OBJECT is therefore {. And it's expecting it somewhere.

but was STRING

But instead he found a string "Something". Still doesn't tell us where.

at line 1 column 1 path $

Ah, perfect. At line 1 column 1. Which is the start of the JSON. So you have forgotten to enclose the whole thing in {} (or at least you have forgotten the first one, but I bet you've forgotten them both).

Astrogat
  • 1,617
  • 12
  • 24
  • 3
    Note that JSON could also be enclosed in square brackets ( [ ] ), if it is an array – SnyersK Jul 15 '15 at 09:05
  • 3
    Excellent explanation with nice formatting. +1 to you. – OO7 Oct 13 '15 at 06:04
  • @OO7 @SnyersK @Astrogat How can I avoid crash my app - I get this error when trying to format API errorBody response (when I wrong request for e.g. 25 times in 10 sec)... I've got `catch (IOException | IllegalStateException e)` but it doesn't help... – y07k2 Aug 24 '16 at 08:45
  • Dear @Astrogat I have an interceptor in my server not called at all, however I get this error!!! please help – Hosein Aqajani Apr 01 '18 at 09:15
2

Recently i'd faced similiar issue and solutioned only by adding "Accept: application/json" into header section. So, if you're using retrofit 2.0;

1st solution: For post method add headers parameter like below;

@Headers({"Accept: application/json"})
@POST(Constants.Api.URL_REGISTRATION)
@FormUrlEncoded
BaseWrapper registerUser(@Field("first_name") String firstname, 
                         @Field("last_name") String lastname, 
                         @Field("regNumber") String phone, 
                         @Field("regRole") int role);

2nd solution: Add header into your interceptor class like this;

NB: Code is in kotlin

private fun getInterceptor(): Interceptor {
        try {
            return Interceptor {
                val request = it.request()
                it.proceed(
                    request.newBuilder()
                        .header("Accept", "application/json")
                        .header("Authorization", "$accessTokenType $accessToken")
                        .build()
                )
            }
        } catch (exception: Exception) {
            throw Exception(exception.message)
        }
    }
}

Hope it helps, happy coding :)

Rezwan
  • 61
  • 2
0

Cleaning and rebuilding the project works for me.

Benjamin Basmaci
  • 2,247
  • 2
  • 25
  • 46
0

If you want to add the ArrayList in the json object and parse in GSON then make sure the ArrayList should be like below.

ArrayList<JSONObject>

Instead of

ArrayList<String>

and Parse like this.

ArrayList<JSONObject> mItem = new ArrayList<JSONObject>();
mItem.add(jsonObject);

// and Use like this.
JSONArray list = new JSONArray(mItem);
jsonObject.put("Item",list);
Shaikh Mohib
  • 278
  • 3
  • 11
0

If your app was using stored data from previous version and you changed the data type, you may encounter this error.

For example: I had something stored as a String in my previous version. I later updated the class that had the data stored in it to an object type. When I ran it, I got this error. After clearing the app-data or re-installing it, the error cleared.

Clearing the app-data might be an easy fix.

0

SOLUTION

In Kotlin we can use Response of ResponseBody and manage the initial response within it.

viewModelScope.launch(Dispatchers.IO) {
        mainRepository.getAPIData(
            Constants.getRequestBody(requestBody.toString())
        ).let { it ->
            if (it.isSuccessful && it.code() == 200) {
                val responseBody = it.body()
                val res: String? = responseBody?.string()
                try {
                    val main = JSONObject(res!!)
                    Log.e("TAG", "onSuccess: " + main.toString())
                    if (main.getInt("StatusCode") == 200) {
                        val type = object : TypeToken<Response>() {}.type
                        val response: Response = Gson().fromJson(
                            main.toString(), type
                        )
                        Log.e("TAG", "onSuccess: " + response.toString())
                    } else {
                        apiResponseData.postValue(Resource.error(main.getString("Message"), null))
                        Log.e("TAG", "onFail: " + main.toString())
                    }
                } catch (exception: JSONException) {
                    Log.e("TAG", "Exception: " + exception.message)
                }
            }
        }
    }

Response - Retrofit

ResponseBody - okHttp

Response is actual model Response e.g. UserResponse

Here, getAPIData() is API call which returns Response of ResponseBody

apiResponseData is MutableLiveData

using this you can avoid JSON type cast error in response.

0

It's a proguard problem. In release minifyEnabled true broke the API models. You need to add Serializable in ResponseModel and in RequestModel API

https://i.stack.imgur.com/uHN22.png

Marco
  • 1
  • 1