如何解决Cosmos DB 序列化问题引发错误将 Int 读取为 Double
在我的某些文档中,我的 .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,JsonContainerContract containerContract,JsonProperty containerMember,Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader,Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader,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
````
解决方法
根据您的评论:
如果我进入门户并重新保存文档,则一切正常
这表明该项目上次修改的任何内容都可能引入了一些不正确的编码,而不是真正的 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}");
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。