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.

Combining custom camel case serializer with LINQ

See original GitHub issue

The SDK supports a custom serializer by deriving from CosmosSerializer but using a serializer that converts idiomatic C# pascal case property names to JSON camel case names break LINQ queries.

Version 3.2.0-preview2 now supports CosmosPropertyNamingPolicy.CamelCase which fixes the camel case problem. Thanks!

However, it is impossible to both have a custom serializer and also a LINQ provider that uses camel case. If I specify a custom serializer then I’m no longer allowed to use CosmosPropertyNamingPolicy.CamelCase which I need to change the behavior of the LINQ provider to match my custom serializer.

Would it be possible to both configure the LINQ provider to generate camel case SQL while also using a custom serializer? That would be awesome.

Related issues: #72, #551, #570.

And just to explain why I need a custom serializer here are some of the reasons:

  • I have some code generated types that my serializer is able to serialize based on an attribute so number-like types are serialized as numbers and not strings.
  • I have abstract base types and concrete derived types which JSON doesn’t support but my serializer is able to deserialize to the correct derived type based on additional light-weight type information in the JSON.
  • I have some custom types that I use as dictionary keys which also require extra support from the serializer.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:14
  • Comments:11 (4 by maintainers)

github_iconTop GitHub Comments

6reactions
derekgreercommented, Oct 21, 2020

bump

6reactions
Liversagecommented, Oct 2, 2019

Here are some additional thoughts on how to handle this issue which may be relevant to users of the Cosmos SDK (people like me, not the developers of the SDK).

I’m building my system in C# and I use the type system to assist me in doing that which includes using inheritance and combatting primitive obsession with dedicated value types.

Unfortunately, there is some impedance mismatch between C# types and JSON. To handle this I have had to customize the JSON serializer and this customization has only grown over time. This has resulted in a heavy dependency on Json.NET.

The most recent release of the Cosmos SDK has good support for camel case/pascal case but then I can no longer use my customized serializer. Essentially I was still stuck at

  1. littering [JsonProperty] all over my domain model (no, that doesn’t scale at all),
  2. writing queries directly using Cosmos SQL (no, LINQ is so much better e.g. for composition), or
  3. writing my own LINQ provider (yes, I did that - interesting, but not recommended at all).

The fundamental problem here is that intersection of my domain model, my desire to use LINQ, a requirement that all JSON is camel cased to avoid client side confusion, and the Cosmos SDK is empty.

Also, having a strong dependency on Json.NET has been a concern of mine. I would like to be able to switch to System.Text.Json in the future where it might end up being the “default” serializer with only “legacy” software using Json.NET.

As Cosmos SDK works quite well for “simple” POCO types (especially with the latest addition to support camel case) I realized that I could solve my problem by inserting a “DTO layer” with “JSON friendly” types between my domain model and lower layers like JSON serialization, Cosmos SDK etc. This would remove all the trouble I’m having with using a specific JSON serializer and a specific Cosmos SDK. If I want camel case I can just generate the DTOs with camel case and handle that in my own mapper.

I don’t want to write a ton of DTOs by hand so instead I’ve created a system where “JSON friendly” DTOs are generated at run-time (using Roslyn). I already had a mapper in place to automatically map between domain types and DTOs and my DTO generator expands on specific conventions of my type system. Creating a general library to do this is a major undertaking so I have opted to just support the specific types I use to limit the scope.

To sum up writing to Cosmos involves the following steps:

  • Generate the DTO that matches the domain type involved (this involves recursive generation for nested type but generated types are cached thus only generated once).
  • Map the domain object to the generated DTO object.
  • Hand the DTO object over to the JSON serializer/Cosmos SDK to serialize and write the data to Cosmos.

Reading is more or less the same just going the opposite way. The most tricky part is probably rewriting the “domain layer” LINQ expressions to equivalent “DTO layer” expressions which enables LINQ queries.

I admit that there were far more devils found in the details than I expected when building this but I’m quite happy with the final results.

Read more comments on GitHub >

github_iconTop Results From Across the Web

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 >
LINQ — C#/.NET
The documents in the restaurants collection use the camel-case naming convention. ... To learn more about custom serialization, see Custom Serialization.
Read more >
Azure Cosmos DB (EF/Core) - Camel Case Property Names ...
In the case of Cosmos you may want the names in the database to be the same as the names when you serialize...
Read more >
Json Serialization
This can be overridden to serialize the names to camelCase and Marten will store the JSON in the database as specified by the...
Read more >
FAQ & Troubleshooting
Serialize to camel case? ​. While it's possible to accommodate any serialization schemes by implementing a custom ISerializer , Marten's ...
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