【发布时间】:2022-11-06 04:20:27
【问题描述】:
假设,我们有 2 个 RESTful Web 服务 (JAX-RS)。第一个服务充当消费者并调用第二个服务的 API。第二个服务(提供者)是使用 openapi-generator-maven-plugin 和 jaxrs-spec 选项和描述 API 的底层 .yml 文件生成的。提供者和消费者 Web 服务都成功部署在 Weblogic 应用程序服务器上,并按预期服务请求......
...除了一个小例外。 Enums 的序列化/反序列化没有按预期工作。 Eums 是使用相应的 Jackson2 注释 @JsonValue 和 @Jsoncreator 生成的:
public enum MyEnum {
FIRST_VALUE("first_value"),
SECOND_VALUE("second_value");
private static Map<String, MyEnum> ENUM_MAP = Stream
.of(MyEnum.values())
.collect(Collectors.toMap(s -> s.formatted, Function.identity()));
private final String value;
private MyEnum(String value) { this.value = value; }
@JsonValue
public String value() { return value; }
@JsonCreator
public static MyEnum fromString(String string) {
return Optional
.ofNullable(ENUM_MAP.get(string))
.orElseThrow(() -> new IllegalArgumentException(string));
}
}
期望(假设 ObjectMapper 不会忽略 Jackson 注释)Java 对象 MyEnum.FIRST_VALUE 被序列化为 {"first_value"}。但是,结果(提供者 Web 服务接收和消费者 Web 服务发送的内容)是 {"FIRST_VALUE"}。怎么来的? Weblogic 使用 MOXy 作为默认 JSON 提供程序。而 MOXy 忽略了上面提到的 Jackson2 Annotations。
因此,问题是:如何让网络服务接收 {"first_value"} 而不是 {"FIRST_VALUE"}和我应该如何调整我的 JAX-RS Jersey 客户端(在第一个 Web 服务中),以便在使用调用时将值 {"first_value"} 传递给我的第二个 Web 服务
Client client = ClientBuilder().newClient();
client.target(MY_URI)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(MyEnum.FIRST_VALUE, MediaType.APPLICATION_JSON));
我尝试了以下方法:
- 当我们使用 Jackson 作为 JSON 提供者时,发现序列化/反序列化在 Java SE 环境中正常工作(在添加相应的 maven 坐标之后)。请点击here,我的示例枚举看起来一样(加上
@JsonValue注解,减去@JsonProperty)。但是,序列化在 Java SE 单元测试中按预期工作 - 发现 MOXy 需要 JAXB-Annotations,因此我们可以使用
openapi-generator-maven-plugin来生成 JAXB-Annotations。见here。似乎有点太复杂,无法实现目标。 - 编写自定义 XmlAdapter,请参阅 here。当杰克逊开箱即用时,我们为什么要这样做?
- 禁用 MOXy 作为默认 JSON 提供程序,请参阅 here。实际上,这解决了生产者方面的问题,但是消费者呢?客户端仍然发送“错误”的 JSON,因此服务会抛出异常。
【问题讨论】: