如果REST原始净荷被映射到对象,是否可以在rest控制器中使用,否则?

问题描述 投票:0回答:1

我有一个POST端点,带有一些保存重要数据的JSON有效负载应通过摘要进行存档。

@RestController
public class SomeController {

  @PostMapping(value = "/api/some")
  public ResponseEntity<ResponseStatus> postSome(@Valid @RequestBody Some some) {
    archiveAndDigest(rawJsonPostPayloadSomeHowFromCurrentContext());
    someService(some);
    return new ResponseEntity<ResponseStatus>(
      ResponseStatus.builder()
...
        .build(),
        HttpStatus.CREATED
      );
  }

控制器端点太具有表现力和方便性(确保内容类型,解析并验证输入有效载荷),以至于无法丢弃原始字符串输入,并且需要手工完成所有这些操作。输入的有效负载必须保留用于审核。

rest spring-boot
1个回答
0
投票

有可能获得原始的JSON值而不是反序列化的对象。

我可以想到两种方法。

1st,其中我不推荐

这样,您无法使用Spring Validator中的。

以字符串形式接收JSON,然后使用ObjectMapper将原始值转换为对象。

@RestController
public class SomeController {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @PostMapping(value = "/api/some")
    public ResponseEntity<ResponseStatus> postSome(String rawRequest) {
        log.info("Raw value: {}", rawRequest);

        ObjectMapper mapper = new ObjectMapper();
        Some some = mapper.readValue(rawRequest, Some.class);
        someService(some);

        return new ResponseEntity<ResponseStatus> (ResponseStatus.builder()
        ...
        .build(), HttpStatus.CREATED);
    }
}

第二,其中我更喜欢

将对象作为对象接收(就像您所做的那样,然后使用ObjectMapper从对象获取JSON原始值

这样您可以使用Spring Validator。

@RestController
public class SomeController {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @PostMapping(value = "/api/some")
    public ResponseEntity<ResponseStatus> postSome(@Valid @RequestBody Some some) {
        ObjectMapper mapper = new ObjectMapper();

        String rawJsonValue mapper.writeValueAsString(some);
        log.info("Raw value: {}", rawJsonValue);

        someService(some);

        return new ResponseEntity<ResponseStatus> (ResponseStatus.builder()
        ...
        .build(), HttpStatus.CREATED);
    }
}

我更喜欢梯子,但请记住,不会打印对象中不存在的JSON请求中发送的任何属性。发生这种情况是因为mapper.writeValueAsString(some)将基于对象的属性生成JSON。

UPDATE

您可以将HttpServletRequest定义为方法的参数。这样,Spring将提供当前请求并将其传递给参数。

@RestController
public class SomeController {

    @PostMapping(value = "/api/some")
    public ResponseEntity<ResponseStatus> postSome(@Valid @RequestBody Some some, HttpServletRequest request) {
        String rawValue = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));

        System.out.println(rawValue);

        someService(some);

        return new ResponseEntity<ResponseStatus> (ResponseStatus.builder()
        ...
        .build(), HttpStatus.CREATED);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.