Unable to deserialize JSON in Java Servlet

My endpoint cannot understand the incoming JSON.

Here's the end point:

import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.hibernate.Query; import org.hibernate.Session; import org.json.JSONObject; ... @POST @Path("/{department}/{team}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response handleJSON(JSONObject json , @PathParam("department") String department, @PathParam("team") String team){ MyObj myObj = new MyObj(); myObj.setDepartment(department); myObj.setTeam(team); myObj.setPlatform(json.optString("platform")); saveObj(myObj); return Response.ok(true).build(); } 

I am sending a JSON containing the key / value for the "platform" using Postman, with the header: Content-Type as application/json

But I get this exception: com.owlike.genson.JsonBindingException: Could not deserialize to type class org.json.JSONObject

Looks like the problem is related to: Illegal character at row 0 and column 1 expected { but read '-' !

But I'm sure that the postman should send valid JSON ...

Here's more from stacktrace:

 09-Jul-2014 10:30:00.017 SEVERE [http-nio-8080-exec-4] com.sun.jersey.spi.container.ContainerResponse.logException Mapped exception to response: 500 (Internal Server Error) javax.ws.rs.WebApplicationException: com.owlike.genson.JsonBindingException: Could not deserialize to type class org.json.JSONObject at com.owlike.genson.ext.jaxrs.GensonJsonConverter.readFrom(GensonJsonConverter.java:127) at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:474) at com.sun.jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider$EntityInjectable.getValue(EntityParamDispatchProvider.java:123) at com.sun.jersey.server.impl.inject.InjectableValuesProvider.getInjectableValues(InjectableValuesProvider.java:46) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$EntityParamInInvoker.getParams(AbstractResourceMethodDispatchProvider.java:153) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:203) at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699) at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:744) Caused by: com.owlike.genson.JsonBindingException: Could not deserialize to type class org.json.JSONObject at com.owlike.genson.Genson.deserialize(Genson.java:391) at com.owlike.genson.ext.jaxrs.GensonJsonConverter.readFrom(GensonJsonConverter.java:125) ... 41 more Caused by: com.owlike.genson.stream.JsonStreamException: Illegal character at row 0 and column 1 expected { but read '-' ! at com.owlike.genson.stream.JsonReader.newWrongTokenException(JsonReader.java:949) at com.owlike.genson.stream.JsonReader.begin(JsonReader.java:425) at com.owlike.genson.stream.JsonReader.beginObject(JsonReader.java:157) at com.owlike.genson.reflect.BeanDescriptor.deserialize(BeanDescriptor.java:101) at com.owlike.genson.reflect.BeanDescriptor.deserialize(BeanDescriptor.java:90) at com.owlike.genson.convert.BeanViewConverter.deserialize(BeanViewConverter.java:102) at com.owlike.genson.convert.NullConverter$NullConverterWrapper.deserialize(NullConverter.java:56) at com.owlike.genson.Genson.deserialize(Genson.java:389) ... 42 more 
+6
source share
2 answers

This may not be the perfect solution, but I think it might work.

Hope you already have a Jackson JSON dependency ...

you can find it here: http://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core

I would try the following code:

 @POST @Path("/{department}/{team}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response handleJSON(String json, @PathParam("department") String department, @PathParam("team") String team){ ObjectMapper mapper = new ObjectMapper(); JsonNode node = mapper.readValue(json, JsonNode.class); MyObj myObj = new MyObj(); myObj.setDepartment(department); myObj.setTeam(team); if (node.get("platform") != null) { myObj.setPlatform(node.get("platform").textValue()); } saveObj(myObj); return Response.ok(true).build(); } 

Please note that I am asking your WS Framework to simply pass me the JSON as a String and just process it yourself. It may not be perfect, but should work.

Hooray!

+3
source

I don’t know which JSON Serializer you are using, but most likely it will be Jettison or Jackson . As far as I know, they do not support conversion of an org.json.JSONObject instance directly. A more common way is to simply use custom Java Beans:

 public class Foo implements Serializable { private String platform; // getters + setters } @POST @Path("/{department}/{team}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response handleJson(Foo foo, @PathParam("department") String department, @PathParam("team") String team) { ... myObj.setPlatform(foo.getPlatform()); ... } 

Foo should be annotated @XmlRootElement if you are using Jettison.

If you do not want to create a custom Bean for each object that you expect, you can use Object , Map or String as a parameter and serialize it yourself:

 @POST @Path("/{department}/{team}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response handleJson(String json, @PathParam("department") String department, @PathParam("team") String team) { ... JSONObject jsonObject = new JSONObject(json); myObj.setPlatform(json.optString("platform")); ... } 

The latter solution implements MessageBodyReader , which handles a JSONObject . A simple example:

 @Provider public class JsonObjectReader implements MessageBodyReader<JSONObject> { @Override public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type == JSONObject.class && MediaType.APPLICATION_JSON_TYPE.equals(mediaType); } @Override public JSONObject readFrom(Class<JSONObject> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException { return new JSONObject(IOUtils.toString(entityStream)); } } 
+3
source

Source: https://habr.com/ru/post/971988/


All Articles