如何将 GeoJSON 数据绑定到 ASP.NET Core 中的参数?

How can I bind GeoJSON data to parameters in ASP.NET Core?

在 GeoJSON 中,相同的属性 coordinates 可以是数组或数组的数组。

如何为同一个 json 对象定义相同的属性名称但不同的类型?

public class Geometry
{
    public string type { get; set; }

    [BsonElement("coordinates")]
    public List<List<List<double>>> coordinates { get; set; }

    [BsonElement("coordinates")]
    public List<List<List<List<double>>>> coordinates { get; set; }
}

坐标可以是 4d 或 3d,我该如何处理这种可变性?

示例:

{
        "type": "Polygon",
        "coordinates": [
            [
                [
                    [
                        51.263632,
                        60.962938
                    ],
                    [
                        30.884274,
                        20.065517
                    ],
                    [
                        68.832044,
                        14.362602
                    ],
                    [
                        51.263632,
                        60.962938
                    ]
                ]
            ]
        ]
}

{
    "type": "MultiPolygon",
    "coordinates": [
        [
            [
                [
                    43.182162,
                    64.042209
                ],
                [
                    14.721334,
                    22.358269
                ],
                [
                    51.263632,
                    17.738761
                ],
                [
                    43.182162,
                    64.042209
                ]
            ]
        ],
        [
            [
                [
                    55.831419,
                    51.446822
                ],
                [
                    65.66973,
                    20.065517
                ],
                [
                    97.64424,
                    37.509124
                ],
                [
                    55.831419,
                    51.446822
                ]
            ]
        ]
    ]
}

我的行动是

[HttpPost]
public IActionResult<Geometry> Create(Geometry layer)
{
    _layerService.Create(layer);
    
    return NoContent();
}

不要尝试自己动手 类。这不是一步就能完成的事情,你最终得到的 类 在空间场景中也不容易使用。最好使用公共空间 类 和一个可以序列化它们的库。

即使您自己推出,创建将您的空间 类 映射到地理 [=] 的自定义 JSON 转换器也会 容易很多 59=].

NetTopologySuite,几乎是 .NET Core 中空间数据的实际标准,已经发布了使用 JSON.NET 的 NetTopologySuite.IO.GeoJSON4STJ package that serializes NTS classes to GeoJSON using System.Text.Json. At 84K downloads it's not as popular as the 1.4M downloads of NetTopologySuite.IO.GeoJSON,但它完成了工作。

repo landing page 展示了如何使用 GeoJSON4STJ 将 GeoJSON 有效负载绑定到 类 中的 Geometry 参数,方法是添加自定义转换器:

services.AddControllers()
  .AddJsonOptions(options => {
        options.JsonSerializerOptions.Converters.Add(
            new NetTopologySuite.IO.Converters.GeoJsonConverterFactory());
  });

NTS 类 被 EF Core itself for Spatial data 使用,因此最好使用 这些 而不是创建新的 类。

着陆页也显示 how to (de)serialize JSON text

var geoJson = "{\"type\":\"Point\",\"coordinates\":[0.0,0.0]}";
Geometry geometry;

var serializer = GeoJsonSerializer.Create();
using var stringReader = new StringReader(geoJson);
using var jsonReader = new JsonTextReader(stringReader);

var geometry = serializer.Deserialize<Geometry>(jsonReader);

var geometry = new Point(0, 0);

var serializer = GeoJsonSerializer.Create();
using var stringWriter = new StringWriter();
using var jsonWriter = new JsonTextWriter(stringWriter);

serializer.Serialize(jsonWriter, geometry);
var geoJson = stringWriter.ToString();

GeoJsonSerializer.Create() 方法只是使用 GeoJSON 转换器创建一个新的 JsonSerializer

    public new static JsonSerializer Create()
    {
        return CreateDefault();
    }

    public new static JsonSerializer CreateDefault()
    {
        var s = JsonSerializer.CreateDefault();
        s.NullValueHandling = NullValueHandling.Ignore;

        AddGeoJsonConverters(s, Wgs84Factory, 2, false, null);
        return s;
    }

创建你自己的

如果您决定创建自己的 GeoJSON 转换器,很好 的起点是 check the GeoJSON4STJ converters。不仅有一个转换器,每种类型都有不同的转换器,或者更确切地说,类型类别。坐标、数组和单个特征有不同的转换器。这使得序列化 lot 变得更容易和更快。阅读 type 后,您就会知道如何处理对象的其他属性。

另一种选择是将整个 JSON 字符串作为 JsonDocument 加载,并使用访问者遍历所有节点并根据它们的 type 解析它们。由于 JsonDocument 本质上是源数据的副本,因此速度较慢并且使用更多内存。