无法在Java Servlet中反序列化JSON

我的端点无法理解传入的JSON。

这是端点:

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(); } 

我使用Postman发布包含“platform”的键/值的JSON,标题为: Content-Type as application/json

但是我得到了这个exception: com.owlike.genson.JsonBindingException: Could not deserialize to type class org.json.JSONObject

看起来问题与: Illegal character at row 0 and column 1 expected { but read '-' !

但我很确定Postman应该发送有效的JSON ……

这里有更多的堆栈跟踪:

 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 

这可能不是一个理想的解决方案,但我认为它可以工作。

希望你已经拥有Jackson JSON依赖…

你可以在这里找到它: http : //mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core

我会尝试以下代码:

 @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(); } 

请注意,我要求您的WS Framework将JSON作为String传递给我,并自己处理它。 也许它不理想,但应该工作。

干杯!

我不知道你使用的是哪个JSON Serializer,但最有可能是Jettison或Jackson 。 据我所知,他们不支持直接转换org.json.JSONObject的实例。 更常见的方法是简单地使用自定义Java Bean:

 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()); ... } 

如果您使用Jettison, 则应使用@XmlRootElement注释Foo

如果您不想为您期望的每个实体创建自定义Bean,可以使用ObjectMapString作为参数并自行序列化:

 @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")); ... } 

最后的解决方案是实现一个处理JSONObject的MessageBodyReader 。 简单的例子:

 @Provider public class JsonObjectReader implements MessageBodyReader { @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 type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws IOException, WebApplicationException { return new JSONObject(IOUtils.toString(entityStream)); } }