„Oczekiwano BEGIN_OBJECT, ale było STRING w wierszu 1 kolumny 1”

127

Mam taką metodę:

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

Chcę przeanalizować JSON za pomocą:

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

Ale pojawia się komunikat o błędzie:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: oczekiwano BEGIN_OBJECT, ale było STRING w linii 1 w kolumnie 1

Crapo Wolf
źródło
2
Opublikuj ciąg JSON zwrócony przez żądanie wiadomości.
Adrian Leonhard
Opublikuj swój ciąg JSON
bhspencer

Odpowiedzi:

164

Nawet nie widząc swojego ciągu JSON, możesz stwierdzić po komunikacie o błędzie, że nie jest to poprawna struktura do przeanalizowania w instancji Twojej klasy.

Gson oczekuje, że ciąg JSON zaczyna się od nawiasu otwierającego obiekt. na przykład

{

Ale przekazany ciąg znaków zaczyna się od cudzysłowu

"
bhspencer
źródło
1
A sama nazwa metody podpowiada dlaczego. parseStringToObjectsugeruje, że oczekuje obiektu JSON, który zawsze zaczyna się od {.
yshavit
12
„[” wskazywałoby początek tablicy Json, a nie obiektu Json.
bhspencer
wiedziałem, że ... ale co musimy zrobić, aby przeanalizować to?
Ajay Mistry
@AjayMistry Bez dodatkowych szczegółów nie jest jasne, o co prosisz. Sugeruję opublikowanie konkretnego problemu w nowym pytaniu z przykładem JSON, który próbujesz przeanalizować.
bhspencer
1
Drogi @bhspencer, używam modernizacji w aplikacji na Androida, aby uzyskać prosty plik json, taki jak {"ip":"192.167.1.15"}z Restful EJB web service with jboss EAP 7.1zaplecza. Jednak pojawia się komunikat „Oczekiwano BEGIN_OBJECT, ale był STRING w linii 1, kolumna 1”. Pomóż mi ... To moja usługa internetowa: @Stateless @Path ("/ getflashcard") klasa publiczna 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; }}
Hosein Aqajani
17

Nieprawidłowy kod JSON z serwera powinien zawsze być oczekiwanym przypadkiem użycia. Milion rzeczy może się nie udać podczas transmisji. Gson jest trochę skomplikowany, ponieważ jego wyjście błędu da jeden problem, a rzeczywisty złapany wyjątek będzie innego typu.

Mając to wszystko na uwadze, właściwą poprawką po stronie klienta jest

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

Jeśli chcesz wiedzieć, dlaczego kod JSON otrzymany z serwera jest nieprawidłowy, możesz zajrzeć do bloku catch w wyjątek. Ale nawet jeśli jest to twój problem, klient nie jest odpowiedzialny za naprawianie JSON, które otrzymuje z Internetu.

Tak czy inaczej, to klient jest odpowiedzialny za podjęcie decyzji, co zrobić, gdy pojawi się zły JSON. Dwie możliwości to odrzucenie JSON i nic nie robienie i ponowna próba.

Jeśli masz zamiar spróbować ponownie, bardzo polecam ustawienie flagi wewnątrz bloku try / catch, a następnie udzielenie odpowiedzi na tę flagę poza blokiem try / catch. Zagnieżdżone try / catch to prawdopodobnie sposób, w jaki Gson wpuścił nas w ten bałagan, ponieważ nasz ślad stosu i wyjątki nie pasują do siebie.

Innymi słowy, chociaż przyznam, że nie wygląda to zbyt elegancko, polecam

boolean failed = false;

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

if (failed)
{
  //...
Jessica Pennell
źródło
Chcę dodać, ponieważ jest to uzyskiwanie widoków, których użyłem jako wartości logicznej dla uproszczenia; w „prawdziwym świecie” prawdopodobnie będziesz chciał sprawdzić obecność ciągu znaków, w którym zapisałeś dane wyjątków zebrane w poszczególnych blokach try / catch, zasadniczo odtwarzając historię transakcji dla siebie, dzięki czemu możesz podejmować inteligentne decyzje dotyczące czy ponowić próbę i wysłać przydatne dane wyjściowe, gdy ostatecznie zdecydujesz się nie udać.
Jessica Pennell
5

W Retrofit2, jeśli chcesz przesłać parametry w formacie RAW, musisz użyć skalarów.

najpierw dodaj to w swoim 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);

}

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

Odniesienie: [ Jak POSTOWAĆ nieprzetworzony cały kod JSON w treści żądania modernizacji?

Raj008
źródło
3

Może masz JSON Objectrację, ale odpowiedź, którą otrzymałeś, nie jest poprawnymi danymi, tak jak przy podłączaniu nieprawidłowego WiFi, możesz otrzymać dziwną odpowiedź < html>.....< /html>, GSONktórej nie można przeanalizować.

może być konieczne zrobienie try..catch..tej dziwnej odpowiedzi, aby uniknąć awarii.

BrantYu
źródło
3

Przyszedłem podzielić się rozwiązaniem. Wystąpił błąd po zmuszeniu notatnika do rozłączenia się. możliwe rozwiązanie clean preject.

Wallace Roberto
źródło
3

Upewnij się, że masz DESERIALIZOWANE obiekty, takie jak DATE / DATETIME itp. Jeśli bezpośrednio wysyłasz JSON bez deserializacji, może to spowodować ten problem.

Ravi Wadje
źródło
SERIALIZOWANY przed wysłaniem?
ratzip,
@ratzip Przepraszamy, miałem na myśli, że powinniśmy dodać deserializator (logikę) dla obiektów takich jak DATA | DATETIME. Miałem do czynienia z tym problemem, gdy chciałem zmapować obiekt JsonObject na obiekt JAVA.
Ravi Wadje,
3

W mojej sytuacji mam „model”, składający się z kilku parametrów String, z wyjątkiem jednego: jest to tablica bajtów byte[]. Jakiś fragment kodu:

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

Ostatnia linia powyżej dotyczy pliku

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

jest wyzwalany. Przeszukując SO, zdałem sobie sprawę, że potrzebuję jakiejś formy Adapterkonwersji BaseModeldo i z JsonObject. Mieszanie Stringi byte[]w modelu komplikuje sprawę. Widocznie,Gson nie podoba mi się ta sytuacja.

W końcu robię, Adapteraby upewnić się, że byte[]zostanie przekonwertowany do Base64formatu. Oto moja Adapterklasa:

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

Aby przekonwertować JSONObject na model, użyłem:

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

Podobnie, aby przekonwertować model na JSONObject, użyłem:

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

Zasadniczo kod polega na przepchnięciu zamierzonej class/object(w tym przypadku byte[]klasy) przez plikAdapter każdym razem, gdy zostanie napotkana podczas konwersji do / z JSONObject.

YazidEF
źródło
0

Nie używaj jsonObject.toStringna obiekcie JSON.

Solomon Fissehaye
źródło
0

W moim przypadku zwracam obiekt JSON jako

{"data": "", "message": "Obecność zapisana pomyślnie .. !!!", "status": "sukces"}

Rozwiązano, zmieniając go jako

{"data": {}, "message": "Obecność zapisana pomyślnie .. !!!", "status": "sukces"}

Tutaj dane są podrzędnym obiektem JsonObject i powinny zaczynać się od {nie ""

RAJESH KUMAR ARUMUGAM
źródło
0

jeśli format json i zmienne są w porządku, sprawdź zapytania bazy danych ... nawet jeśli dane są poprawnie zapisane w bazie danych, może tam być rzeczywisty problem ... sprawdź ponownie swoje zapytania i spróbuj ponownie .. Mam nadzieję, że to pomoże

Shabbir Ahmed
źródło
0

Nie zapomnij najpierw przekonwertować swojego obiektu na Json za pomocą Gson ()

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

Następnie możesz łatwo przekształcić go z powrotem w obiekt za pomocą tej niesamowitej biblioteki

      val fromUser = Gson().fromJson(fromUserJson, User::class.java)
dave o grady
źródło
0

Miałem przypadek, w którym czytałem z odręcznego pliku JSON. JSON jest doskonały. Jednak ten błąd wystąpił. Więc piszę z obiektu java do pliku json, a następnie czytam z tego pliku json. wszystko jest w porządku. Nie widziałem żadnej różnicy między odręcznym jsonem a tym z obiektu java. Wypróbowany poza tym, że nie widzi różnicy. W końcu zauważyłem, że dwa rozmiary plików są nieco inne i użyłem narzędzia winHex i wykryłem dodatkowe rzeczy. Więc rozwiązaniem dla mojej sytuacji jest skopiowanie dobrego pliku json, wklejenie do niego treści i użycie.

wprowadź opis obrazu tutaj

Feng Zhang
źródło