Jpa Could Not Read Document: Can Not Construct Instance of Java.lang.enum:
Невозможно десериализовать экземпляр java.util.ArrayList из токена START_OBJECT
Я пытаюсь опубликовать Listпользовательские объекты. Мой JSON в теле запроса таков:
{ "collection" : [ { "name" : "Test order1" , "detail" : "ahk ks" }, { "proper name" : "Test order2" , "detail" : "Fisteku" } ] } Код на стороне сервера, обрабатывающий запрос:
import java . util . Drove ; import javax . ws . rs . Consumes ; import javax . ws . rs . Postal service ; import javax . ws . rs . Path ; import javax . ws . rs . Produces ; import javax . ws . rs . cadre . MediaType ; import javax . ws . rs . core . Response ; @Path ( value = "/rest/corder" ) public class COrderRestService { @POST @Produces ( MediaType . APPLICATION_JSON ) @Consumes ( MediaType . APPLICATION_JSON ) public Response postOrder ( Collection < COrder > orders ) { StringBuilder stringBuilder = new StringBuilder (); for ( COrder c : orders ) { stringBuilder . append ( c . toString ()); } System . out . println ( stringBuilder ); return Response . ok ( stringBuilder , MediaType . APPLICATION_JSON ). build (); } } Сущность COrder:
import javax . xml . bind . annotation . XmlRootElement ; @XmlRootElement public class COrder { String name ; Cord detail ; @Override public String toString () { return "COrder [name=" + name + ", detail=" + detail + ", getClass()=" + getClass () + ", hashCode()=" + hashCode () + ", toString()=" + super . toString () + "]" ; } } Но возникает исключение:
Astringent : Failed executing Post / rest / corder org . jboss . resteasy . spi . ReaderException : org . codehaus . jackson . map . JsonMappingException : Can not deserialize instance of java . util . ArrayList out of START_OBJECT token at [ Source : org . apache . catalina . connector . CoyoteInputStream@6de8c535 ; line : 1 , column : 1 ] at org . jboss . resteasy . core . MessageBodyParameterInjector . inject ( MessageBodyParameterInjector . java : 183 ) at org . jboss . resteasy . core . MethodInjectorImpl . injectArguments ( MethodInjectorImpl . java : 88 ) at org . jboss . resteasy . cadre . MethodInjectorImpl . invoke ( MethodInjectorImpl . java : 111 ) at org . jboss . resteasy . core . ResourceMethodInvoker . invokeOnTarget ( ResourceMethodInvoker . java : 280 ) at org . jboss . resteasy . cadre . ResourceMethodInvoker . invoke ( ResourceMethodInvoker . coffee : 234 ) at org . jboss . resteasy . cadre . ResourceMethodInvoker . invoke ( ResourceMethodInvoker . java : 221 ) at org . jboss . resteasy . core . SynchronousDispatcher . invoke ( SynchronousDispatcher . java : 356 ) at org . jboss . resteasy . cadre . SynchronousDispatcher . invoke ( SynchronousDispatcher . java : 179 ) at org . jboss . resteasy . plugins . server . servlet . ServletContainerDispatcher . service ( ServletContainerDispatcher . java : 220 ) at org . jboss . resteasy . plugins . server . servlet . HttpServletDispatcher . service ( HttpServletDispatcher . java : 56 ) at org . jboss . resteasy . plugins . server . servlet . HttpServletDispatcher . service ( HttpServletDispatcher . java : 51 ) at javax . servlet . http . HttpServlet . service ( HttpServlet . java : 728 ) at org . apache . catalina . core . ApplicationFilterChain . internalDoFilter ( ApplicationFilterChain . java : 305 ) at org . apache . catalina . cadre . ApplicationFilterChain . doFilter ( ApplicationFilterChain . java : 210 ) at org . apache . tomcat . websocket . server . WsFilter . doFilter ( WsFilter . java : 51 ) at org . apache . catalina . core . ApplicationFilterChain . internalDoFilter ( ApplicationFilterChain . java : 243 ) at org . apache . catalina . cadre . ApplicationFilterChain . doFilter ( ApplicationFilterChain . java : 210 ) at org . apache . catalina . core . StandardWrapperValve . invoke ( StandardWrapperValve . java : 222 ) at org . apache . catalina . core . StandardContextValve . invoke ( StandardContextValve . java : 123 ) at org . apache . catalina . authenticator . AuthenticatorBase . invoke ( AuthenticatorBase . java : 502 ) at org . apache . catalina . core . StandardHostValve . invoke ( StandardHostValve . coffee : 171 ) at org . apache . catalina . valves . ErrorReportValve . invoke ( ErrorReportValve . java : 100 ) at org . apache . catalina . valves . AccessLogValve . invoke ( AccessLogValve . java : 953 ) at org . apache . catalina . cadre . StandardEngineValve . invoke ( StandardEngineValve . java : 118 ) at org . apache . catalina . connector . CoyoteAdapter . service ( CoyoteAdapter . coffee : 408 ) at org . apache . coyote . http11 . AbstractHttp11Processor . procedure ( AbstractHttp11Processor . java : 1041 ) at org . apache . coyote . AbstractProtocol$AbstractConnectionHandler . process ( AbstractProtocol . java : 603 ) at org . apache . tomcat . util . internet . JIoEndpoint$SocketProcessor . run ( JIoEndpoint . java : 312 ) at java . util . concurrent . ThreadPoolExecutor . runWorker ( ThreadPoolExecutor . coffee : 1145 ) at java . util . concurrent . ThreadPoolExecutor$Worker . run ( ThreadPoolExecutor . java : 615 ) at java . lang . Thread . run ( Thread . coffee : 724 ) Ответы:
Проблема в JSON - по умолчанию он не может быть десериализован в Collectionмассив, потому что на самом деле это не массив JSON - это будет выглядеть так:
[ { "name" : "Test order1" , "detail" : "ahk ks" }, { "proper noun" : "Test order2" , "detail" : "Fisteku" } ] Поскольку вы не контролируете точный процесс десериализации (это делает RestEasy), первым вариантом было бы просто ввести JSON как a, Stringа затем взять под контроль процесс десериализации:
Collection < COrder > readValues = new ObjectMapper (). readValue ( jsonAsString , new TypeReference < Drove < COrder >>() { } ); Вы бы немного потеряли удобство, не делая этого самостоятельно, но вы легко решите проблему.
Другой вариант - если вы не можете изменить JSON - было бы создать оболочку, соответствующую структуре вашего ввода JSON, и использовать ее вместо Drove<COrder>.
Надеюсь это поможет.
Вместо документа JSON вы можете обновить объект ObjectMapper, как показано ниже:
ObjectMapper mapper = new ObjectMapper (); mapper . configure ( DeserializationFeature . ACCEPT_SINGLE_VALUE_AS_ARRAY , true ); Это будет работать:
Проблема может возникнуть, когда вы пытаетесь прочитать список с одним элементом как JsonArray, а не JsonNode, или наоборот.
Поскольку вы не можете точно знать, содержит ли возвращаемый список один элемент (поэтому json выглядит так {...} ) или несколько элементов (а json выглядит так [{...}, {... }] ) - вам нужно будет проверить во время выполнения тип элемента.
Должно получиться так:
(Примечание: в этом примере кода я использую com.fasterxml.jackson)
Cord jsonStr = response . readEntity ( Cord . class ); ObjectMapper mapper = new ObjectMapper (); JsonNode rootNode = mapper . readTree ( jsonStr ); // Get-go by checking if this is a listing -> the order is important here: if ( rootNode instanceof ArrayNode ) { // Read the json as a list: myObjClass [] objects = mapper . readValue ( rootNode . toString (), myObjClass []. class ); ... } else if ( rootNode instanceof JsonNode ) { // Read the json equally a single object: myObjClass object = mapper . readValue ( rootNode . toString (), myObjClass . grade ); ... } else { ... } В связи с ответом Евгения вы можете решить этот конкретный случай, создав объект POJO-оболочки, который содержит в Drove<COrder>качестве своей переменной-члена. Это правильно поможет Джексону поместить фактические Droveданные в переменную-член POJO и создать JSON, который вы ищете в запросе API.
Пример:
public grade ApiRequest { @JsonProperty ( "collection" ) private Drove < COrder > collection ; // getters } Затем установите тип параметра COrderRestService.postOrder()как вашу новую ApiRequestоболочку POJO вместо Collection<COrder>.
В эти дни я столкнулся с той же проблемой, и, возможно, некоторые подробности могут быть полезны кому-то другому.
Я искал некоторые рекомендации по безопасности для Rest API и преодолел очень интригующую проблему с массивами json. Проверьте ссылку для получения подробной информации, но в основном вы должны заключить их в объект, как мы уже видели в этом вопросе публикации.
Итак, вместо:
[ { "name" : "order1" }, { "proper noun" : "order2" } ] Желательно, чтобы мы всегда делали:
{ "data" : [ { "name" : "order1" }, { "proper noun" : "order2" } ] } Это довольно просто, когда вы выполняете GET , но может вызвать некоторые проблемы, если вместо этого вы попытаетесь выполнить POST / PUT тот же самый json.
В моем случае у меня было более одного Become, который был списком, и более одного POST / PUT , которые получали бы один и тот же json.
В итоге я использовал очень простой объект Wrapper для списка :
public class Wrapper < T > { private List < T > information ; public Wrapper () {} public Wrapper ( List < T > information ) { this . data = data ; } public List < T > getData () { return data ; } public void setData ( Listing < T > data ) { this . data = data ; } } Сериализация моих списков была произведена с помощью @ControllerAdvice :
@ControllerAdvice public class JSONResponseWrapper implements ResponseBodyAdvice < Object > { @Override public boolean supports ( MethodParameter returnType , Course <? extends HttpMessageConverter <?>> converterType ) { render true ; } @Override @SuppressWarnings ( "unchecked" ) public Object beforeBodyWrite ( Object body , MethodParameter returnType , MediaType selectedContentType , Course <? extends HttpMessageConverter <?>> selectedConverterType , ServerHttpRequest request , ServerHttpResponse response ) { if ( body instanceof Listing ) { return new Wrapper <>(( List < Object >) body ); } else if ( body instanceof Map ) { render Collections . singletonMap ( "information" , body ); } return body ; } } Итак, все списки и карты были обернуты поверх объекта данных, как показано ниже:
{ "data" : [ {...} ] } Десериализация по-прежнему была по умолчанию, просто использовался объект de Wrapper :
@PostMapping ( "/resource" ) public ResponseEntity < Void > setResources ( @RequestBody Wrapper < ResourceDTO > wrappedResources ) { List < ResourceDTO > resources = wrappedResources . getData (); // your code here render ResponseEntity . ok () . build (); } Вот и все! Надеюсь, это кому-то поможет.
Примечание: протестировано с помощью SpringBoot one.5.5.RELEASE .
У меня была эта проблема с Balance API, созданным с использованием Jump framework. Добавление аннотации @ResponseBody (чтобы сделать ответ JSON) разрешило это.
Обычно мы сталкиваемся с этой проблемой, когда возникает проблема сопоставления узла JSON с узлом Java-объекта. Я столкнулся с той же проблемой, потому что в чванстве узел был определен как массив типа, а объект JSON имел только один элемент, поэтому система испытывала трудности с отображением одного списка элементов в массив.
В Swagger элемент был определен как
Exam : "type" : "array" , "minItems" : ane , "items" : { "$ref" : "#/definitions/TestNew" } Хотя должно быть
Test : "$ref" : "#/definitions/TestNew" И TestNewдолжен быть типа array
Dto response = softConvertValue ( jsonData , Dto . class ); public static < T > T softConvertValue ( Object fromValue , Class < T > toValueType ) { ObjectMapper objMapper = new ObjectMapper (); return objMapper . configure ( DeserializationFeature . FAIL_ON_UNKNOWN_PROPERTIES , imitation ) . convertValue ( fromValue , toValueType ); } Та же проблема:
com . fasterxml . jackson . databind . exc . MismatchedInputException : Cannot deserialize instance of ` java . util . UUID ` out of START_OBJECT token Причиной этого было следующее:
ResponseEntity < UUID > response = restTemplate . postForEntity ( "/case/" , zilch , UUID . class ); В моем тесте я намеренно установил запрос как null (без Mail содержимого). Как упоминалось ранее, причина для OP была та же, потому что запрос не содержал действительного JSON, поэтому он не мог быть автоматически идентифицирован как запрос application / json, что было ограничением на сервере ( consumes = "application/json"). Действительный запрос JSON будет. Что исправлено, так это явное заполнение объекта нулевым телом и заголовками json.
HttpHeaders headers = new HttpHeaders (); headers . setContentType ( MediaType . APPLICATION_JSON ); HttpEntity request = new HttpEntity <>( null , headers ); ResponseEntity < UUID > response = restTemplate . postForEntity ( "/case/" , request , UUID . class ); В моем случае ошибка отображалась, потому что, когда я читал свой файл JSON с использованием библиотеки Джексона, мой файл JSON содержал только 1 объект. Следовательно, он начинается с "{" и заканчивается "}". Но, читая его и сохраняя в переменной, я сохранял его в объекте Assortment (как и в моем случае, могло быть более 1 объекта).
Следовательно, я добавил «[» в начале и «]» в конец моего файла JSON, чтобы преобразовать его в массив объектов, и он работал отлично без каких-либо ошибок.
Как упоминалось выше, проблему решило бы следующее: mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
Однако в моем случае провайдер выполнил сериализацию [0..ane] или [0 .. *] скорее как ошибку, и я не мог принудительно исправить. С другой стороны, он не хотел влиять на мой строгий картограф во всех других случаях, которые требуют строгой проверки.
Итак, я сделал ГЛАВНЫЙ ХАК Jackson (который не следует копировать вообще ;-)), особенно потому, что у моего SingleOrListElement было только несколько свойств, которые нужно исправить:
@JsonProperty ( value = "SingleOrListElement" , access = JsonProperty . Access . WRITE_ONLY ) private Object singleOrListElement ; public List < SingleOrListElement > patch ( Object singleOrListElement ) { if ( singleOrListElement instanceof List ) { return ( ArrayList < SingleOrListElement >) singleOrListElement ; } else { LinkedHashMap map = ( LinkedHashMap ) singleOrListElement ; return Collections . singletonList ( SingletonList . builder () . property1 (( String ) map . get ( "p1" )) . property2 (( Integer ) map . go ( "p2" )) . build ()); } @JsonFormat (with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) частный список заказов <COrder>;
Jpa Could Not Read Document: Can Not Construct Instance of Java.lang.enum:
Source: https://qastack.ru/programming/20837856/can-not-deserialize-instance-of-java-util-arraylist-out-of-start-object-token
0 Response to "Jpa Could Not Read Document: Can Not Construct Instance of Java.lang.enum:"
Post a Comment