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
我正在尝试将 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