【问题标题】:Spring Boot - RestController Deserializing YAML Uploads?Spring Boot - RestController 反序列化 YAML 上传?
【发布时间】:2016-09-16 15:13:29
【问题描述】:

如何配置 Spring Boot RestController 以接受 YAML 上传?

下面的结果是 415。我可以通过调试看到我的 Spring 上下文中的 MappingJackson2HttpMessageConverter 实例仅支持 [application/json;charset=UTF-8, application/*+json;charset=UTF-8]。我不能是唯一一个尝试这样做的 Spring Boot 用户,我很惊讶它不能正常工作 - 大多数事情都在 Spring Boot 中完成!

我的 POM 中有 YAML 数据格式:

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-yaml</artifactId>
    </dependency>

我的 RestController 有一个方法:

@RequestMapping(method=RequestMethod.POST, value="/", consumes="application/yaml")
public String upload(@RequestBody Declaration declaration) {
    //Do stuff
}

我的测试:

@Test
public void triggersConvergence() throws Exception {
    ClassPathResource fixture = new ClassPathResource("declaration.yml");
    HttpHeaders requestHeaders = new HttpHeaders();
    requestHeaders.add("Content-Type", "application/yaml");
    requestHeaders.add("Accept", "application/json");

    URI uri = new URI("http://127.0.0.1:"+port);
    byte[] bytes = new byte[(int)fixture.contentLength()];
    fixture.getInputStream().read(bytes);
    RequestEntity<byte[]> postRequest = new RequestEntity<byte[]>(bytes, requestHeaders, HttpMethod.POST, uri);

    ResponseEntity<String> response = rest.exchange(postRequest, String.class);
    assertThat(response.getStatusCode(), is(HttpStatus.OK));
    assertThat(response.getBody(), is("Converged org my-lovely-org"));
}

【问题讨论】:

  • 您要上传还是要提交表示为 YAML 的对象。因为两者都是完全不同的问题(和解决方案)。

标签: java spring-boot jackson yaml


【解决方案1】:

虽然此功能在 Spring 中不可用,但使用 YAMLMapper 只需 2 个简单步骤即可轻松添加:

  1. 定义你自己的支持Content-Type: application/x-yamlHttpMessageConverter

    final class YamlJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
        YamlJackson2HttpMessageConverter() {
            super(new YAMLMapper(), MediaType.parseMediaType("application/x-yaml"));
        }
    }
    
  2. 注册您的转换器:

    @Configuration
    public class YamlConfiguration extends WebMvcConfigurerAdapter {
        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add(new YamlJackson2HttpMessageConverter());
        }
    }
    

享受来自 POJO 的控制器方法消费生产application/x-yaml

【讨论】:

  • 太棒了!这正是我希望为您提供的那种轻触式解决方案。
  • 不知道为什么会出现“你”这个词!
【解决方案2】:

是的,你可以这样做。

Maven 依赖:

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-yaml</artifactId>
  <version>2.5.4</version>
</dependency>

控制器方法:

@RequestMapping(value = "/my/endpoint", method = RequestMethod.POST, consumes = "application/x-yaml")
@ResponseBody
public ResponseEntity<MyResponse> receiveYaml(@RequestBody final String yaml) {
    //unserialize yaml
}

使用 curl 的请求示例:

curl -X POST --header "Content-Type: application/x-yaml" --header "Accept: */*" -d "invoice: 34843
date   : 2001-01-23
bill-to: &id001
    given  : Chris
    family : Dumars
    address:
        lines: |
            458 Walkman Dr.
            Suite #292
        city    : Royal Oak
        state   : MI
        postal  : 48046
ship-to: *id001
product:
    - sku         : BL394D
      quantity    : 4
      description : Basketball
      price       : 450.00
    - sku         : BL4438H
      quantity    : 1
      description : Super Hoop
      price       : 2392.00
tax  : 251.42
total: 4443.52
comments: >
    Late afternoon is best.
    Backup contact is Nancy
    Billsmer @ 338-4338."

【讨论】:

  • com.fasterxml.jackson.dataformat:jackson-dataformat-yaml 不需要在receiveYaml(@RequestBody final String yaml) 中消费application/x-yaml
  • 你是对的。但是如果你想使用 new ObjectMapper(new YAMLFactory()); 反序列化 yaml 是必需的
  • 您可以使用 POJO 的类型而不是 String 来声明参数,因此可以避免使用 ObjectMapper 显式反序列化。 BTW,它可以同时支持yaml & json,所以不需要加consumes = "application/x-yaml",除非你只想接受yaml。
猜你喜欢
  • 1970-01-01
  • 2018-08-07
  • 2019-02-14
  • 2015-02-17
  • 1970-01-01
  • 2019-04-03
  • 2015-09-01
  • 2017-05-24
  • 2018-02-05
相关资源
最近更新 更多