Problem
In some scenarios engineers might want to use a custom JSON serializer for documents stored in CosmosDB.
Solution
In CosmosDBV3 .NET Core API, when creating an instance of CosmosClient one of optional setting in CosmosClientOptions is to specify an instance of a Serializer. This serializer must be JSON based and be of CosmosSerializer type. This means that if a custom serializer is needed this should inherit from CosmosSerializer abstract class and override its two methods for serializing and deserializing of an object. The challenge is that both methods from CosmosSerializer are stream based and therefore might be not as easy to implement as engineers used to assume - still not super complex.
For demonstration purpose as or my custom serializer I'm going to use Netwonsoft.JSON library. Firstly a new type is needed and this must inherit from CosmosSerializer.
For demonstration purpose as or my custom serializer I'm going to use Netwonsoft.JSON library. Firstly a new type is needed and this must inherit from CosmosSerializer.
using Microsoft.Azure.Cosmos;
using Newtonsoft.Json; using System.IO; using System.Text; /// <summary> /// Custom serializer for CosmosDB client. /// </summary> public class SerliarizationService : CosmosSerializer { private readonly JsonSerializer serializer; public SerliarizationService() { this.serializer = new JsonSerializer { NullValueHandling = NullValueHandling.Ignore }; } /// <summary> /// Logic for deserialization. /// </summary> public override T FromStream<T>(Stream stream) { return this.serializer.Deserialize<T>(new JsonTextReader(new StreamReader(stream))); } /// <summary> /// Serialization logic. /// </summary> public override Stream ToStream<T>(T input) { using var stringWriter = new StringWriter(); using var jsonTextWriter = new JsonTextWriter(stringWriter); this.serializer.Serialize(jsonTextWriter, input, input.GetType()); return new MemoryStream(Encoding.UTF8.GetBytes(stringWriter.ToString())); } }
With a custom serialization in place, the only thing to change is to change settings when initializing a new instance of CosmosClient.
cosmosClient = new CosmosClient( this.dbConfig.EndpointUrl, this.dbConfig.AuthorizationKey, new CosmosClientOptions() { Serializer = new SerliarizationService(), });
Job done.
Thank you
Thank you
/dz