将SQLGeography多边形重新格式化为JSON

Jam*_*mes 8 c# json geojson sqlgeography wkt

我正在构建一个以JSON格式提供地理边界数据的Web服务.

地理数据使用表中的地理类型存储在SQL Server 2008 R2数据库中.我使用[ColumnName].ToString()方法将多边形数据作为文本返回.

示例输出:

POLYGON ((-6.1646509904325884 56.435153006374627, ... -6.1606079906751 56.4338050060666))

MULTIPOLYGON (((-6.1646509904325884 56.435153006374627 0 0, ... -6.1606079906751 56.4338050060666 0 0)))
Run Code Online (Sandbox Code Playgroud)

地理定义可以采用定义多边形的纬度/长度对数组的形式,或者在多个定义的情况下,采用数组或多边形(多边形).

我有以下正则表达式,根据输出将输出转换为多维数组中包含的JSON对象.

Regex latlngMatch = new Regex(@"(-?[0-9]{1}\.\d*)\s(\d{2}.\d*)(?:\s0\s0,?)?", RegexOptions.Compiled);

    private string ConvertPolysToJson(string polysIn)
    {
        return this.latlngMatch.Replace(polysIn.Remove(0, polysIn.IndexOf("(")) // remove POLYGON or MULTIPOLYGON
                                               .Replace("(", "[")  // convert to JSON array syntax
                                               .Replace(")", "]"), // same as above
                                               "{lng:$1,lat:$2},"); // reformat lat/lng pairs to JSON objects
    }
Run Code Online (Sandbox Code Playgroud)

这实际上工作得很好,并且在响应操作调用时动态地将DB输出转换为JSON.

然而,我不是正则表达式大师,而且String.Replace()对我来说效率似乎也低效.

有没有人对此表现有任何建议/意见?

Jam*_*mes 11

再次只是为了关闭这个我将用我正在使用的解决方案回答我自己的问题.

此方法接受来自ToString()MS SQL上的调用的输出Geography Type.如果返回的字符串包含由GPS点构成的多边形数据,则此方法将解析并将其重新格式化为JSON sting.

public static class PolyConverter
{
    static Regex latlngMatch = new Regex(@"(-?\d{1,2}\.\dE-\d+|-?\d{1,2}\.?\d*)\s(-?\d{1,2}\.\dE-\d+|-?\d{1,2}\.?\d*)\s?0?\s?0?,?", RegexOptions.Compiled);
    static Regex reformat = new Regex(@"\[,", RegexOptions.Compiled);

    public static string ConvertPolysToJson(string polysIn)
    {
        var formatted = reformat.Replace(
                        latlngMatch.Replace(
                        polysIn.Remove(0, polysIn.IndexOf("(")), ",{lng:$1,lat:$2}")
                        .Replace("(", "[")
                        .Replace(")", "]"), "[");

        if (polysIn.Contains("MULTIPOLYGON"))
        {
            formatted = formatted.Replace("[[", "[")
                                 .Replace("]]", "]")
                                 .Replace("[[[", "[[")
                                 .Replace("]]]", "]]");
        }

        return formatted;
    }
}
Run Code Online (Sandbox Code Playgroud)

这特定于我的应用,但可能对某人有用,甚至可能创建更好的实现.


Ale*_*lex 8

要从WKT转换为GeoJson,您可以使用nuget的NetTopologySuite.添加NetTopologySuiteNetTopologySuite.IO.GeoJSON

var wkt = "POLYGON ((10 20, 30 40, 50 60, 10 20))";
var wktReader = new NetTopologySuite.IO.WKTReader();
var geom = wktReader.Read(wkt);
var feature = new NetTopologySuite.Features.Feature(geom, new NetTopologySuite.Features.AttributesTable());
var featureCollection = new NetTopologySuite.Features.FeatureCollection();
featureCollection.Add(feature);
var sb = new StringBuilder();
var serializer = new NetTopologySuite.IO.GeoJsonSerializer();
serializer.Formatting = Newtonsoft.Json.Formatting.Indented;
using (var sw = new StringWriter(sb))
{
    serializer.Serialize(sw, featureCollection);
}
var result = sb.ToString();
Run Code Online (Sandbox Code Playgroud)

输出:

{
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              10.0,
              20.0
            ],
            [
              30.0,
              40.0
            ],
            [
              50.0,
              60.0
            ],
            [
              10.0,
              20.0
            ]
          ]
        ]
      },
      "properties": {}
    }
  ],
  "type": "FeatureCollection"
}
Run Code Online (Sandbox Code Playgroud)

  • 吉普车,太棒了。谢谢你!这个应该是最上面的。 (2认同)

小智 6

要回答有关效率的问题,对于这种特殊情况,我认为Replace vs RegEx不会有太大的区别。我们真正要更改的只是一些括号和逗号。就个人而言,我更喜欢在TSQL中为Web应用程序执行操作,因为我可以将计算工作卸载到SQL Server而不是Web Server上。就我而言,我为地图生成了很多数据,因此不想在Web服务器上进行大量数据转换。此外,为了提高性能,通常在SQL Server上比在Web服务器上具有更多的功能,因此即使两个功能之间存在某些差异,如果使用Replace,效率较低,至少是由具有更多资源的服务器处理的。通常,我希望我的Web服务器处理与客户端的连接,而我希望SQL Server处理数据计算。这也使我的Web服务器脚本保持干净高效。所以我的建议如下:

在您的数据库中编写一个Scalar TSQL函数。这使用了SQL REPLACE函数,虽然有点蛮力,但它确实表现不错。如果您确实想简化Web服务器代码,则可以直接在SELECT语句上使用此函数,也可以在表中创建计算列。当前,该示例仅支持POINT,POLYGON和MULTIPOLYGON,并为geoJSON格式提供“ geometry” JSON元素。

GetGeoJSON标量函数

CREATE FUNCTION GetGeoJSON (@geo geography) /*this is your geography shape*/
RETURNS varchar(max)
WITH SCHEMABINDING /*this tells SQL SERVER that it is deterministic (helpful if you use it in a calculated column)*/
AS
BEGIN
/* Declare the return variable here*/
DECLARE @Result varchar(max)

/*Build JSON "geometry" element for geoJSON*/

SELECT  @Result = '"geometry":{' +
    CASE @geo.STGeometryType()
        WHEN 'POINT' THEN
            '"type": "Point","coordinates":' +
            REPLACE(REPLACE(REPLACE(REPLACE(@geo.ToString(),'POINT ',''),'(','['),')',']'),' ',',')
        WHEN 'POLYGON' THEN 
            '"type": "Polygon","coordinates":' +
            '[' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@geo.ToString(),'POLYGON ',''),'(','['),')',']'),'], ',']],['),', ','],['),' ',',') + ']'
        WHEN 'MULTIPOLYGON' THEN 
            '"type": "MultiPolygon","coordinates":' +
            '[' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@geo.ToString(),'MULTIPOLYGON ',''),'(','['),')',']'),'], ',']],['),', ','],['),' ',',') + ']'
    ELSE NULL
    END
    +'}'

    /* Return the result of the function*/
    RETURN @Result

END
Run Code Online (Sandbox Code Playgroud)

接下来,GetGeoJSONSELECT语句中使用您的函数,例如:

SELECT dbo.GetGeoJSON([COLUMN]) as Geometry From [TABLE]
Run Code Online (Sandbox Code Playgroud)

我希望这能提供一些见识并帮助其他人寻找方法,祝您好运!