在反序列化具有$id的对象时获得JsonSerializationException



我有一个preserverreferenceshandling。所有这些都是在JSON序列化器设置上设置的,这使得使用自动生成的$id创建数据,并且似乎会导致数据的反序列化错误。

我有一个代码片段,我已经能够重现一个错误。您可以在本地机器上运行它并尝试:

class Program
{
static async Task Main(string[] args)
{
CosmosClient client = new CosmosClient("https://xxxx.documents.azure.com:443/", 
new DefaultAzureCredential(), GetCosmosClientOptions());
string databaseId = "Test";
var database = client.GetDatabase(databaseId);
string collectionId = "Test";
var container = database.GetContainer(collectionId);
var requestOptions = new QueryRequestOptions();
var entity = new Entity
{
id = Guid.NewGuid().ToString(),
Name = "test",
Comments = new List<Detail>(),
Item = new Item
{
itemid = "7"
}
};
await container.CreateItemAsync(entity);
//var baseQuery = container.GetItemLinqQueryable<Entity>(requestOptions: requestOptions);
//using (var setIterator = baseQuery.ToFeedIterator())
//{
//    while (setIterator.HasMoreResults)
//    {
//        foreach (var item in await setIterator.ReadNextAsync())
//        {
//        }
//    }
//}
}
protected static CosmosClientOptions GetCosmosClientOptions()
{
var cosmosClientOptions = new CosmosClientOptions()
{
ConnectionMode = ConnectionMode.Direct,
Serializer = new CosmosJsonNetSerializer(new JsonSerializerSettings()
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
PreserveReferencesHandling = PreserveReferencesHandling.All,
NullValueHandling = NullValueHandling.Include,
TypeNameHandling = TypeNameHandling.None,
})
};
return cosmosClientOptions;
}
}
public class Entity
{
public string id;
public string Name;
public Item Item;
public List<Detail> Comments;
}
public class Item
{
public string itemid;
}
public class Comment
{
public string id;
}
public class Detail
{
public string detailId;
}

上面代码片段中的CosmosJsonNetSerializer是一个自定义序列化器。源代码在这里:https://pastebin.com/jSNfzUpa

如果运行上述代码,上面代码中的create语句将抛出一个错误:

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CosmosErrorDebugging.Detail]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'Comments.$id', line 1, position 119.'

然而,文档将成功创建。下面是它创建的文档,注意自动生成的$id:

{
"id": "da82f504-ebbd-4e4c-8e02-a5e454f52435",
"$id": "1",
"Name": "test",
"Item": {
"itemid": "7"
},
"Comments": []
}

然后,注释掉上面代码片段中的create行并取消注释以执行读取操作:

//await container.CreateItemAsync(entity);
var baseQuery = container.GetItemLinqQueryable<Entity>(requestOptions: requestOptions);
using (var setIterator = baseQuery.ToFeedIterator())
{
while (setIterator.HasMoreResults)
{
foreach (var item in await setIterator.ReadNextAsync())
{
}
}
}

在setterator . readnextasync ()

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CosmosErrorDebugging.Detail]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path '[6].Comments.$id', line 1, position 1876.'

问题是我已经有很多数据与$id。我需要读取工作没有抛出任何错误。我尝试设置preserverreferenceshandling。没有,但我仍然得到相同的错误,已经创建的数据与$id。

编辑以下是异常的详细信息:

Exception: {"Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CosmosErrorDebugging.Detail]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path '[6].Comments.$id', line 1, position 1876."}
Data: {System.Collections.ListDictionaryInternal}
HResult: -2146233088
Helplink: null
Inner Exception: null
Message: "Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CosmosErrorDebugging.Detail]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path '[6].Comments.$id', line 1, position 1876."
Source: "Newtonsoft.Json"
Stacktrace: "   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.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
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.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
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[T](JsonReader reader)
at Azure4Educators.Business.Utilities.CosmosJsonNetSerializer.FromStream[T](Stream stream) in C:\Users\...\source\repos\CosmosErrorDebugging\CosmosErrorDebugging\Class2.cs:line 40
at Microsoft.Azure.Cosmos.CosmosJsonSerializerWrapper.FromStream[T](Stream stream)
at Microsoft.Azure.Cosmos.CosmosSerializerCore.FromFeedStream[T](Stream stream)
at Microsoft.Azure.Cosmos.CosmosFeedResponseSerializer.FromFeedResponseStream[T](CosmosSerializerCore serializerCore, Stream streamWithServiceEnvelope)
at Microsoft.Azure.Cosmos.ReadFeedResponse`1.CreateResponse[TInput](ResponseMessage responseMessage, CosmosSerializerCore serializerCore)
at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.CreateQueryFeedResponseHelper[T](ResponseMessage cosmosResponseMessage)
at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.CreateQueryFeedUserTypeResponse[T](ResponseMessage responseMessage)
at Microsoft.Azure.Cosmos.FeedIteratorCore`1.<ReadNextAsync>d__8.MoveNext()"

此错误表示您返回一个对象并反序列化为列表如果你返回一个json对象,写为:

Entity _entity=Newtonsoft.Json.JsonConvert.DeserializeObject<Entity>(json_file);

返回多个对象:

List<Entity> _entites=Newtonsoft.Json.JsonConvert.DeserializeObject<List<Entity>>(json_file);

最新更新