如何配置ModelMapper,序列化时将JTS Geometry转为GeoJSON格式?
当然可以实现这个需求!要让ModelMapper把JTS Geometry类型(比如你的MultiPolygon)序列化为标准的GeoJSON格式,你有两种常用的方案,我都会详细说明:
方案一:自定义ModelMapper类型转换器
这种方式直接通过ModelMapper的扩展能力,覆盖默认的Geometry映射逻辑,把它转成GeoJSON格式。
步骤1:添加JTS GeoJSON依赖
首先确保你的项目引入了能处理JTS和GeoJSON转换的依赖,Maven示例如下:
<dependency> <groupId>com.vividsolutions</groupId> <artifactId>jts-geojson</artifactId> <version>1.13</version> </dependency>
步骤2:实现自定义转换器
创建一个Converter类,负责把JTS Geometry对象转成GeoJSON字符串(或者直接转成Jackson的JsonNode,这样序列化后就是GeoJSON对象而不是字符串):
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.geojson.GeoJsonWriter; import org.modelmapper.Converter; import org.modelmapper.spi.MappingContext; // 转为GeoJSON字符串的版本 public class GeometryToGeoJsonConverter implements Converter<Geometry, String> { private final GeoJsonWriter geoJsonWriter = new GeoJsonWriter(); @Override public String convert(MappingContext<Geometry, String> context) { Geometry geometry = context.getSource(); if (geometry == null) { return null; } // 直接调用JTS的工具类生成GeoJSON字符串 return geoJsonWriter.write(geometry); } }
如果希望最终序列化后是GeoJSON对象(而非带引号的字符串),可以改成转成Jackson的JsonNode:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.geojson.GeoJsonWriter; import org.modelmapper.Converter; import org.modelmapper.spi.MappingContext; public class GeometryToGeoJsonNodeConverter implements Converter<Geometry, JsonNode> { private final GeoJsonWriter geoJsonWriter = new GeoJsonWriter(); private final ObjectMapper objectMapper = new ObjectMapper(); @Override public JsonNode convert(MappingContext<Geometry, JsonNode> context) { Geometry geometry = context.getSource(); if (geometry == null) { return null; } try { String geoJsonStr = geoJsonWriter.write(geometry); // 把字符串转成JsonNode,序列化后就是GeoJSON对象 return objectMapper.readTree(geoJsonStr); } catch (Exception e) { throw new RuntimeException("转换Geometry到GeoJSON失败", e); } } }
步骤3:注册转换器到ModelMapper
在创建ModelMapper实例时,把自定义的转换器注册进去:
ModelMapper modelMapper = new ModelMapper(); // 注册转换器,支持所有Geometry子类(包括MultiPolygon) modelMapper.addConverter(new GeometryToGeoJsonConverter()); // 如果用的是JsonNode版本,就注册对应的转换器 // modelMapper.addConverter(new GeometryToGeoJsonNodeConverter());
步骤4:调整DTO的字段类型
- 如果用的是字符串版本,DTO中的
geom字段类型为String - 如果用的是JsonNode版本,DTO中的
geom字段类型为JsonNode
这样当你用ModelMapper把Municipio实体转成DTO后,geom字段就会是GeoJSON格式的内容了。
方案二:结合Jackson自动处理(推荐)
如果你是用Jackson来序列化最终的DTO(大多数Java项目都是如此),那可以直接让Jackson来处理Geometry到GeoJSON的转换,ModelMapper只需要做简单的对象映射即可,这种方式更简洁。
步骤1:添加Jackson JTS模块依赖
<dependency> <groupId>com.bedatadriven</groupId> <artifactId>jackson-datatype-jts</artifactId> <version>2.14.0</version> </dependency>
步骤2:配置ObjectMapper
注册JTS模块到Jackson的ObjectMapper中,这样Jackson就知道如何把Geometry序列化为GeoJSON:
import com.bedatadriven.jackson.datatype.jts.JtsModule; import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper objectMapper = new ObjectMapper(); // 注册JTS模块,自动处理Geometry的GeoJSON序列化 objectMapper.registerModule(new JtsModule());
步骤3:正常使用ModelMapper映射
这时候你的DTO中的geom字段可以直接用MultiPolygon或者Geometry类型,ModelMapper不需要任何特殊配置,直接映射即可:
Municipio municipio = // 从数据库获取的实体 MunicipioDTO dto = modelMapper.map(municipio, MunicipioDTO.class);
步骤4:序列化DTO
用配置好的ObjectMapper序列化DTO,就能得到带有GeoJSON对象的结果:
String json = objectMapper.writeValueAsString(dto);
两种方案都能解决你的问题,如果你更希望在ModelMapper层完成转换,选方案一;如果项目用Jackson做序列化,方案二更省心。
内容的提问来源于stack exchange,提问作者joninx

