自定义Jackson序列化到Json在Wildfly 26中不工作



我正试图将一个大型复杂项目从Wildfly 23升级到Wildfly 26,但Json响应不再返回我们期望的有效载荷。两个例子是:

  1. 包装列表的对象应该返回包装列表的Json数组,但相反,它返回包装对象与列表一起,即它应该返回[ ... ],但它返回{ "objects": [ ... ] }

包装器类使用@JsonValue在列表getter方法中,它应该使此工作,但列表类上的自定义序列化器没有被调用。

  1. @JsonFormat(pattern = ...some pattern...)注释的日期字段不被格式化

这是一个Java 11项目(11.0.14.1,Eclipse Adoptium),它使用Maven 3.6.3创建一个WAR文件,该文件部署到Wildfly 26(构建在Windows 10 Enterprise上,部署到Windows Server 2019 Standard)。我已经创建了一个非常精简的例子来说明这种行为(如下所示的类/文件)。

我使用mvn clean verify构建项目,它创建了targetjsontest.war然后将其复制到单机部署成功部署的目录。有一个自定义登录模块使用,但我不认为这是相关的问题,因为端点正在被到达。

在server.log中有两个我认为不相关的警告:

WARN  [org.jboss.as.dependency.deprecated] (MSC service thread 1-5) WFLYSRV0221: Deployment "deployment.jsontest.war" is using a deprecated module ("javax.api") which may be removed in future versions without notice.
WARN  [org.jboss.as.dependency.deprecated] (MSC service thread 1-5) WFLYSRV0221: Deployment "deployment.jsontest.war" is using a deprecated module ("org.jboss.resteasy.resteasy-jaxrs") which may be removed in future versions without notice.

如果能提供任何帮助,我将不胜感激。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>jsontest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.7</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>jsontest</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<webResources>
<resource>
<directory>${project.basedir}/src/main/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
在<<p> strong> src/主/java/org/example/jsontest 有以下类:

MainResource.java

package org.example.jsontest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
@Path("/")
public class MainResource {
@GET
@Path("json")
@Produces({ MediaType.APPLICATION_JSON })
public Response getJsonExample() {
// We want to return a Json array containing 2 objects
final SomeObject object1 = new SomeObject().setA("a1").setB("b1");
final SomeObject object2 = new SomeObject().setA("a2").setC("c2");
final ResponseList<SomeObject> objectList = new ResponseList<>();
objectList.addAll(List.of(object1, object2));
final ResponseListWrapper<SomeObject> wrapper = new ResponseListWrapper<>();
wrapper.setObjects(objectList);
return Response.ok(wrapper).build();
}
}

ResponseListWrapper.java

package org.example.jsontest;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonValue;
@JsonInclude(value = Include.NON_NULL)
public class ResponseListWrapper<T> {
private ResponseList<T> objects;
public ResponseListWrapper() {
objects = new ResponseList<>();
}
public ResponseListWrapper(ResponseList<T> objects) {
setObjects(objects);
}
/**
* @JsonValue is supposed to indicate that the value from the method is to be used to produce the Json output.
* We want to return a Json array, not the wrapped object with an array, i.e.
*
* [ { "a": "a1", "b": "b1" }, { "a": "a2", "c": "c2" } ]
*
* But instead we get the wrapped object:
* { "objects": [ { "a": "a1", "b": "b1" }, { "a": "a2", "c": "c2" } ] }
*
* ResponseList is annotated with @JsonSerialize(using = JacksonListSerializer.class)
* but JacksonListSerializer.serialize() is never called.
*
*/
@JsonValue
public ResponseList<T> getObjects() {
return objects;
}
public void setObjects(ResponseList<T> objects) {
this.objects = objects;
}
}

ResponseList.java

package org.example.jsontest;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.ArrayList;
import java.util.Collection;
/**
*
* @JsonSerialize is supposed to tell Jackson to use JacksonListSerializer when generating a Json response but it is not
* being called.
*/
@JsonSerialize(using = JacksonListSerializer.class)
public class ResponseList<T> extends ArrayList<T> {
private static final long serialVersionUID = -6120242076197274777L;
public ResponseList() {
}
public ResponseList(Collection<? extends T> c) {
super(c);
}
public ResponseList(int initialCapacity) {
super(initialCapacity);
}
}

JacksonListSerializer.java

package org.example.jsontest;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class JacksonListSerializer extends JsonSerializer<ResponseList<?>> {
@Override
public void serialize(ResponseList<?> list, JsonGenerator generator, SerializerProvider provider)
throws IOException {
generator.writeStartArray();
if (list != null) {
for (Object item : list) {
generator.writeObject(item);
}
}
generator.writeEndArray();
}
}

SomeObject.java

package org.example.jsontest;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serializable;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SomeObject implements Serializable {
private static final long serialVersionUID = 6725549179169119963L;
private String a;
private String b;
private String c;
public String getA() {
return a;
}
public SomeObject setA(final String a) {
this.a = a;
return this;
}
public String getB() {
return b;
}
public SomeObject setB(final String b) {
this.b = b;
return this;
}
public String getC() {
return c;
}
public SomeObject setC(final String c) {
this.c = c;
return this;
}
}
在<<p> strong> src/main/webapp 有以下文件:

jboss-deployment-structure.xml

<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.wildfly.security.elytron"/>
<module name="org.wildfly.extension.elytron"/>
<module name="javax.api"/>
<module name="org.jboss.resteasy.resteasy-jaxrs"/>
<module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
</dependencies>
</deployment>
</jboss-deployment-structure>

jboss-web.xml

<?xml version="1.0"?>
<jboss-web xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.jboss.com/xml/ns/javaee"
version="6.0"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_6_0.xsd">
<security-domain>...removed...</security-domain>
<context-root>/jsontest</context-root>
</jboss-web>

web . xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>jsontest</display-name>
<!-- Security related settings have been removed -->
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<path>/jsontest</path>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
</web-app>

终于追查到原因了。我们有一个自定义的认证/登录模块,它使用自己的Jackson库副本(Jackson -core-2.13.4.jar, Jackson -databind-2.13.4.2.jar, Jackson -annotations-2.13.4.jar)。我从module.xml中删除了它们而是在module.xml中的依赖项中添加了以下内容:

<module name="org.jboss.resteasy.resteasy-jaxrs"/>
<module name="org.jboss.resteasy.resteasy-jackson2-provider"/>

重新启动Wildfly后,有效载荷按预期返回。我确实按照James的建议使用了-D"resteasy.preferJacksonOverJsonB"="true"设置(谢谢!)。

相关内容

  • 没有找到相关文章

最新更新