为啥这个 Json 不能从 HTTP 请求中解析?

Posted

技术标签:

【中文标题】为啥这个 Json 不能从 HTTP 请求中解析?【英文标题】:Why this Json cannot be resolved from the HTTP request?为什么这个 Json 不能从 HTTP 请求中解析? 【发布时间】:2018-04-15 20:55:44 【问题描述】:

我的代码基于SpringBoot,接收post请求,解析json数据并使用jdbc执行。

public class ETLController 
@Autowired
@Qualifier("ETLService")
private ETLServiceImpl ETLServiceImpl;

@RequestMapping(value = "/sql", method = RequestMethod.POST)
@ResponseBody
/**
 * @param sqlString 
 */    
public String identify(HttpServletRequest request) 

    //String sqlString, int maxRowNum, int maxColumnNum, int maxDuration, long startTime, String killQueryJob, int processResult
    System.out.println("request: "+request) ;
    String requestJson = request.getParameter("parametersJson");
    System.out.println("requestJson: "+requestJson) ;

    //Json parser
    JsonObject object = Json.parse(requestJson).asObject();

    //connection parameters
    String connString = object.get("connString").asString();
    String connUserName = object.get("connUserName").asString();
    String connPassWord = object.get("connPassWord").asString();

    //HQL query parameter
    String sqlString = object.get("sqlString").asString();
    int maxRowNum = object.get("maxRowNum").asInt();
    int maxColumnNum = object.get("maxColumnNum").asInt();
    int maxDuration = object.get("maxDuration").asInt();

    String sqlResult = ETLServiceImpl.executeShellScript(connString, connUserName, connPassWord, sqlString, maxRowNum, maxColumnNum, maxDuration);
    return sqlResult;

curl命令如下:

curl -H "Content-Type: application/json" -X POST  --data  '"sqlString":"select room_id from dim.dim_room","connString":"jdbc:hive2://192.168.7.21:10001/","connUserName":"xxxx","connPassWord":"xxxx","maxRowNum":500,"maxColumnNum":10,"maxDuration":6000' http://192.168.7.24:xxx/etl/sql

但是,当我通过 curl 发送 post 请求时,无法解析参数并且requestJson 始终为空。

为什么会出现这个问题以及如何解决?


堆栈跟踪:

2017-11-03 14:45:32.290 ERROR 181818 --- [nio-9162-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException: string is null] with root cause

java.lang.NullPointerException: string is null
        at com.eclipsesource.json.Json.parse(Json.java:292) ~[minimal-json-0.9.4.jar!/:na]
        at com.lz.web.action.etl.ETLController.identify(ETLController.java:39) ~[classes!/:1.0-SNAPSHOT]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_101]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_101]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]

【问题讨论】:

您应该决定是要发送 POST 请求还是 GET 请求。您的 curl 输入对于 POST 请求是错误的(它不应包含诸如“parametersJson”之类的参数名称,它应该只包含 JSON 内容),并且您的服务器会像需要 GET 请求一样查找参数。 请使用错误堆栈跟踪添加/更新您的问题 Trying to use Spring Boot REST to Read JSON String from POST的可能重复 @Eran 感谢您的回复。该命令一开始不包含参数名称,但不起作用。 @SuperDelta 因为您正在发送 POST 请求,但您的服务器似乎期待 GET 请求。 【参考方案1】:

使用类成员创建一个 Pojo 类,该类成员应与您传递的 JSON 中可用的键相同。

public class ConnectionString

    private String sqlString;
    private String connString;
    private String connUserName;
    private String connPassWord; 
    private Long maxRowNum ;
    private Long maxColumnNum;
    private Long maxDuration;

    //all getters and setters.
  

现在对您的方法 identify() 做一个简单的更改,直接将其作为 Java 对象接收。

试试这个方法定义(见改变的参数)

public String identify(HttpServletRequest request, @RequestBody ConnectionString connectionString)

  //here how receive your data you passed using curl.
   System.out.println(connectionString.getSqlString());

   // this will print the value you passed as a body.

您还需要编辑您传递的 curl 正文 json 数据,例如删除密钥 parametersJson

试试这个

'"sqlString":"select room_id from dim.dim_room","connString":"jdbc:hive2://192.168.7.21:10001/","connUserName":"xxxx","connPassWord":"xxxx","maxRowNum":500,"maxColumnNum":10,"maxDuration":6000'

而不是

'parametersJson='"sqlString":"select room_id from dim.dim_room","connString":"jdbc:hive2://192.168.7.21:10001/","connUserName":"xxxx","connPassWord":"xxxx","maxRowNum":500,"maxColumnNum":10,"maxDuration":6000''

注意 - Spring 会自动将您的 requestbody 数据更改为 JavaObject。 Spring 内部使用jackson-databind jar 类来执行此操作。 :)

【讨论】:

【参考方案2】:

下面可以试试

curl -H "Content-Type: application/json" -X POST  -d  '"sqlString":"select room_id from dim.dim_room","connString":"jdbc:hive2://192.168.7.21:10001/","connUserName":"magic","connPassWord":"w8spDGCJVMG3J2MWio5X","maxRowNum":500,"maxColumnNum":10,"maxDuration":6000' http://192.168.7.24:xxx/etl/sql

【讨论】:

你应该解释你有什么更新以及为什么你认为这会奏效【参考方案3】:

尝试:

public String identify(HttpServletRequest request, @RequestBody String parametersJson)...

【讨论】:

如果您将其作为String 接收,则需要将其转换为Java Object 以执行进一步的任务。谢谢你:) 是的。无论如何,您正在做相同的 JsonObject object = Json.parse(requestJson).asObject();

以上是关于为啥这个 Json 不能从 HTTP 请求中解析?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Javascript 不能从字符串文字中解析这个 JSON 数组?

为啥不能从文件中解析 JSON?

为啥 Python 不能解析这个 JSON 数据? [关闭]

为啥我从这个请求 iOS JSON 得到空响应

目标c从url请求中解析json

Kotlin Android,从 HTTP 请求解析 Json