为控制器中的每个请求映射配置FAIL_ON_UNKNOWN_PROPERTIES

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

我想在控制器中的不同@RequestMapping上以不同的方式处理json到Object的转换。

[我相信,如果我们在我们的spring-boot项目中添加Jackson依赖项,它将处理json到Object的转换,并且#spring.jackson.deserialization.fail-on-unknown-properties=true属性将确保如果json中存在一些未知的属性,转换将失败(如果我是错误)。

我们能否在本地告诉杰克逊何时对未知属性失败以及何时忽略那些属性。

下面是使用标记的代码段。

    @GetMapping(value = "sample")
    public @ResponseBody UserDTO test(@RequestParam String str, @RequestParam boolean failFast) {
        ObjectMapper map = new ObjectMapper();
        if( failFast) {
            map.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
        } else {
            map.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }
        UserDTO userDTO = null;
        try {
            userDTO = map.readValue(str, UserDTO.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return userDTO;
    }

我不需要像我正在使用@RequestParam.那样在运行时进行处理有没有可用于标记映射的属性,可以在哪里检查未知属性以及在哪里忽略它们。

编辑:我正在寻找的是更改现有应用程序以处理每个映射的未知属性。例如:

        @PostMapping(value = "fail/fast")
        public @ResponseBody UserDTO test(@**FailOnUnknown** @RequestBody UserDTO userDTO, @RequestParam boolean failFast) {
            ..///processing...
            return userDTO;
        }

        @PostMapping(value = "fail/safe")
        public @ResponseBody UserDTO test( @RequestBody UserDTO userDTO, @RequestParam boolean failFast) {
                ..///processing...
                return userDTO;
        }

如果可以为每个映射添加一些验证之王,那么我不需要更改所有现有映射来自定义未知属性,并且代码更改将是最小的。

json spring-boot jackson deserialization spring-restcontroller
1个回答
1
投票

JacksonObjectMapper允许您使用自定义配置创建新的ObjectReader。您可以在应用程序中创建一个常见的ObjectMapper实例,并且对于某些控制器,该实例用作创建自定义阅读器的基础对象。它将允许您使用所有常用功能和已注册的模块,并在需要时进行更改。参见下面的控制器:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Objects;

@RestController
@RequestMapping(value = "/options")
public class JacksonOptionsController {

    private final ObjectMapper objectMapper;

    @Autowired
    public JacksonOptionsController(ObjectMapper objectMapper) {
        this.objectMapper = Objects.requireNonNull(objectMapper);
    }

    @PostMapping(path = "/fail")
    public ResponseEntity<String> readAndFastFail(HttpServletRequest request) throws IOException {
        String json = readAsRawJSON(request);
        Payload payload = createFailFastReader().readValue(json);

        return ResponseEntity.ok("SUCCESS");
    }

    @PostMapping(path = "/success")
    public ResponseEntity<String> readAndIgnore(HttpServletRequest request) throws IOException {
        String json = readAsRawJSON(request);
        Payload payload = createSafeReader().readValue(json);

        return ResponseEntity.ok("SUCCESS");
    }

    private ObjectReader createFailFastReader() {
        return objectMapper
                .readerFor(Payload.class)
                .with(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    private ObjectReader createSafeReader() {
        return objectMapper
                .readerFor(Payload.class);
    }

    private String readAsRawJSON(HttpServletRequest request) throws IOException {
        try (InputStreamReader reader = new InputStreamReader(request.getInputStream())) {
            try (StringWriter out = new StringWriter(64)) {
                reader.transferTo(out);
                return out.toString();
            }
        }
    }
}

Payload类只有一个属性-id。在一个控制器中,我们使用启用了ObjectReaderDeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES。在其他情况下,我们将ObjectReader与默认配置一起使用,并禁用DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES

对于测试请求:

curl -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"id":"some-value","id1":1}' http://localhost:8080/options/fail

应用抛出异常并请求:

curl -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"id":"some-value"}' http://localhost:8080/options/fail

它返回SUCCESS值。当我们在http://localhost:8080/options/success URL上发送两个以上有效载荷时,两种情况下的应用程序都返回SUCCESS值。

另请参见:

© www.soinside.com 2019 - 2024. All rights reserved.