package com.cdzy.operations.handler; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import org.postgresql.geometric.PGpoint; import org.postgresql.geometric.PGpolygon; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * PGpolygon 反序列化器 - 将 JSON 反序列化为 PGpolygon */ public class PGpolygonDeserializer extends JsonDeserializer { @Override public PGpolygon deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); if (node.isNull()) { return null; } try { // 支持多种 JSON 格式 // 格式1: 自定义格式 {"type": "polygon", "coordinates": [[x1,y1], [x2,y2], ...]} if (node.isObject() && node.has("type") && "polygon".equals(node.get("type").asText())) { return parseFromCustomFormat(node); } // 格式2: GeoJSON 格式 {"type": "Polygon", "coordinates": [[[x1,y1], [x2,y2], ...]]} if (node.isObject() && node.has("type") && "Polygon".equals(node.get("type").asText())) { return parseFromGeoJSON(node); } // 格式3: 直接坐标数组 [[x1,y1], [x2,y2], ...] if (node.isArray()) { return parseFromArray(node); } // 格式4: 字符串格式 "((x1 y1, x2 y2, ...))" if (node.isTextual()) { return parseFromString(node.asText()); } throw new IOException("不支持的 PGpolygon JSON 格式"); } catch (Exception e) { throw new IOException("PGpolygon 反序列化失败: " + e.getMessage(), e); } } @Override public Class handledType() { return PGpolygon.class; } /** * 解析自定义格式 */ private PGpolygon parseFromCustomFormat(JsonNode node) throws IOException { JsonNode coordinatesNode = node.get("coordinates"); if (coordinatesNode == null || !coordinatesNode.isArray()) { throw new IOException("coordinates 字段缺失或格式错误"); } List points = new ArrayList<>(); for (JsonNode coordNode : coordinatesNode) { if (coordNode.isArray() && coordNode.size() >= 2) { double x = coordNode.get(0).asDouble(); double y = coordNode.get(1).asDouble(); points.add(new PGpoint(x, y)); } } return createPGpolygonFromPoints(points); } /** * 解析 GeoJSON 格式 */ private PGpolygon parseFromGeoJSON(JsonNode node) throws IOException { JsonNode coordinatesNode = node.get("coordinates"); if (coordinatesNode == null || !coordinatesNode.isArray() || coordinatesNode.isEmpty()) { throw new IOException("coordinates 字段缺失或格式错误"); } // GeoJSON 格式: coordinates 是三维数组 [[[x1,y1], [x2,y2], ...]] JsonNode ringNode = coordinatesNode.get(0); if (!ringNode.isArray()) { throw new IOException("GeoJSON coordinates 格式错误"); } List points = new ArrayList<>(); for (JsonNode coordNode : ringNode) { if (coordNode.isArray() && coordNode.size() >= 2) { double x = coordNode.get(0).asDouble(); double y = coordNode.get(1).asDouble(); points.add(new PGpoint(x, y)); } } return createPGpolygonFromPoints(points); } /** * 解析坐标数组格式 */ private PGpolygon parseFromArray(JsonNode node) throws IOException { List points = new ArrayList<>(); for (JsonNode coordNode : node) { if (coordNode.isArray() && coordNode.size() >= 2) { double x = coordNode.get(0).asDouble(); double y = coordNode.get(1).asDouble(); points.add(new PGpoint(x, y)); } } return createPGpolygonFromPoints(points); } /** * 解析字符串格式 */ private PGpolygon parseFromString(String polygonString) throws IOException { try { return new PGpolygon(polygonString); } catch (Exception e) { throw new IOException("PGpolygon 字符串格式解析失败: " + polygonString, e); } } /** * 从点列表创建 PGpolygon */ private PGpolygon createPGpolygonFromPoints(List points) throws IOException { if (points == null || points.size() < 3) { throw new IOException("多边形至少需要3个点"); } try { // 构建多边形字符串格式:((x1 y1, x2 y2, x3 y3, x1 y1)) StringBuilder sb = new StringBuilder("(("); for (int i = 0; i < points.size(); i++) { PGpoint point = points.get(i); sb.append(point.x).append(" ").append(point.y); if (i < points.size() - 1) { sb.append(", "); } } // 确保多边形闭合(首尾点相同) PGpoint firstPoint = points.get(0); PGpoint lastPoint = points.get(points.size() - 1); if (firstPoint.x != lastPoint.x || firstPoint.y != lastPoint.y) { sb.append(", ").append(firstPoint.x).append(" ").append(firstPoint.y); } sb.append("))"); return new PGpolygon(sb.toString()); } catch (Exception e) { throw new IOException("创建 PGpolygon 失败", e); } } }