Spring Boot 未使用@JsonbTypeAdapter

@JsonbTypeAdapter is not used by Spring Boot

我正在尝试将 Json-B 与 Spring 启动版本一起使用: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 发送了一个 post 请求,内容如下:

{
    "expiredTime": 6000
}

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

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

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

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

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

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

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