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.

Unable to use camel case in JSON when C# types use pascal case

See original GitHub issue

One of the shortcomings of the v2 SDK was that when using a custom JSON serializer to convert the pascal cased C# properties to camel case JSON then the LINQ provider would stop working. I raised an issue in the v2 repository about this two years ago.

It seems that this is still a problem in the v3 SDK. Let me walk you through how I tested this. A custom serializer is needed:

class CamelCaseCosmosSerializer : CosmosSerializer
{
    private static readonly Encoding Encoding = new UTF8Encoding(false, true);
    private static readonly JsonSerializer Serializer = new JsonSerializer()
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver()
    };

    public override T FromStream<T>(Stream stream)
    {
        using (stream)
        {
            if (typeof(Stream).IsAssignableFrom(typeof(T)))
                return (T)(object)(stream);

            using (StreamReader streamReader = new StreamReader(stream))
            using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
                return Serializer.Deserialize<T>(jsonTextReader);
        }
    }

    public override Stream ToStream<T>(T input)
    {
        var stream = new MemoryStream();

        using (StreamWriter streamWriter = new StreamWriter(stream, encoding: Encoding, bufferSize: 1024, leaveOpen: true))
        using (JsonWriter writer = new JsonTextWriter(streamWriter))
        {
            writer.Formatting = Newtonsoft.Json.Formatting.None;
            Serializer.Serialize(writer, input);
            writer.Flush();
            streamWriter.Flush();
        }

        stream.Position = 0;
        return stream;
    }
}

The document type (notice that the Id property is named using pascal case):

class Document
{
    public string Id { get; set; }
    public string Foo { get; set; }
}

Code to create a document (using the emulator):

var client = new CosmosClientBuilder("AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==")
    .WithCustomSerializer(new CamelCaseCosmosSerializer())
    .Build();
var database = (await client.CreateDatabaseIfNotExistsAsync("Test")).Database;
var container = (await database.CreateContainerIfNotExistsAsync("Test", "/id")).Container;
var id = new Random().Next(1_000_000);
await container.CreateItemAsync(new Document { Id = id.ToString(), Foo = "Bar" });

This works because the custom serializer emits JSON with a lower case id property.

Unfortunately, creating a LINQ query doesn’t take this into account:

var queryable = container.GetItemLinqQueryable<Document>().Where(d => d.Foo == "Bar");
Console.WriteLine(queryable.ToString());

Printing queryable results in the following:

{"query":"SELECT VALUE root FROM root WHERE (root[\"Foo\"] = \"Bar\") "}

Notice how the generated query uses pascal cased Foo and not camel cased foo as the property name.

It seems that the LINQ provider in the new SDK (like the old) assumes that .NET property names are mapped to JSON property names without any case conversion making it impossible to use the LINQ provider while at the same time using a JSON serializer that conventionally maps C# pascal case to JSON camel case. I can see that this problem is not easy to solve generally so I would at least like to know if this is a scenario you intend to support in the future.

Interestingly, the query works if I add [JsonProperty("foo")] to the Foo property so there must be some attempt in the LINQ provider to guess how property names are mapped when converting to JSON.

SDK version: 3.0.0, OS version: Windows

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
MikesGlitchcommented, Sep 13, 2019

@buyckkdelaware It’s released now in Preview 2. Works for me! Thanks guys, this came just in time 🥇

1reaction
buyckkdelawarecommented, Sep 6, 2019

#716 Adding camel case serialization on LINQ query generation Above PR address it. It will get released part of 3.2.0

Is it possible to create a new preview version with this fix included? It’s not included in the current 3.2.0-preview version on NuGet. If not, any release data for 3.2.0? Thank you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

TypeScript: Strange behaviour when switching between ...
The json data actually has the property names with camelCase, but you have defined the Info class with PascalName. Take a look at...
Read more >
How to serialize to JSON in camelCase using .NET Core?
The default casing is PascalCase. Changing this requires a bit of configuration, and is not intuitive. But we'll figure this out, no worries!...
Read more >
Camel Case vs. Snake Case vs. Pascal Case — Naming ...
Pascal case follows the same camel case naming convention rules — all but one: we capitalize the first letter (e.g., SomeVariable). In object- ......
Read more >
ASP.NET Core MVC JSON Output in camelCase or PascalCase
Your browser can't play this video. Learn more.
Read more >
PascalCase or camelCase? : r/csharp
So the real answer? You don't use camelCase or PascalCase... you use both. (and others like _underscorePrefixCamelCase for other areas.).
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