问题描述
我正在尝试将旧的 EJB 服务(内部逻辑)包装在微服务中。我使用 Quarkus / RESTEasy 来实现这个微服务
但是,我在自定义序列化/反序列化时遇到了问题。
问题:Cannot construct instance of com.vividsolutions.jts.geom.Geometry
这让我相信 Jackson 并没有将 Geometry 视为要解析为字符串的类。这导致相信我没有选择对象映射器..
注 1:我可以在 Quarkus 日志中提供的日志语句中看到:customizing ObjectMapper,adding geometry serializer / deserializer
注意 2:单元测试在 RegisterGeometryMapper
上运行良好。
这是我要解析的JSON(注意:几何是GeoGSON)
{
"geometry": {
"type": "Point","coordinates": [
134750,477800,3.18
],"crs": {
"type": "name","properties": {
"name": "epsg:28992"
}
}
},"date": 1612519294297
}
这是 REST 资源方法:
@POST
@Path( "/etrs89-transformation" )
@Consumes( MediaType.APPLICATION_JSON )
@Produces( MediaType.APPLICATION_JSON )
TransformationResult transformToEtrs89(@NotNull @Valid TransformationRequest request);
及其请求 DTO:
public class TransformationRequest {
@NotNull private Geometry geometry;
private Date date;
}
这是我注册的映射器。
@Singleton
public class RegisterGeometryMapper implements ObjectMapperCustomizer {
private static final Logger LOG = Logger.getLogger( RegisterGeometryMapper .class );
public void customize(ObjectMapper mapper) {
LOG.debug( "customizing ObjectMapper,adding geometry serializer / deserializer." );
SimpleModule module = new SimpleModule();
module.addDeserializer( Geometry.class,new GeometryDeserializer() );
module.addSerializer( Geometry.class,new GeometrySerializer() );
mapper.registerModule( module );
}
public static class GeometryDeserializer extends StdDeserializer<Geometry> {
private final GeoJsonReader reader = new GeoJsonReader();
public GeometryDeserializer() {
this( Geometry.class );
}
public GeometryDeserializer(Class<Geometry> vc) {
super( vc );
}
@Override
public Geometry deserialize(JsonParser jp,DeserializationContext ctxt) throws IOException,JsonProcessingException {
JsonNode node = jp.getCodec().readTree( jp );
String geoGson = node.toString();
try {
return reader.read( geoGson );
}
catch ( ParseException ex ) {
throw new IOException( ex );
}
}
}
public static class GeometrySerializer extends StdSerializer<Geometry> {
private final GeoJsonWriter writer = new GeoJsonWriter();
protected GeometrySerializer() {
this( Geometry.class );
}
protected GeometrySerializer(Class<Geometry> t) {
super( t );
}
@Override
public void serialize(Geometry geometry,JsonGenerator jgen,SerializerProvider serializerProvider) throws IOException {
jgen.writerawValue( writer.write( geometry ) );
}
}
}
作者/读者源自 jts io。
<!-- GeoJson -->
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts-io</artifactId>
<version>1.14.0</version>
</dependency>
此外:我坚持使用 jts(无法迁移到较新版本 - locationtech - 由于遗留原因,JBOSS EAP 停留在不支持 locationtech 的 Hibernate 上)。
解决方法
上述解决方案是正确且有效的。
问题是我在代码中的其他地方添加了:
@Provider
public class JacksonConfig implements ContextResolver<ObjectMapper> {
private final ObjectMapper objectMapper;
public JacksonConfig() throws Exception {
objectMapper = new ObjectMapper();
objectMapper.enable( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS );
}
@Override
public ObjectMapper getContext(Class<?> arg0) {
return objectMapper;
}
}
这会创建一个新的 ObjectMapper
并撤消我在 @Singleton
类中所做的一切。