Microsoft.Azure.Cosmos.Spatial 反序列化点坐标时出错

问题描述

我正在尝试将地理空间数据存储在名为 Trips 的 Cosmos db 容器中,并从我的 .net core web api (.net 5) 中检索项目。我正在使用 Microsoft.Azure.Cosmos (3.19.0) 并且没有为序列化明确配置任何内容。保存有效,但当我尝试检索时出现此错误

Newtonsoft.Json.JsonSerializationException:无法反序列化 Geometry 对象,因为“type”属性不存在或值无效。

Cosmos 客户端实例:

   var options = new CosmosClientOptions()
    {
       AllowBulkExecution = true,SerializerOptions = new CosmosSerializationoptions()
       {
          PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
       }
    };
    var cosmosClient = new CosmosClient(account,key,options);

型号:

public class Trip
    {
        [JsonPropertyName("id"),required]
        public string Id { get; set; }

        [JsonPropertyName("vehicleId"),required]
        public string VehicleId { get; set; }

        [JsonPropertyName("startDateTime"),required]
        public DateTime StartDateTime { get; set; }

        [JsonPropertyName("endDateTime"),required]
        public DateTime EndDateTime { get; set; }

        [JsonPropertyName("wayPoints"),required]
        public List<WayPoint> WayPoints { get; set; }
    }

    public class WayPoint
    {
        [JsonPropertyName("timeStamp"),required]
        public DateTime TimeStamp { get; set; }

        [JsonPropertyName("point"),required]
        public Point Point { get; set; }
    }

服务:

public async Task<IEnumerable<Trip>> GetMultipleAsync(string vehicleId = "")
{
   var queryDeFinition = new QueryDeFinition($"Select * from c where c.vehicleId = \"{vehicleId}\"");
   var queryIterator = _container.GetItemQueryIterator<Trip>(queryDeFinition);
    
   var trips = new List<Trip>();
   while(queryIterator.HasMoreResults)
   {
      var response = await queryIterator.ReadNextAsync();
      trips.AddRange(response.ToList());
   }
   return trips;
}

控制器:

using FileStream createStream = System.IO.File.Create(@"C:\repos\TripGenerator\trips.json");
await JsonSerializer.SerializeAsync(
 createStream,trips);

Json 示例:

{
    "id": "a9153ca0-e171-4fe8-bcfe-733ac75f6b85","vehicleId": "599abc63-eafb-4015-ac65-fc6aed48d9aa","startDateTime": "2021-06-17T00:00:00Z","endDateTime": "2021-06-17T23:55:00Z","wayPoints": [
        {
            "timeStamp": "2021-06-17T00:00:00Z","point": {
                "Position": {
                    "Coordinates": [
                        51.23156579100001,-0.603818000999999
                    ],"Longitude": 77.23156579100001,"Latitude": 12.016038180009999,"Altitude": null
                },"Crs": {
                    "Type": 0
                },"Type": 0,"BoundingBox": null,"AdditionalProperties": {}
            }
        },{
            "timeStamp": "2021-06-17T00:05:00Z","point": {
                "Position": {
                    "Coordinates": [
                        51.23159449100001,-0.01703846700999
                    ],"Longitude": 77.23159449100001,"Latitude": 12.603846700999998,////////////
        {
            "timeStamp": "2021-06-17T23:55:00Z","point": {
                "Position": {
                    "Coordinates": [
                        51.23980269100042,-0.01961205490099
                    ],"Longitude": 77.23980269100042,"Latitude": 12.612054900999901,"AdditionalProperties": {}
            }
        }
    ],}

任何帮助将不胜感激。谢谢!

解决方法

问题似乎出在您使用的套管配置上:

PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase

您的 Json 显示“Point”的“Type”属性存在,但错误中的大小写显示“type”(小写 T)。

V3 SDK (https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos/src/Spatial/Geometry.cs#L70) 中的 Geometry 类型将 Type 定义为“type”:

[DataMember(Name = "type")]
[JsonProperty("type",Required = Required.Always,Order = 0)]
[JsonConverter(typeof(StringEnumConverter))]
public GeometryType Type { get; private set; }

所以通常我们希望它被序列化/保存为“类型”,而不是“类型”。

PropertyNamingPolicy 在保存文档时将其序列化为“Type”,或者使用不同的 SDK/工具保存文档,该 SDK/工具将几何体序列化为“Type”。

这就是抛出这个异常的原因。