LINQ queries doesn't use custom CosmosSerializer
See original GitHub issueWe are continuously addressing and improving the SDK, if possible, make sure the problem persist in the latest SDK version.
Describe the bug I need to use custom serializer (implementing serialization with System.Text.Json) for CosmosClient I decorate properties of my classes with JsonPropertyName attribute to translate class property names to attribute names of documents in my database. But SQL queries created from LINQ queries contains original property names, not names from JsonPropertyName.
To Reproduce
- Create documents in database with column names e.g. id, project_id
- Create C# project with class:
public record MyItem
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("project_id")]
public string ProjectId { get; set; }`
}
- Write custom serializer using System.Text.Json:
public class CosmosSystemTextJsonSerializer : CosmosSerializer
{
private readonly JsonObjectSerializer _systemTextJsonSerializer;
public CosmosSystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions)
{
_systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions);
}
public override T FromStream<T>(Stream stream)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
using (stream)
{
if (stream.CanSeek && stream.Length == 0)
{
return default;
}
if (typeof(Stream).IsAssignableFrom(typeof(T)))
{
return (T)(object)stream;
}
return (T)this._systemTextJsonSerializer.Deserialize(stream, typeof(T), default);
}
}
public override Stream ToStream<T>(T input)
{
MemoryStream streamPayload = new MemoryStream();
_systemTextJsonSerializer.Serialize(streamPayload, input, typeof(T), default);
streamPayload.Position = 0;
return streamPayload;
}
}
- Create CosmosClient with custom serializer:
var cosmosSystemTextJsonSerializer = new CosmosSystemTextJsonSerializer(new JsonSerializerOptions());
var cosmosClientOptions = new CosmosClientOptions()
{
Serializer = cosmosSystemTextJsonSerializer
};
var cosmosClient = new CosmosClient(connectionString, cosmosClientOptions);
- Query with LINQ
container = cosmosClient.GetDatabase(databaseName).GetContainer(containerName));
var projectId = _projectId.ToString();
var query = container.GetItemLinqQueryable<MyItem>().Where(i => i.ProjectId == projectId);
var feedIterator = query.ToFeedIterator();
- LINQ query is translated to SQL query
SELECT VALUE root FROM root WHERE (root["ProjectId"] = "XXX")
Expected behavior LINQ query is translated to SQL query using atribute names from JsonPropertyName attributes:
SELECT VALUE root FROM root WHERE (root["project_id"] = "XXX")
Actual behavior LINQ query is translated to SQL query with original property names, not names from JsonPropertyName attributes:
SELECT VALUE root FROM root WHERE (root["ProjectId"] = "XXX")
Environment summary SDK Version: 3.20.1 OS Version: Windows 10
Additional context
Issue Analytics
- State:
- Created 2 years ago
- Reactions:9
- Comments:6 (2 by maintainers)
Top GitHub Comments
We have the same problem and used the following workaround. According to the documentation of the
GetItemLinqQueryable
you can add specific serializer options here as well.So we did this:
This fixes the issue for now.
TypeSystem doesn’t take into account JsonPropertyNameAttribute. As a straightforward workaround you can mark your properties by DataMemberAttribute or Newtonsoft.Json.JsonPropertyAttribure
https://github.com/Azure/azure-cosmos-dotnet-v3/blob/090af9c26a04d2d208e5443554c6c01d81482dd6/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs#L25