“BEGIN_OBJECT가 필요하지만 1 행 1 열에서 STRING이었습니다.”


126

이 방법이 있습니다.

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이었습니다.


2
게시 요청에서 반환 된 JSON 문자열을 게시합니다.
Adrian Leonhard 2015

JSON 문자열 게시
bhspencer 2015

답변:


163

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

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

{

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

"

1
그리고 그 방법의 이름 자체가 그 이유를 암시합니다. parseStringToObject는 항상 {.
yshavit 2015

12
'['는 Json 객체가 아닌 Json 배열의 시작을 나타냅니다.
bhspencer

나는 그것을 알고 있었다. 그러나 우리가 그것을 파싱하기 위해 무엇을해야 하는가 ??
Ajay Mistry

@AjayMistry 자세한 내용 없이는 무엇을 요구하는지 명확하지 않습니다. 구문 분석하려는 JSON의 예와 함께 새 질문에 특정 문제를 게시하는 것이 좋습니다.
bhspencer

1
나는 안드로이드 APK에 개조를 사용하고 친애하는 @bhspencer 같은 간단한 JSON을 얻을 {"ip":"192.167.1.15"}에서 Restful EJB web service with jboss EAP 7.1백엔드한다. 그러나 "예상 된 BEGIN_OBJECT이지만 1 행 1 열에서 STRING이었습니다"라는 메시지가 표시됩니다. 제발 도와주세요. 이것은 내 웹 서비스입니다. @Stateless @Path ( "/ getflashcard") public class GetFlashcard {@Interceptors (Validator.class) @GET @Produces (MediaType.APPLICATION_JSON) public String getFlashcard () {String jsonString = new JSONObject (). put ( "ip", "192.167.1.15"). toString (); return jsonString; }}
하면서 스토리지 Aqajani

17

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

단순성을 위해 부울을 사용한 뷰를 가져 오기 때문에 추가하고 싶습니다. "실제"에서는 개별 try / catch 블록 내에 수집 한 예외 데이터를 저장 한 문자열이 있는지 테스트하고 본질적으로 트랜잭션 기록을 재생하여 다음과 같은 지능적인 결정을 내릴 수 있습니다. 재시도 여부를 확인하고 결국 실패하기로 결정할 때 유용한 출력을 보냅니다.
Jessica Pennell

5

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하는 방법은 무엇입니까?


3

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

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


3

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


3

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


보내기 전에 SERIALIZED?
ratzip

@ratzip 죄송합니다. DATE | 같은 객체에 deserializer (logic)를 추가해야한다는 의미입니다. 날짜 시간. JsonObject를 JAVA 개체에 매핑하려고 할 때이 문제에 직면했습니다.
Ravi Wadje 2018 년

3

내 상황에서는 하나를 제외하고 여러 문자열 매개 변수로 구성된 "모델"이 있습니다 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로 /로 변환하는 동안 발생할 때마다 입니다.



0

제 경우에는 JSON 객체를 다음과 같이 반환합니다.

{ "data": "", "message": "출석이 성공적으로 저장되었습니다 .. !!!", "status": "success"}

다음과 같이 변경하여 해결되었습니다.

{ "data": {}, "message": "출석이 성공적으로 저장되었습니다 .. !!!", "status": "success"}

여기서 데이터는 하위 JsonObject이며 ""가 아닌 {에서 시작해야합니다.


0

json 형식과 변수가 괜찮다면 데이터베이스 쿼리를 확인하십시오. 데이터가 db에 올바르게 저장되어 있어도 실제 문제가있을 수 있습니다. 쿼리를 다시 확인하고 다시 시도하십시오. 도움이되기를 바랍니다.


0

먼저 Gson ()을 사용하여 객체를 Json으로 변환하는 것을 잊지 마십시오.

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

그런 다음이 멋진 라이브러리를 사용하여 쉽게 객체로 다시 변환 할 수 있습니다.

      val fromUser = Gson().fromJson(fromUserJson, User::class.java)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.