Ожидалось STRING, но было BEGIN_OBJECT

Я прочитал много ответов об этой ошибке, и я не нашел решения для себя, возможно, объект класса не тот

Моя ошибка:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: ожидалось STRING, но было BEGIN_OBJECT

Итак, я просто пытаюсь получить объект из JSON следующим образом:

JsonObject mS1SystemStatusJsonObject = parameterEntries.getValue().getAsJsonObject();

MS1SystemStatusResponse mS1SystemStatusResponse = gson.fromJson(mS1SystemStatusJsonObject, MS1SystemStatusResponse.class);

мой JsonObject:

{
 "WARNING_CONDITION_LIST":
  {
   "warningConditionList": {"warningCondition":"BLACK_POSTAL_INK_WF_COND"}
   },
 "DISABLING_CONDITION_LIST": {"disablingConditionList":""},
 "CurrentErrorList":"",
 "LockState":"lockspend",
"SystemReadyState":true
}

Мои разные POJO (я не ставлю код get и set для краткости):

public class MS1SystemStatusResponse{

@SerializedName("LockState")
String lockState;

@SerializedName("SystemReadyState")
Boolean systemReadyState;

@SerializedName("WARNING_CONDITION_LIST")
WARNING_CONDITION_LIST warningConditionListMy;

@SerializedName("DISABLING_CONDITION_LIST")
DISABLING_CONDITION_LIST disablingConditionListMy;

@JsonAdapter(EmptyStringAsNullTypeAdapter.class)    
@SerializedName("CurrentErrorList")
CurrentErrorList currentErrorList;


public class WARNING_CONDITION_LIST {

@SerializedName(value = "warningConditionList")
@JsonAdapter(EmptyStringAsNullTypeAdapter.class)
WarningConditionList warningConditionList;


public class DISABLING_CONDITION_LIST {

@SerializedName(value = "disablingConditionList")
@JsonAdapter(EmptyStringAsNullTypeAdapter.class)
DisablingConditionList disablingConditionList;

public class CurrentErrorList {

@SerializedName(value = "Error")
private Error error;


public class WARNING_CONDITION_LIST {

@SerializedName(value = "warningConditionList")
@JsonAdapter(EmptyStringAsNullTypeAdapter.class)
WarningConditionList warningConditionList;


public class WarningConditionList {

@SerializedName(value = "warningCondition")
String warningCondition;

Вот полная трассировка стека и еще один класс, который я забыл добавить раньше:

Трассировки стека :

java.lang.IllegalStateException: Expected STRING but was BEGIN_OBJECT
    com.google.gson.internal.bind.JsonTreeReader.nextString(JsonTreeReader.java:154)
    com.pb.marqueo.connect.plus.api.common.model.response.EmptyStringAsNullTypeAdapter.read(EmptyStringAsNullTypeAdapter.java:24)
    com.pb.marqueo.connect.plus.api.common.model.response.EmptyStringAsNullTypeAdapter.read(EmptyStringAsNullTypeAdapter.java:10)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:117)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:217)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:117)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:217)
    com.google.gson.Gson.fromJson(Gson.java:861)
    com.google.gson.Gson.fromJson(Gson.java:926)
    com.google.gson.Gson.fromJson(Gson.java:899)
    com.pb.marqueo.connect.plus.api.core.service.impl.ConnectPlusServicesImpl.getMS1SystemStatus(ConnectPlusServicesImpl.java:410)
    com.pb.marqueo.connect.plus.api.core.facade.impl.ConnectPlusBusinessServicesImpl.startProduction(ConnectPlusBusinessServicesImpl.java:1236)
    com.pb.marqueo.connect.plus.rest.services.impl.ConnectPlusControllerImpl.startProd(ConnectPlusControllerImpl.java:280)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    com.pb.marqueo.common.filter.OriginFilter.doFilter(OriginFilter.java:70)

Адаптер класса:

public class EmptyStringAsNullTypeAdapter extends TypeAdapter<String> {

    @Override
    public void write(JsonWriter out, String value) throws IOException {
        out.value(value);
    }

    @Override
    public String read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        String result = in.nextString();
        if ("".equals(result)) {
            return null;
        }
        return result;
    }
}

Я оборачиваюсь с 1 недели :(

что печатает mS1SystemStatusJsonObject?

Carlos López Marí 17.04.2019 17:53

Можете попробовать заменить "SystemReadyState":true на "SystemReadyState":"true"?

Arnaud Denoyelle 17.04.2019 17:54

Нет, я не могу заменить это, это влияет на многое в программе, у меня нет ошибки, когда СПИСОК ПРЕДУПРЕЖДЕНИЙ СОСТОЯНИЯ пуст.

Stephanie Joyce 17.04.2019 17:56

При запросе об исключении всегда публикует полную трассировку стека исключения.

JB Nizet 17.04.2019 18:05

Вы используете адаптер с именем EmptyStringAsNullTypeAdapter для свойств, которые не являются строками. Вероятно, причина в этом: он ожидает строку, а получает объект. Трассировка стека, вероятно, подтвердит это.

JB Nizet 17.04.2019 18:07

я добавил полную трассировку стека

Stephanie Joyce 17.04.2019 18:18

@JBNizet я добавил полную трассировку стека и адаптер

Stephanie Joyce 17.04.2019 18:31

Это подтверждает то, что я сказал. Исключение генерирует адаптер, пытающийся прочитать строку. И поскольку он применяется к полям типа CurrentErrorList, WarningConditionList и DisablingConditionList, ни одно из которых не является строкой, вы получаете исключение. Удалите эту аннотацию, которая не имеет смысла.

JB Nizet 17.04.2019 18:37

Давайте продолжить обсуждение в чате.

Stephanie Joyce 17.04.2019 19:00

Нет, я не болтаю, извините. Если у вас есть другие комментарии, сделайте их здесь.

JB Nizet 17.04.2019 19:17

Когда я удаляю аннотацию, я получаю ошибку в другом смысле: java.lang.IllegalStateException: Ожидается BEGIN_OBJECT, но это STRING java.lang.IllegalStateException: Ожидается BEGIN_OBJECT, но это STRING JsonTree‌​Reader.java:139) com.google.gson.internal.bind.JsonTreeReader.beginObject(Jso‌​nTreeReader.java:70) com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$A‌​dapter.read(Reflecti‌​ veTypeAdapterFactory‌​.java:189) com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1‌​.read(ReflectiveType‌​AdapterFactory.java:‌​103)

Stephanie Joyce 17.04.2019 19:18

Это связано с тем, что поле disablingConditionList в DISABLING_CONDITION_LIST имеет тип DisablingConditionList в вашей модели Java, но является строкой в ​​JSON.

JB Nizet 17.04.2019 19:20

Поскольку в этом случае он пуст, это может быть список как warningConditionList

Stephanie Joyce 17.04.2019 19:29

Затем используйте null вместо пустой строки в вашем JSON. Кстати, когда вы называете «список», это вовсе не список. Это объект.

JB Nizet 17.04.2019 20:35

Можете ли вы показать, как вы создаете экземпляр gson?

Fred 18.04.2019 09:01

@Fred Gson gson = new GsonBuilder().create();

Stephanie Joyce 18.04.2019 09:55

подождите... куда вы тогда добавляете адаптер типа?

Fred 18.04.2019 09:58

@ Фред, я не понимаю, что ты имеешь в виду? я показал, где был добавлен адаптер

Stephanie Joyce 18.04.2019 10:07

о, извините, я не знал, что у вас есть аннотации. Хорошо, позвольте мне проверить пару вещей и посмотреть, могу ли я помочь.

Fred 18.04.2019 10:09

Итак, вы пытаетесь десериализовать объект — WarningConditionList — как строку, и это не работает. Вот что говорит вам ошибка. Мне трудно понять, какова конечная цель? Вы хотите просто десериализовать пустые строки как нулевые? Может ли json быть как { "WARNING_CONDITION_LIST": ""}?

Fred 18.04.2019 10:57

для WarningConditionList я хочу десериализовать его в значение Null, если оно равно " ", или получить объект списка, если он не нулевой

Stephanie Joyce 18.04.2019 10:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
21
2 595
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, из разговора в комментариях я понял, что вы хотите иметь возможность десериализовать оба этих случая:

{
  "WARNING_CONDITION_LIST": {
      "warningConditionList": {"warningCondition":"BLACK_POSTAL_INK_WF_COND"}
  },
  ...
}

а также

{
  "WARNING_CONDITION_LIST": ""
  ...
}

В первом сценарии вам нужен объект, а во втором — null.

Первое, что я заметил, это то, что у вас есть аннотация @JsonAdapter не в том месте. На самом деле он должен быть в поле WARNING_CONDITION_LIST. Что-то вроде этого:

public class MS1SystemStatusResponse {
  // ...
  @SerializedName("WARNING_CONDITION_LIST")
  @JsonAdapter(EmptyStringAsNullTypeAdapter.class)
  WARNING_CONDITION_LIST warningConditionListMy;
  // ...
}

Однако это само по себе не решит вашу проблему. Проблема внутри EmptyStringAsNullTypeAdapter. Он ожидает, что поле будет просто строкой, и не обрабатывает случай, когда оно может быть объектом. Для этого мы можем написать следующий адаптер:

public class EmptyStringAsEmptyWarningConditionlTypeAdapter extends TypeAdapter<WARNING_CONDITION_LIST> {

  @Override
  public void write(JsonWriter out, WARNING_CONDITION_LIST value) throws IOException {
    out.beginObject();
    out.name("warningConditionList");
    out.value(value.warningConditionList.warningCondition);
    out.endObject();
  }

  @Override
  public WARNING_CONDITION_LIST read(JsonReader in) throws IOException {
    WARNING_CONDITION_LIST result = new WARNING_CONDITION_LIST();
    result.warningConditionList =  new WarningConditionList();
    result.warningConditionList.warningCondition = "";

    if (in.peek() == JsonToken.BEGIN_OBJECT) {
        in.beginObject();
        in.nextName();
        in.beginObject();
        in.nextName();
        result.warningConditionList.warningCondition = in.nextString();
        in.endObject();
        in.endObject();
    } else {
        in.nextString();
        return null;
    }
    return result;
  }
}

По сути, он проверит, есть ли у вас строка или объект, и вернет null или объект соответственно.

Это работает только для этих двух случаев, которые я показал вам с помощью json, и этого должно быть достаточно, чтобы помочь вам разобраться с остальными.

Вероятно, вы столкнетесь с похожей проблемой с CurrentErrorList.

Спасибо, я попробую это, я создам 2 других адаптера, похожих на этот, и я посмотрю, работает ли он.

Stephanie Joyce 18.04.2019 14:25

Для этого ввода: {"WARNING_CONDITION_LIST":{"warningConditionList":""},"DISAB‌​LING_CONDITION_LIST"‌​:{"disablingConditio‌​nList":""},"CurrentE‌​rrorList":"","LockSt‌​ate ":"lockspend","Sy‌​stemReadyState":true‌​} У меня ошибка: in.nextName(): java.lang.IllegalStateException: Ожидалось BEGIN_OBJECT, но было STRING

Stephanie Joyce 18.04.2019 15:21

да, я объяснил в своем ответе, что это работает только для двух jsons, которые у меня есть в ответе, и не будет работать ни для чего другого. Это объяснение того, как можно использовать адаптер типа. Мне не совсем понятно, чего вы хотите добиться, но если вы хотите сделать warningConditionList нулевым, когда это пустая строка, просто переместите адаптер типа на один уровень вглубь и адаптируйте код.

Fred 18.04.2019 15:36

Я обновил его таким образом, и он работает, большое спасибо if (in.peek() == JsonToken.BEGIN_OBJECT) { in.beginObject(); in.следующееИмя(); result.getDisablingConditionList().setDisablingCondition(in.‌​nextString()); in.конечный объект(); } else { result.getDisablingConditionList().setDisablingCondition(in‌​.nextString()); }

Stephanie Joyce 19.04.2019 10:05

Другие вопросы по теме