question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

LINQ queries doesn't use custom CosmosSerializer

See original GitHub issue

We 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

  1. Create documents in database with column names e.g. id, project_id
  2. Create C# project with class:
public record MyItem
{
    [JsonPropertyName("id")]
    public string Id { get; set; }

    [JsonPropertyName("project_id")]
    public string ProjectId { get; set; }`
}
  1. 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;
    }
}
  1. Create CosmosClient with custom serializer:
var cosmosSystemTextJsonSerializer = new CosmosSystemTextJsonSerializer(new JsonSerializerOptions());
var cosmosClientOptions = new CosmosClientOptions()
{
    Serializer = cosmosSystemTextJsonSerializer
};
var cosmosClient = new CosmosClient(connectionString, cosmosClientOptions);
  1. 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();
  1. 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:open
  • Created 2 years ago
  • Reactions:9
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
thomasvdbcommented, Jul 14, 2022

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:

var query = container.GetItemLinqQueryable<MyItem>().Where(i => i.ProjectId == projectId, linqSerializerOptions: new CosmosLinqSerializerOptions { PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase }));

This fixes the issue for now.

3reactions
evgenxppcommented, Sep 8, 2021

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

Read more comments on GitHub >

github_iconTop Results From Across the Web

LINQ queries doesn't use custom CosmosSerializer #2685
I decorate properties of my classes with JsonPropertyName attribute to translate class property names to attribute names of documents in my ...
Read more >
Casing strategy on custom serializer is not picked up by ...
This works fine - actually, this serializer is an internal class in the Cosmos SDK, internal to "easy" the migration towards System.Text.Json.
Read more >
Under the hood of the new Azure Functions extension for ...
LINQ should use the custom serializer, please report any concerns with the .NET SDK to https://github.com/Azure/azure-cosmos-dotnet-v3/issues.
Read more >
Handling type hierarchies in Cosmos DB (part 2)
In this post, I'll show another approach based on custom ... First, let add an abstract Type property to the base class of...
Read more >
Custom JSON serialization with Azure Cosmos DB SDK
This post explains how you can use custom JSON serializer settings with Cosmos DB using Newtonsoft JSON and System.Text.Json.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found