自定义注解,jackson 序列化 GeoJSON Feature FeatureCollection GeometryCollection对象
自定义注解
@Documented
@Target({TYPE})
@Retention(RUNTIME)
public @interface GeoJsonType {
/**
* Returns the {@link FeatureType} to serialize to.
*
* @return the {@link FeatureType}
*/
FeatureType type();
}
@Documented
@Target({METHOD, FIELD})
@Retention(RUNTIME)
@Inherited
public @interface GeoJsonProperty {
String name() default "";
}
@Documented
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeoJsonId {
}
@Inherited
@Documented
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeoJsonGeometry {
}
@Inherited
@Documented
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeoJsonGeometries {
}
@Inherited
@Documented
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeoJsonFeatures {
}
@Getter
public enum FeatureType {
/**
* Geometry type <em>GeometryCollection</em>
*/
GEOMETRY_COLLECTION(GeomConstants.GEOMETRY_COLLECTION),
/**
* GeoJson type <em>Feature</em>
*/
FEATURE(GeomConstants.FEATURE),
/**
* GeoJson type <em>FeatureCollection</em>
*/
FEATURE_COLLECTION(GeomConstants.FEATURE_COLLECTION);
private String name;
FeatureType(String name) {
this.name = name;
}
}
Jackson序列化类
public class ToGeoJsonSerializer extends JsonSerializer<Object> {
@Override
public Class<Object> handledType() {
return Object.class;
}
@SneakyThrows
@Override
public void serialize(Object object, JsonGenerator gen, SerializerProvider provider) throws IOException {
GeoJsonType geoJsonTypeAnnotation = object.getClass().getAnnotation(GeoJsonType.class);
if (geoJsonTypeAnnotation == null) {
throw BizException.newInstance("Annotation @GeoJson is not present.");
}
switch (geoJsonTypeAnnotation.type().getName()) {
case GeomConstants.FEATURE:
write(getFeatureFrom(object), gen, provider);
break;
case GeomConstants.FEATURE_COLLECTION:
write(getFeatureCollectionFrom(object), gen);
break;
case GeomConstants.GEOMETRY_COLLECTION:
write(getGeometryCollectionFrom(object), gen);
break;
default:
throw BizException.newInstance("Unsupported GeoJsonType: " + geoJsonTypeAnnotation.type());
}
}
private void write(GeometryCollectionDTO geometryCollection, JsonGenerator gen) throws IOException {
gen.writeStartObject();
gen.writeStringField(GeomConstants.TYPE, GeomConstants.GEOMETRY_COLLECTION);
gen.writeObjectField(GeomConstants.GEOMETRIES, geometryCollection.getGeometries());
gen.writeEndObject();
}
private void write(FeatureCollectionDTO featureCollection, JsonGenerator gen) throws IOException {
gen.writeStartObject();
gen.writeStringField(GeomConstants.TYPE, GeomConstants.FEATURE_COLLECTION);
gen.writeObjectField(GeomConstants.FEATURES, featureCollection.getFeatures());
gen.writeEndObject();
}
private void write(FeatureDTO feature, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField(GeomConstants.TYPE, GeomConstants.FEATURE);
Object id = feature.getId();
if (id != null) {
gen.writeObjectField(GeomConstants.ID, id);
}
gen.writeFieldName(GeomConstants.GEOMETRY);
Geometry geometry = feature.getGeometry();
if (geometry != null) {
new ToJsonGeometrySerializer().serialize(geometry, gen, provider);
} else {
gen.writeNull();
}
Object properties = feature.getProperties();
if (null != properties) {
gen.writeObjectField(GeomConstants.PROPERTIES, properties);
}
gen.writeEndObject();
}
private GeometryCollectionDTO getGeometryCollectionFrom(Object object) throws IllegalAccessException {
GeometryCollectionDTO feature = new GeometryCollectionDTO();
final Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
final Annotation[] annotations = field.getAnnotations();
if (annotations.length == 0) {
continue;
}
field.setAccessible(true);
final GeoJsonGeometries geoJsonGeometries = field.getAnnotation(GeoJsonGeometries.class);
if (geoJsonGeometries != null) {
final Object value = field.get(object);
List<?> features;
if (value == null) {
features = Collections.emptyList();
} else if (value instanceof Object[]) {
features = Arrays.asList(((Object[]) value));
} else if (value instanceof Collection) {
features = new ArrayList<>((Collection<?>) value);
} else {
throw BizException.newInstance("Value of " + value.getClass().getName() + " is not an Array or Collection.");
}
feature.setGeometries(features);
}
}
return feature;
}
private FeatureCollectionDTO getFeatureCollectionFrom(Object object) throws IllegalAccessException {
FeatureCollectionDTO feature = new FeatureCollectionDTO();
final Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
final Annotation[] annotations = field.getAnnotations();
if (annotations.length == 0) {
continue;
}
field.setAccessible(true);
final GeoJsonFeatures geoJsonFeatures = field.getAnnotation(GeoJsonFeatures.class);
if (geoJsonFeatures != null) {
final Object value = field.get(object);
List<?> features;
if (value == null) {
features = Collections.emptyList();
} else if (value instanceof Object[]) {
features = Arrays.asList(((Object[]) value));
} else if (value instanceof Collection) {
features = new ArrayList<>((Collection<?>) value);
} else {
throw BizException.newInstance("Value of " + value.getClass().getName() + " is not an Array or Collection.");
}
feature.setFeatures(features);
}
}
return feature;
}
private FeatureDTO getFeatureFrom(Object object) throws IllegalAccessException {
FeatureDTO feature = new FeatureDTO();
final Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
final Annotation[] annotations = field.getAnnotations();
if (annotations.length == 0) {
continue;
}
field.setAccessible(true);
final GeoJsonId geoJsonId = field.getAnnotation(GeoJsonId.class);
if (geoJsonId != null) {
feature.setId(field.get(object));
}
final GeoJsonProperty geoJsonProperty = field.getAnnotation(GeoJsonProperty.class);
if (geoJsonProperty != null) {
String name = StringUtils.isNotBlank(geoJsonProperty.name()) ? geoJsonProperty.name() : field.getName();
feature.getProperties().put(name, field.get(object));
}
final GeoJsonGeometry geoJsonGeometry = field.getAnnotation(GeoJsonGeometry.class);
if (geoJsonGeometry != null) {
if (!field.getType().getName().equals(Geometry.class.getName())) {
throw BizException.newInstance("@GeoJsonGeometry only supported Geometry");
}
feature.setGeometry((Geometry) field.get(object));
}
}
return feature;
}
}
Jackson工具类
@Slf4j
public final class GisJacksonUtils {
private static ObjectMapper OBJECT_MAPPER;
private GisJacksonUtils() {
}
static {
init();
}
private static void init() {
OBJECT_MAPPER = new ObjectMapper();
OBJECT_MAPPER.registerModule(new JtsModule());
}
public static String toJson(Object obj) {
try {
return OBJECT_MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.error("输出json数据失败", e);
throw BizException.newInstance(String.format("输出json数据失败 %s", e.getMessage()));
}
}
public static String toPrettyJson(Object obj) {
try {
return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.error("输出json数据失败", e);
throw BizException.newInstance(String.format("输出json数据失败 %s", e.getMessage()));
}
}
}
import com.fasterxml.jackson.databind.module.SimpleModule;
/**
* @author chenjunfan
* @date 2023-06-29
*/
public class JtsModule extends SimpleModule {
public JtsModule() {
super("JtsModule");
this.addSerializer(new ToJsonGeometrySerializer());
}
}
Test代码
Feature
public class GeomFeatureTest {
@Test
public void test() {
DemoFeature demoFeature = new DemoFeature();
demoFeature.setId(1L);
demoFeature.setGeom(GeomUtils.createPoint(1, 2));
demoFeature.setName("test");
demoFeature.setAddr("addr");
System.out.println(JacksonUtils.toPrettyJson(demoFeature));
}
@Data
@GeoJsonType(type = FeatureType.FEATURE)
@JsonSerialize(using = ToGeoJsonSerializer.class)
public static class DemoFeature {
@GeoJsonId
private Long id;
@GeoJsonGeometry
private Geometry geom;
@GeoJsonProperty
private String name;
@GeoJsonProperty
private String addr;
}
}
运行结果
{
"type" : "Feature",
"id" : 1,
"geometry" : {
"type" : "Point",
"coordinates" : [ 1.0, 2.0 ]
},
"properties" : {
"name" : "test",
"addr" : "addr"
}
}
FeatureCollection
public class GeomFeatureCollectionTest {
@Test
public void test() {
DemoFeature demoFeature = new DemoFeature();
demoFeature.setId(1L);
demoFeature.setGeom(GeomUtils.createPoint(1, 2));
demoFeature.setName("test");
demoFeature.setAddr("addr");
DemoFeature demoFeature2 = new DemoFeature();
demoFeature2.setId(2L);
demoFeature2.setGeom(GeomUtils.createPoint(1, 2));
demoFeature2.setName("test2");
demoFeature2.setAddr("addr2");
DemoFeatureCollection demoFeatureCollection = new DemoFeatureCollection();
demoFeatureCollection.setList(Arrays.asList(demoFeature, demoFeature2));
System.out.println(JacksonUtils.toPrettyJson(demoFeatureCollection));
}
@Data
@GeoJsonType(type = FeatureType.FEATURE_COLLECTION)
@JsonSerialize(using = ToGeoJsonSerializer.class)
public static class DemoFeatureCollection {
@GeoJsonFeatures
private List<?> list;
}
@Data
@GeoJsonType(type = FeatureType.FEATURE)
@JsonSerialize(using = ToGeoJsonSerializer.class)
public static class DemoFeature {
@GeoJsonId
private Long id;
@GeoJsonGeometry
private Geometry geom;
@GeoJsonProperty
private String name;
@GeoJsonProperty
private String addr;
}
}
运行结果
{
"type" : "FeatureCollection",
"features" : [ {
"type" : "Feature",
"id" : 1,
"geometry" : {
"type" : "Point",
"coordinates" : [ 1.0, 2.0 ]
},
"properties" : {
"name" : "test",
"addr" : "addr"
}
}, {
"type" : "Feature",
"id" : 2,
"geometry" : {
"type" : "Point",
"coordinates" : [ 1.0, 2.0 ]
},
"properties" : {
"name" : "test2",
"addr" : "addr2"
}
} ]
}
GeometryCollection
public class GeometryCollectionTest {
@Test
public void test() {
DemoGeometryCollection geometryCollection = new DemoGeometryCollection();
geometryCollection.setList(Arrays.asList(GeomUtils.createPoint(1, 2),
GeomUtils.createPoint(1, 2)));
System.out.println(GisJacksonUtils.toPrettyJson(geometryCollection));
}
@Data
@GeoJsonType(type = FeatureType.GEOMETRY_COLLECTION)
@JsonSerialize(using = ToGeoJsonSerializer.class)
public static class DemoGeometryCollection<T extends Geometry> {
@GeoJsonGeometries
private List<T> list;
}
}
运行结果
{
"type" : "GeometryCollection",
"geometries" : [ {
"type" : "Point",
"coordinates" : [ 1.0, 2.0 ]
}, {
"type" : "Point",
"coordinates" : [ 1.0, 2.0 ]
} ]
}