Java 用弹簧解码车身参数

Java 用弹簧解码车身参数,java,spring,slack,slack-api,spring-rest,Java,Spring,Slack,Slack Api,Spring Rest,我正在为Slack应用程序开发一个带有Spring的RESTAPI后端。我能够从Slack(斜杠命令)接收消息,但无法正确接收组件交互(按钮单击) 报告说: 您的操作URL将接收一个HTTP POST请求,包括一个有效负载主体参数,该参数本身包含一个application/x-www-form-urlencoded JSON字符串 因此,我编写了以下@RestController: @RequestMapping(method = RequestMethod.POST, value = "/ac

我正在为Slack应用程序开发一个带有Spring的RESTAPI后端。我能够从Slack(斜杠命令)接收消息,但无法正确接收组件交互(按钮单击)

报告说:

您的操作URL将接收一个HTTP POST请求,包括一个有效负载主体参数,该参数本身包含一个application/x-www-form-urlencoded JSON字符串

因此,我编写了以下
@RestController

@RequestMapping(method = RequestMethod.POST, value = "/actions", headers = {"content-type=application/x-www-form-urlencoded"})
public ResponseEntity action(@RequestParam("payload") ActionController.Action action) {
    return ResponseEntity.status(HttpStatus.OK).build();
}

@JsonIgnoreProperties(ignoreUnknown = true)
class Action {

    @JsonProperty("type")
    private String type;

    public Action() {}

    public String getType() {
        return type;
    }

}
但是,我得到以下错误:

Failed to convert request element: org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'controllers.ActionController$Action'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'controllers.ActionController$Action': no matching editors or conversion strategy found

这意味着什么,以及如何解析?

您收到一个包含JSON内容的字符串。您不会收到JSON输入,因为
application/x-www-form-urlencoded
用作内容类型,而不是
application/JSON
,如上所述:

您的操作URL将接收HTTP POST请求,包括有效负载 body参数,本身包含一个应用程序/x-www-form-urlencoded JSON字符串

因此,将参数类型更改为
String
,并使用Jackson或任何JSON库将
String
映射到您的
Action
类:

@RequestMapping(method = RequestMethod.POST, value = "/actions", headers = {"content-type=application/x-www-form-urlencoded"})
public ResponseEntity action(@RequestParam("payload") String actionJSON) {
    Action action = objectMapper.readValue(actionJSON, Action.class);  
    return ResponseEntity.status(HttpStatus.OK).build();
}
正如pvpkiran所建议的,如果您可以在POST请求的主体中直接传递JSON字符串,而不是作为参数值传递,那么您可以将
@RequestParam
替换为
@RequestBody

实际上,通过使用
@RequestBody
,请求的主体通过
HttpMessageConverter
来解析方法参数

为了回答您的评论,SpringMVC没有提供一种非常简单的方法来实现您的需求:将字符串JSON映射到您的
Action
类。
但是,如果您确实需要自动化此转换,您有一个冗长的替代方案,如Formatters(重点是我的):

一些带注释的控制器方法参数表示基于字符串的 请求输入 — e、 g.
@RequestParam
@RequestHeader
@PathVariable
@MatrixVariable、
@CookieValue
可能需要进行类型转换,如果 参数声明为字符串以外的内容

对于这种情况,类型转换将根据 配置转换器。默认情况下,简单类型,如int、long、, 支持日期等类型转换可以通过 WebDataBinder,请参阅DataBinder,或通过向 格式化转换服务,请参阅Spring字段格式化。

通过为
Action
类创建格式化程序(
FormatterRegistry
子类),您可以在SpringWeb配置中添加:

并在参数声明中使用它:

public ResponseEntity action(@RequestParam("payload") @Action Action actionJ) 
{...}

为了简单起见,您可以使用下面的代码块@Request主体将有效负载映射到操作类。它还进行验证以确保类型不是空的。@Valid@NotBlank来自javax.validation

    @PostMapping("actions")
public ResponseEntity<?> startApplication(@RequestBody @Valid Action payload) {
    // use your payload here 
    return ResponseEntity.ok('done');
}


class Action {

    @NotBlank
    private String type;

    public Action() {
    }

    public String getType() {
        return type;
    }
}
@PostMapping(“操作”)
公共响应启动应用程序(@RequestBody@Valid Action-payload){
//在这里使用有效载荷
返回ResponseEntity.ok('done');
}
集体诉讼{
@不空白
私有字符串类型;
公共行动(){
}
公共字符串getType(){
返回类型;
}
}

两件事。1.使Action成为一个单独的类,而不是内部类。Jackson在反序列化到内部类方面有一些问题。2发送到此终结点的正文是什么。发送到此终结点的正文是
payload=%7B%22type%22%3A%22interactive_message%22%2C%22trigger_id%22%3A%22425937372067.385758389520。上面的字符串是url的一部分吗?或者它是邮件正文的一部分?如果它是url的一部分,那么解决方案就是按照@davidxxx的建议去做。如果它是Post消息负载的一部分,则使用
@RequestBody
而不是
@RequestParam
,spring将自动将其转换为您的操作class@pvpkiran这是一个有趣的想法。实际上,直接在主体中发布{…}的不是JSON,而是请求主体中添加的有效负载参数的值。你认为Spring能够同样地转换成自定义类吗?@davidxxx如果不是json,没有Spring可以这样做。因为spring依赖Jackson来完成转换,这实际上是可行的,但在我看来,这是一个解决方案,而不是一个解决方案。斯普林/杰克逊真的没有办法自动做到这一点吗?@Andrea不幸的是没有。自动功能取决于另一方是否遵守标准的操作方式,例如,没有合理的理由不双重编码有效负载。真的不知道。也许chrylis是对的。@Andrea不是一个简单的解决方案,但您可以自动化JSON->Action转换。
    @PostMapping("actions")
public ResponseEntity<?> startApplication(@RequestBody @Valid Action payload) {
    // use your payload here 
    return ResponseEntity.ok('done');
}


class Action {

    @NotBlank
    private String type;

    public Action() {
    }

    public String getType() {
        return type;
    }
}