[java] “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();
    }
}

하지만 오류 메시지가 나타납니다.

com.google.gson.JsonSyntaxException : java.lang.IllegalStateException : BEGIN_OBJECT가 필요하지만 1 행 1 열에서 STRING이었습니다.



답변

JSON 문자열을 보지 않아도 오류 메시지에서 클래스 인스턴스로 구문 분석 할 올바른 구조가 아니라는 것을 알 수 있습니다.

Gson은 JSON 문자열이 객체 여는 중괄호로 시작될 것으로 예상합니다. 예 :

{

그러나 전달한 문자열은 열린 따옴표로 시작합니다.

"


답변

서버의 잘못된 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)
{
  //...


답변

Retrofit2에서 매개 변수를 raw로 보내려면 스칼라를 사용해야합니다.

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

참조 : [ Retrofit 요청 본문에 원시 전체 JSON을 POST하는 방법은 무엇입니까?


답변

아마도 당신 JSON Object이 맞았을 수도 있지만, 당신이받은 응답은 당신의 유효한 데이터가 아닙니다. 마치 당신이 잘못된 것을 연결할 때처럼 WiFi, 당신은 구문 분석 할 수없는 이상한 응답 < html>.....< /html>GSON받을 수 있습니다.

try..catch..충돌을 피하기 위해이 이상한 응답을 위해 몇 가지를 수행해야 할 수도 있습니다 .


답변

나는 해결책을 공유하기 위해 왔습니다. notbook을 강제로 끊은 후 오류가 발생했습니다. 가능한 해결책 clean preject.


답변

DATE / DATETIME 등과 같은 DESERIALIZED 개체가 있는지 확인하십시오. JSON을 deserialize하지 않고 직접 보내는 경우이 문제가 발생할 수 있습니다.


답변

내 상황에서는 하나를 제외하고 여러 문자열 매개 변수로 구성된 “모델”이 있습니다 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를 통해 검색하면서 JsonObject로 또는 이리저리 Adapter변환하려면 어떤 형태가 필요하다는 것을 깨달았습니다 BaseModel. 모델 Stringbyte[]모델 을 혼합하면 일이 복잡해집니다. 분명히 Gson상황이별로 마음에 들지 않습니다.

나는 형식으로 변환 Adapter되도록 만들기 위해 끝납니다 . 내 수업 은 다음과 같습니다 .byte[]Base64Adapter

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

코드가 수행하는 작업은 기본적으로 의도 된 class/object(이 경우 byte[]클래스)을Adapter JSONObject로 /로 변환하는 동안 발생할 때마다 입니다.