Я прочитал много ответов об этой ошибке, и я не нашел решения для себя, возможно, объект класса не тот
Моя ошибка:
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 недели :(
Можете попробовать заменить "SystemReadyState":true на "SystemReadyState":"true"?
Нет, я не могу заменить это, это влияет на многое в программе, у меня нет ошибки, когда СПИСОК ПРЕДУПРЕЖДЕНИЙ СОСТОЯНИЯ пуст.
При запросе об исключении всегда публикует полную трассировку стека исключения.
Вы используете адаптер с именем EmptyStringAsNullTypeAdapter для свойств, которые не являются строками. Вероятно, причина в этом: он ожидает строку, а получает объект. Трассировка стека, вероятно, подтвердит это.
я добавил полную трассировку стека
@JBNizet я добавил полную трассировку стека и адаптер
Это подтверждает то, что я сказал. Исключение генерирует адаптер, пытающийся прочитать строку. И поскольку он применяется к полям типа CurrentErrorList, WarningConditionList и DisablingConditionList, ни одно из которых не является строкой, вы получаете исключение. Удалите эту аннотацию, которая не имеет смысла.
Давайте продолжить обсуждение в чате.
Нет, я не болтаю, извините. Если у вас есть другие комментарии, сделайте их здесь.
Когда я удаляю аннотацию, я получаю ошибку в другом смысле: java.lang.IllegalStateException: Ожидается BEGIN_OBJECT, но это STRING java.lang.IllegalStateException: Ожидается BEGIN_OBJECT, но это STRING JsonTreeReader.java:139) com.google.gson.internal.bind.JsonTreeReader.beginObject(JsonTreeReader.java:70) com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(Reflecti veTypeAdapterFactory.java:189) com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:103)
Это связано с тем, что поле disablingConditionList в DISABLING_CONDITION_LIST имеет тип DisablingConditionList в вашей модели Java, но является строкой в JSON.
Поскольку в этом случае он пуст, это может быть список как warningConditionList
Затем используйте null вместо пустой строки в вашем JSON. Кстати, когда вы называете «список», это вовсе не список. Это объект.
Можете ли вы показать, как вы создаете экземпляр gson?
@Fred Gson gson = new GsonBuilder().create();
подождите... куда вы тогда добавляете адаптер типа?
@ Фред, я не понимаю, что ты имеешь в виду? я показал, где был добавлен адаптер
о, извините, я не знал, что у вас есть аннотации. Хорошо, позвольте мне проверить пару вещей и посмотреть, могу ли я помочь.
Итак, вы пытаетесь десериализовать объект — WarningConditionList — как строку, и это не работает. Вот что говорит вам ошибка. Мне трудно понять, какова конечная цель? Вы хотите просто десериализовать пустые строки как нулевые? Может ли json быть как { "WARNING_CONDITION_LIST": ""}?
для WarningConditionList я хочу десериализовать его в значение Null, если оно равно " ", или получить объект списка, если он не нулевой




Итак, из разговора в комментариях я понял, что вы хотите иметь возможность десериализовать оба этих случая:
{
"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 других адаптера, похожих на этот, и я посмотрю, работает ли он.
Для этого ввода: {"WARNING_CONDITION_LIST":{"warningConditionList":""},"DISABLING_CONDITION_LIST":{"disablingConditionList":""},"CurrentErrorList":"","LockState ":"lockspend","SystemReadyState":true} У меня ошибка: in.nextName(): java.lang.IllegalStateException: Ожидалось BEGIN_OBJECT, но было STRING
да, я объяснил в своем ответе, что это работает только для двух jsons, которые у меня есть в ответе, и не будет работать ни для чего другого. Это объяснение того, как можно использовать адаптер типа. Мне не совсем понятно, чего вы хотите добиться, но если вы хотите сделать warningConditionList нулевым, когда это пустая строка, просто переместите адаптер типа на один уровень вглубь и адаптируйте код.
Я обновил его таким образом, и он работает, большое спасибо if (in.peek() == JsonToken.BEGIN_OBJECT) { in.beginObject(); in.следующееИмя(); result.getDisablingConditionList().setDisablingCondition(in.nextString()); in.конечный объект(); } else { result.getDisablingConditionList().setDisablingCondition(in.nextString()); }
что печатает mS1SystemStatusJsonObject?