#java #json #parsing #gson
#java #json #синтаксический анализ #gson
Вопрос:
Я прочитал много ответов об этой ошибке, и я не нахожу решения для своего, возможно, объект класса не тот же
Моя ошибка :
com.google.gson.Исключение JsonSyntaxException: java.lang.Исключение IllegalStateException: ожидаемая СТРОКА, но была 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 и не устанавливаю для краткости код) :
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 resu<
}
}
Я оборачиваюсь с 1 недели: (
Комментарии:
1. что выводит mS1SystemStatusJsonObject?
2. Можете ли вы попробовать заменить
"SystemReadyState":true
на"SystemReadyState":"true"
?3. Нет, я не могу заменить это, это влияет на многое в программе, у меня нет ошибки, когда WARNING_CONDITION_LIST пуст
4. При запросе об исключении всегда публикуйте полную трассировку стека исключений исключения.
5. Вы используете адаптер с именем EmptyStringAsNullTypeAdapter для свойств, которые не являются строками. Вероятно, это причина: он ожидает строку, но получает объект. Трассировка стека, вероятно, подтвердит это.
Ответ №1:
Хорошо, итак, из разговора в комментариях я понял, что вы хотите иметь возможность десериализовать оба этих случая:
{
"WARNING_CONDITION_LIST": {
"warningConditionList": {"warningCondition":"BLACK_POSTAL_INK_WF_COND"}
},
...
}
и
{
"WARNING_CONDITION_LIST": ""
...
}
В первом сценарии вам нужен объект, а во 2-м сценарии вы хотите 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 resu<
}
}
По сути, он проверит, есть ли у вас строка или объект, и вернет null
или объект соответственно.
Это работает только для этих 2 случаев, которые я показал вам с помощью json, и должно быть достаточно, чтобы помочь вам разобраться в остальном.
Вероятно, вы столкнетесь с аналогичной проблемой с CurrentErrorList
.
Комментарии:
1. Спасибо, я попробую это, я создам 2 других адаптера, похожих на этот, и я посмотрю, работает ли он
2. Для этого ввода: {«WARNING_CONDITION_LIST»:{«warningConditionList»:»»},»DISABLING_CONDITION_LIST»:{«disablingConditionList»:»»},»CurrentErrorList»:»»,»LockState»:»lockspend»,»SystemReadyState»:true} У меня ошибка: in.nextName() : java.lang. Исключение IllegalStateException: ожидаемый BEGIN_OBJECT, но был STRING
3. да, я объяснил в своем ответе, что это работает только для 2 json, которые у меня есть в ответе, и это не будет работать ни для чего другого. Это объяснение того, как можно использовать адаптер типа. Мне не совсем понятно, чего вы хотите достичь, но если вы хотите сделать
warningConditionList
null, когда это пустая строка, тогда просто переместите адаптер типа на один уровень глубже и адаптируйте код.4. Я обновил ее следующим образом, и она работает, большое вам спасибо, если (in.peek() == JsonToken . BEGIN_OBJECT) { в.beginObject(); в.nextName(); результат.getDisablingConditionList().setDisablingCondition(в.nextString()); в.endObject(); } остальное { результат.getDisablingConditionList().setDisablingCondition(в.nextString()); }