diff --git a/ebike-operations/src/main/java/com/cdzy/operations/handler/PointDeserializer.java b/ebike-operations/src/main/java/com/cdzy/operations/handler/PointDeserializer.java index 1f47ff7..cf94861 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/handler/PointDeserializer.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/handler/PointDeserializer.java @@ -13,7 +13,7 @@ import java.util.Locale; /** * JTS Point 反序列化器 - 将 JSON 反序列化为 Point - * 支持多种 JSON 格式 + * 支持 type、longitude、latitude 三个字段的格式 */ @Slf4j public class PointDeserializer extends JsonDeserializer { @@ -21,7 +21,7 @@ public class PointDeserializer extends JsonDeserializer { private final GeometryFactory geometryFactory = new GeometryFactory(); @Override - public Point deserialize(JsonParser p, DeserializationContext context) throws IOException { + public Point deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); if (node.isNull()) { @@ -29,47 +29,48 @@ public class PointDeserializer extends JsonDeserializer { } try { - Point result = null; + // 格式1: 三字段格式 {"type": "point", "longitude": 116.3974, "latitude": 39.9093} + if (node.isObject() && node.has("type") && + (node.has("longitude") || node.has("latitude"))) { + return parseFromThreeFields(node); + } - // 格式1: 自定义格式 {"type": "point", "coordinates": [lng, lat]} + // 格式2: 自定义格式 {"type": "point", "coordinates": [lng, lat]} if (node.isObject() && node.has("type")) { String type = node.get("type").asText().toLowerCase(Locale.ROOT); if ("point".equals(type)) { - result = parseFromCustomFormat(node); + return parseFromCustomFormat(node); } } - // 格式2: GeoJSON 格式 {"type": "Point", "coordinates": [lng, lat]} + // 格式3: GeoJSON 格式 {"type": "Point", "coordinates": [lng, lat]} else if (node.isObject() && node.has("type")) { String type = node.get("type").asText(); if ("Point".equals(type)) { - result = parseFromGeoJSON(node); + return parseFromGeoJSON(node); } } - // 格式3: 坐标数组格式 [lng, lat] + // 格式4: 坐标数组格式 [lng, lat] else if (node.isArray()) { - result = parseFromArray(node); + return parseFromArray(node); } - // 格式4: 对象格式但没有 type 字段,尝试解析 coordinates 或直接解析 x,y - else if (node.isObject()) { - result = parseFromObject(node); + // 格式5: 简化的三字段格式(没有type) + else if (node.isObject() && (node.has("longitude") || node.has("latitude"))) { + return parseFromLongitudeLatitude(node); } - // 格式5: WKT 字符串格式 "POINT(lng lat)" + // 格式6: WKT 字符串格式 "POINT(lng lat)" else if (node.isTextual()) { - result = parseFromWKT(node.asText()); + return parseFromWKT(node.asText()); } - if (result == null) { - throw new IOException(""" - 不支持的 Point JSON 格式,支持的格式包括: - 1. 自定义格式: {"type":"point","coordinates":[lng,lat]} - 2. GeoJSON格式: {"type":"Point","coordinates":[lng,lat]} - 3. 坐标数组: [lng,lat] - 4. 简单对象: {"lng":116.3974,"lat":39.9093} 或 {"x":116.3974,"y":39.9093} - 5. WKT字符串: "POINT(lng lat)" - 6. PostgreSQL点格式: "(lng,lat)\""""); - } - - return result; + throw new IOException(""" + 不支持的 Point JSON 格式,支持的格式包括: + 1. 三字段格式: {"type":"point","longitude":116.3974,"latitude":39.9093} + 2. 自定义格式: {"type":"point","coordinates":[lng,lat]} + 3. GeoJSON格式: {"type":"Point","coordinates":[lng,lat]} + 4. 坐标数组: [lng,lat] + 5. 简化格式: {"longitude":116.3974,"latitude":39.9093} + 6. WKT字符串: "POINT(lng lat)" + 7. PostgreSQL点格式: "(lng,lat)" """); } catch (Exception e) { log.error("!!! PointDeserializer 反序列化失败 !!!"); @@ -84,6 +85,31 @@ public class PointDeserializer extends JsonDeserializer { return Point.class; } + /** + * 解析三字段格式:{"type":"point","longitude":116.3974,"latitude":39.9093} + */ + private Point parseFromThreeFields(JsonNode node) throws IOException { + String type = node.get("type").asText(); + if (!"point".equalsIgnoreCase(type)) { + throw new IOException("type 字段必须是 'point',当前是: " + type); + } + + JsonNode lngNode = node.get("longitude"); + JsonNode latNode = node.get("latitude"); + + if (lngNode == null || latNode == null) { + throw new IOException("longitude 或 latitude 字段缺失"); + } + + try { + double longitude = lngNode.asDouble(); + double latitude = latNode.asDouble(); + return geometryFactory.createPoint(new Coordinate(longitude, latitude)); + } catch (NumberFormatException e) { + throw new IOException("longitude/latitude 格式错误", e); + } + } + /** * 解析自定义格式:{"type":"point","coordinates":[lng,lat]} */ @@ -116,37 +142,23 @@ public class PointDeserializer extends JsonDeserializer { } /** - * 解析对象格式:{"lng":116.3974,"lat":39.9093} 或 {"x":116.3974,"y":39.9093} + * 解析简化格式:{"longitude":116.3974,"latitude":39.9093} */ - private Point parseFromObject(JsonNode node) throws IOException { - // 尝试 lng/lat 格式 - if (node.has("lng") && node.has("lat")) { - try { - double lng = node.get("lng").asDouble(); - double lat = node.get("lat").asDouble(); - return geometryFactory.createPoint(new Coordinate(lng, lat)); - } catch (NumberFormatException e) { - throw new IOException("lng/lat 格式错误: " + node, e); - } + private Point parseFromLongitudeLatitude(JsonNode node) throws IOException { + JsonNode lngNode = node.get("longitude"); + JsonNode latNode = node.get("latitude"); + + if (lngNode == null || latNode == null) { + throw new IOException("longitude 或 latitude 字段缺失"); } - - // 尝试 x/y 格式 - if (node.has("x") && node.has("y")) { - try { - double x = node.get("x").asDouble(); - double y = node.get("y").asDouble(); - return geometryFactory.createPoint(new Coordinate(x, y)); - } catch (NumberFormatException e) { - throw new IOException("x/y 格式错误: " + node, e); - } + + try { + double longitude = lngNode.asDouble(); + double latitude = latNode.asDouble(); + return geometryFactory.createPoint(new Coordinate(longitude, latitude)); + } catch (NumberFormatException e) { + throw new IOException("longitude/latitude 格式错误", e); } - - // 尝试 coordinates 格式 - if (node.has("coordinates")) { - return parseCoordinates(node.get("coordinates")); - } - - throw new IOException("对象格式不支持: " + node); } /** @@ -159,24 +171,24 @@ public class PointDeserializer extends JsonDeserializer { try { wktString = wktString.trim(); - + // 支持 PostgreSQL 点格式转换:(x,y) -> POINT(x y) if (wktString.startsWith("(") && wktString.endsWith(")")) { wktString = convertPostgresPointToWKT(wktString); } - + // 确保是有效的 WKT if (!wktString.toUpperCase().startsWith("POINT")) { wktString = "POINT(" + wktString + ")"; } - + WKTReader reader = new WKTReader(geometryFactory); Geometry geometry = reader.read(wktString); - + if (!(geometry instanceof Point)) { throw new IOException("WKT 字符串不是有效的 Point: " + wktString); } - + return (Point) geometry; } catch (Exception e) { throw new IOException("WKT 格式解析失败: " + wktString, e); @@ -202,7 +214,7 @@ public class PointDeserializer extends JsonDeserializer { try { double lng = coordinatesNode.get(0).asDouble(); double lat = coordinatesNode.get(1).asDouble(); - + return geometryFactory.createPoint(new Coordinate(lng, lat)); } catch (NumberFormatException e) { throw new IOException("坐标格式错误: " + coordinatesNode, e); @@ -215,17 +227,17 @@ public class PointDeserializer extends JsonDeserializer { private String convertPostgresPointToWKT(String pgPointString) { // PostgreSQL 格式: (x,y) 或 (x, y) // WKT 格式: POINT(x y) - + String cleaned = pgPointString - .replaceAll("\\s+", "") // 移除所有空格 - .replace("(", "") - .replace(")", ""); - + .replaceAll("\\s+", "") // 移除所有空格 + .replace("(", "") + .replace(")", ""); + String[] coords = cleaned.split(","); if (coords.length >= 2) { return "POINT(" + coords[0] + " " + coords[1] + ")"; } - + return pgPointString; // 无法转换,返回原值 } } \ No newline at end of file diff --git a/ebike-operations/src/main/java/com/cdzy/operations/handler/PointSerializer.java b/ebike-operations/src/main/java/com/cdzy/operations/handler/PointSerializer.java index 07e7aa8..1acbb27 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/handler/PointSerializer.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/handler/PointSerializer.java @@ -14,18 +14,18 @@ import java.util.Locale; /** * JTS Point 序列化器 - 将 Point 序列化为 JSON - * 生成一致的 JSON 格式 + * 输出 type、longitude、latitude 三个字段 */ @Slf4j public class PointSerializer extends JsonSerializer { - private static final DecimalFormat COORD_FORMAT = new DecimalFormat("#.##########", - DecimalFormatSymbols.getInstance(Locale.US)); - + private static final DecimalFormat COORD_FORMAT = new DecimalFormat("#.##########", + DecimalFormatSymbols.getInstance(Locale.US)); + private final WKTWriter wktWriter = new WKTWriter(); @Override - public void serialize(Point point, JsonGenerator gen, SerializerProvider serializers) + public void serialize(Point point, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (point == null) { gen.writeNull(); @@ -35,22 +35,18 @@ public class PointSerializer extends JsonSerializer { try { // 获取坐标 Coordinate coordinate = point.getCoordinate(); - + if (coordinate == null || Double.isNaN(coordinate.x) || Double.isNaN(coordinate.y)) { log.warn("警告: 点坐标无效: {}", coordinate); gen.writeNull(); return; } - // 序列化为自定义格式(与 PolygonSerializer 格式一致) + // 序列化为三字段格式:type、longitude、latitude gen.writeStartObject(); gen.writeStringField("type", "point"); - - gen.writeArrayFieldStart("coordinates"); - gen.writeNumber(formatCoordinate(coordinate.x)); - gen.writeNumber(formatCoordinate(coordinate.y)); - gen.writeEndArray(); - + gen.writeNumberField("longitude", formatCoordinate(coordinate.x)); + gen.writeNumberField("latitude", formatCoordinate(coordinate.y)); gen.writeEndObject(); } catch (Exception e) { @@ -58,7 +54,7 @@ public class PointSerializer extends JsonSerializer { log.error("错误信息: {}", e.getMessage()); // 尝试备用序列化方式 try { - serializeAsSimpleObject(point, gen); + serializeAsAlternativeFormat(point, gen); } catch (Exception e2) { throw new IOException("Point 序列化失败: " + e.getMessage(), e); } @@ -79,9 +75,9 @@ public class PointSerializer extends JsonSerializer { } /** - * 备用序列化方式:序列化为简单对象格式 + * 备用序列化方式:序列化为 coordinates 数组格式 */ - private void serializeAsSimpleObject(Point point, JsonGenerator gen) throws IOException { + private void serializeAsAlternativeFormat(Point point, JsonGenerator gen) throws IOException { if (point == null || point.isEmpty()) { gen.writeNull(); return; @@ -89,16 +85,21 @@ public class PointSerializer extends JsonSerializer { try { Coordinate coordinate = point.getCoordinate(); - - // 方式1:简单对象格式 {"lng":116.3974,"lat":39.9093} + + // 方式1:coordinates 数组格式 gen.writeStartObject(); - gen.writeNumberField("lng", coordinate.x); - gen.writeNumberField("lat", coordinate.y); + gen.writeStringField("type", "point"); + + gen.writeArrayFieldStart("coordinates"); + gen.writeNumber(coordinate.x); + gen.writeNumber(coordinate.y); + gen.writeEndArray(); + gen.writeEndObject(); - + } catch (Exception e) { - log.error("简单对象序列化失败: {}", e.getMessage()); - + log.error("备用序列化失败: {}", e.getMessage()); + // 最终备用:序列化为 WKT 字符串 try { String wkt = wktWriter.write(point); @@ -127,7 +128,7 @@ public class PointSerializer extends JsonSerializer { } Coordinate coordinate = point.getCoordinate(); - return "(" + getFormattedCoordinateString(coordinate.x) + - "," + getFormattedCoordinateString(coordinate.y) + ")"; + return "(" + getFormattedCoordinateString(coordinate.x) + + "," + getFormattedCoordinateString(coordinate.y) + ")"; } } \ No newline at end of file