Cosmos DB 序列化问题引发错误,将 Int 读取为 Double
Posted
技术标签:
【中文标题】Cosmos DB 序列化问题引发错误,将 Int 读取为 Double【英文标题】:Cosmos DB Serialization Issue Throws Error Reading An Int as Double 【发布时间】:2021-05-02 08:41:58 【问题描述】:在我的一些文档中,我的 .NET Cosmos Db 客户端 (v3) 不会读取文档。该文档有一个属性 DistanceInMetres,并在我的类中设置为一个 int。
public int DistanceInMetres get; set;
当我检查导致此错误的文档之一(有很多)时,属性设置正确。
"distanceInMetres": 3272,
我收到的错误是:
Input string '3272.0' is not a valid integer. Path 'distanceInMetres', line 1, position 1586.
这是执行请求的代码:
public async Task<T> ReadEntityAsync<T>(string id, string pKey)
var doc= await container.ReadItemAsync<T>(id, new PartitionKey(pKey));
return doc;
序列化错误不依赖于客户端查询,它发生在 Container.Read 以及针对多个文档的 Container.Query 上。我尝试将底层模型属性从 int 更改为 double 我仍然得到同样的错误!我已经检查了具有相同模型的其他文档,这些文档返回时没有错误,看看是否有任何差异但没有(我可以看到)。如果我进入门户并手动更改属性,同时保持值相同并更新文档,则会出现错误。 我不认为这是通过单个和多个查询发生的数据访问问题。 这是 CosmosDB 上的错误吗?有人有什么想法吗?
作为更新: 当我使用 DocumentClient 访问数据库时:
DocumentClient documentClient = new DocumentClient(new
Uri("url"),"Key",
serializerSettings: new JsonSerializerSettings ContractResolver = new
CamelCasePropertyNamesContractResolver() ) ;
文档被毫无例外地读取。
当我使用 CosmosClient 时:
CosmosClient cosmo = new
CosmosClient(config["keys:cosmosClientConStr"], new CosmosClientOptions
ConnectionMode = ConnectionMode.Direct,
SerializerOptions = new CosmosSerializationOptions
PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
);
Container container = cosmo.GetContainer(config["keys:dbName"],
config["keys:colName"]);
我在某些文档上遇到了异常。奇怪的是,如果我进入门户并重新保存文档,一切正常。 更新:如果我将类类型从 T 更改为 Dynamic 我可以读回该项目 即使它存储为整数,它也确实被读取为小数。 这是堆栈跟踪。
at Newtonsoft.Json.JsonTextReader.ParseReadNumber(ReadType readType, Char firstChar, Int32 initialPosition)
at Newtonsoft.Json.JsonTextReader.ParseNumber(ReadType readType)
at Newtonsoft.Json.JsonTextReader.ReadNumberValue(ReadType readType)
at Newtonsoft.Json.JsonTextReader.ReadAsInt32()
at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)
at Microsoft.Azure.Cosmos.CosmosJsonDotNetSerializer.FromStream[T](Stream stream)
at Microsoft.Azure.Cosmos.CosmosJsonSerializerWrapper.FromStream[T](Stream stream)
at Microsoft.Azure.Cosmos.CosmosJsonSerializerWrapper.FromStream[T](Stream stream)
at Microsoft.Azure.Cosmos.CosmosSerializerCore.FromStream[T](Stream stream)
at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.ToObjectpublic[T](ResponseMessage responseMessage)
at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.<CreateItemResponse>b__8_0[T](ResponseMessage cosmosResponseMessage)
at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.ProcessMessage[T](ResponseMessage responseMessage, Func`2 createResponse)
at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.CreateItemResponse[T](ResponseMessage responseMessage)
at Microsoft.Azure.Cosmos.ContainerCore.<ReadItemAsync>d__56`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Microsoft.Azure.Cosmos.ClientContextCore.<RunWithDiagnosticsHelperAsync>d__38`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at CT5ApiService.ApiData.CosmosStore.<ReadEntityAsync>d__4`1.MoveNext() in C:\Users\pjsta\source\repos\CT_CLOUD\CT5ApiService\ApiData\CosmosStore.cs:line 81
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at CT5ApiService.Api.JobsApi.<Get>d__3.MoveNext() in C:\Users\pjsta\source\repos\CT_CLOUD\CT5ApiService\Api\JobsApi.cs:line 49
````
【问题讨论】:
所有文档的创建方式都相同吗?还是问题仅限于特定用户/进程/客户创建的文档? 该属性在数据库中不是小数,并且存储为整数,这似乎很奇怪。JsonConvert
通话是否使用任何文化?
请显示产生错误的相关代码。
不,我没有使用 db 在英国南部的任何文化,我也是。
【参考方案1】:
鉴于您的评论:
如果我进入门户并重新保存文档,一切正常
这表明该项目的最后修改可能会引入一些不正确的编码,这些编码不是真正的 UTF-8 整数值。您的重新保存更正了编码。隐藏字符会导致serialization problems。
更强大的方法是使用ReadItemStreamAsync
SDK 方法读取原始Stream
,然后在流上使用System.Text.Json.JsonSerializer.DeserializeAsync
或JsonConvert
转换为项目。然后您就有机会检查原始值并处理出现的任何异常。
samples repo 中显示了一个示例:
using (ResponseMessage responseMessage = await container.ReadItemStreamAsync(
partitionKey: new PartitionKey("Account1"),
id: "SalesOrder1"))
// Item stream operations do not throw exceptions for better performance
if (responseMessage.IsSuccessStatusCode)
SalesOrder streamResponse = FromStream<SalesOrder>(responseMessage.Content);
Console.WriteLine($"\n1.2.2 - Item Read streamResponse.Id");
// Log the diagnostics
Console.WriteLine($"\n1.2.2 - Item Read Diagnostics: responseMessage.Diagnostics.ToString()");
else
Console.WriteLine($"Read item from stream failed. Status code: responseMessage.StatusCode Message: responseMessage.ErrorMessage");
【讨论】:
不幸的是,这一行抛出了同样的错误。 - .return Serializer.Deserialize以上是关于Cosmos DB 序列化问题引发错误,将 Int 读取为 Double的主要内容,如果未能解决你的问题,请参考以下文章
将Cosmos DB模拟器(MongoDB API)迁移到Azure时发生致命错误
带有 Cosmos DB 绑定的 Azure 函数返回格式化的 DateTime?
Cosmos db Rest API - 错误 401 未经授权
在 cosmos db 和 asp.net core 中处理请求时发生未处理的异常