客户端发送的请求语法不正确()+Spring,RESTClient。

8

我正在使用Spring MVC处理JSON对象。当我尝试从RESTClient发送JSON对象时,我遇到了以下问题:

HTTP状态码400 - 客户端发送的请求在语法上不正确 ()。

这是我的控制器:

ObjectMapper mapper=new ObjectMapper();
@RequestMapping(value = "/addTask", method = RequestMethod.GET)
       public ModelAndView addTask(@RequestParam("json") String json) throws JsonParseException, JsonMappingException, IOException 
       {
          System.out.println("Json object from REST : "+json);
          Task task=(Task) mapper.readValue(json, Task);
          service.addService(task);
          return new ModelAndView("Result");
       }

我的请求URL: http://localhost:8080/Prime/addTask

我的JSON对象:

{"taskName":"nothing","taskId":1234,"taskDesc":"nothing doing"}

我还尝试在RESTClient中指定 "Content-Type: application/json",但仍然收到相同的错误消息。


1
我不确定Spring的工作原理,但如果您的请求方法是GET,那么您的请求URL不应该是http://localhost:8080/Prime/addTask?json=%7B%22taskName%22%3A%22nothing%22%2C%22taskId%22%3A1234%2C%22taskDesc%22%3A%22nothing%20doing%22%7D,并且应该将json参数发送到查询字符串中吗? - Tanzeel Kazi
我也尝试将JSON字符串添加到请求URL中,但仍然显示相同的错误。 - Chandrasekar
你可以使用像 Fiddler(http://www.fiddler2.com/fiddler2/version.asp)这样的工具来检查请求。同时将其发布在问题中,以便其他人可以查看。 - Tanzeel Kazi
3个回答

16

最近在使用JSON字符串作为请求体时,我遇到了与你类似的情况。我的Spring设置也非常相似。不过,在我的情况下,我没有指定一个字符串参数并自己进行反序列化,而是让Spring来处理:

   @RequestMapping(value = "/myService/{id}", method = RequestMethod.POST)
   @ResponseBody
   public void myService(@PathVariable(value = "id") Long id, @RequestBody MyJsonValueObject request) {
   ..
   }

我遇到了一个HTTP错误400的问题,错误信息是"The request sent by the client was syntactically incorrect"。后来我意识到@RequestBody MyJsonValueObject没有默认构造函数,导致反序列化出现问题。虽然问题表现形式如此,但经过这个发现,我解决了这个问题。

所以如果你正在使用POST和对象,并且出现类似的错误,请确保你有一个默认的构造函数!添加一些JUnit测试,确保你可以反序列化该对象。

注意:我并不是说这是你遇到这个错误的唯一原因。原始案例仅使用了字符串(它确实有一个默认构造函数!),所以情况有所不同。但在这两种情况下,请求URI似乎已经映射到正确的方法,但从HTTP请求中提取参数时出现了问题。


这就是我的情况了。谢谢。 - korro
也解决了我的问题。谢谢! - Jonas Geiregat
为什么我们必须在POST中有默认构造函数? - Xelian

3
请尝试以下操作:

更改

@RequestParam("json") String json

To

 @RequestBody Task task

如果您对POST方法不感兴趣,可以尝试以下方法。将您的控制器方法从以下内容更改:
@RequestMapping(value = "/addTask", method = RequestMethod.GET)
   public ModelAndView addTask(@RequestParam("json") String json)

to

@RequestMapping(value = "/addTask/{taskName}/{taskId}/{taskDesc}", method = RequestMethod.GET)
   public ModelAndView addTask(@RequestParam("taskName") String taskName,
@RequestParam("taskId") String taskId,@RequestParam("taskDesc") String taskDesc)

并将您的URL更改为

http://localhost:8080/Prime/addTask/mytask/233/testDesc

谢谢您的回复。我尝试了但没有用。另外@RequestBody是用于POST方法的,而我正在使用GET方法。 - Chandrasekar
@Chandrasekar 我认为你不能在GET方法中发送对象。 - Kris

0

我的问题是由于@RequestBody对象的错误映射导致的。

我的请求体看起来像这样

{data: ["1","2","3"]}

我在我的控制器中有以下代码

@RequestMapping(value = "/mentee", method = RequestMethod.POST)
public @ResponseBody boolean updateData(@RequestBody List<Integer> objDTO, HttpSession session) {
        ...
    }

这个给了我HTTP 400错误,因为Spring不知道如何将我的Json数据绑定到一个列表中。

我将RequestBody对象更改为以下内容:

@RequestMapping(value = "/mentee", method = RequestMethod.POST)
public @ResponseBody boolean updateData(@RequestBody ObjectiveDto objDTO, HttpSession session) {
        ...
    }

并将ObjectiveDto定义如下

@ToString
public class ObjectiveDto {

    @Getter @Setter
    private List<Integer> data;

}

这解决了HTTP 400错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接