0

我正在尝试将 Json-B 与 Spring Boot 版本一起使用:2.3.1

json-b

<dependency>
            <groupId>javax.json.bind</groupId>
            <artifactId>javax.json.bind-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse</groupId>
            <artifactId>yasson</artifactId>
            <version>1.0.5</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.json</artifactId>
            <version>1.1.4</version>
        </dependency>

休息控制器:

@RestController
public class MyController {

    @PostMapping("/api/test")
    public ResponseEntity init(@Valid @RequestBody MyRequest request) {
        return ResponseEntity.ok("ok");
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map<String, String> handleValidationExceptions(
            MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            final Object rejectedValue = ((FieldError) error).getRejectedValue();
            errors.put("Rejected Value: ", rejectedValue.toString());
            errors.put(fieldName, errorMessage);
        });
        return errors;
    }


}

请求:


public class MyRequest  {

    @DurationMin(minutes = 1")
    @DurationMax(minutes = 10)
    @JsonbTypeAdapter(DurationAdapter.class)
    private Duration expiredTime;

    ....getter setter... 
}

Json-B 适配器:

public class DurationAdapter implements JsonbAdapter<Duration, JsonValue> {

    @Override
    public JsonValue adaptToJson(Duration duration) throws Exception {
        final JsonNumber value = Json.createValue(duration.toMillis());
        return value;
    }

    @Override
    public Duration adaptFromJson(JsonValue jsonValue) throws Exception {
        final long timeInMillis = ((JsonNumber) jsonValue).longValue();
        return Duration.ofMillis(timeInMillis);
    }
}

我也试过这个适配器:

public class DurationAdapter implements JsonbAdapter<Duration, Long> {

    @Override
    public Long adaptToJson(Duration obj) throws Exception {
        return obj.toMillis();
    }

    @Override
    public Duration adaptFromJson(Long obj) throws Exception {
        return Duration.ofMillis(obj);
    }
}

我使用 Postman 发送了一个包含如下内容的发布请求:

{
    "expiredTime": 6000
}

我在适配器中放置了断点,但应用程序从未通过断点。我在休息控制器的异常处理程序中的拒绝值处放置了一个断点,我看到持续时间始终以“秒”为单位,而不是毫秒。如果请求具有“expiredTime”:6000,那么 Java 对象将具有值为 Duration=6000 秒的 expriredTime 字段(使用调试器查看值)并且将引发异常(这就是我可以在异常处理程序中使用调试器的原因)。

如何让 Spring Boot 使用我的 Json-B 适配器? 谢谢!

更新:我也在 application.properties 中指定了这个: spring.http.converters.preferred-json-mapper=jsonb

4

1 回答 1

1

您的代码有效,我准备了另一个示例在这里展示。我排除了像下面这样的杰克逊,只是为了确保它没有被使用。

        <exclusions>
            <exclusion>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>

并使用 println 显示在日志中。看起来像这样

在此处输入图像描述

据我了解spring.http.converters.preferred-json-mapper不是很有效。只要它在类路径中找到任何映射器,spring 就会使用它。在https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html中没有http.converter

于 2020-07-22T17:25:42.580 回答