Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a sample on how to use the custom serializer. #560

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 8 additions & 2 deletions Microsoft.Azure.Cosmos.Samples/CodeSamples/Cosmos.Samples.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2041
# Visual Studio Version 16
VisualStudioVersion = 16.0.29102.190
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabaseManagement", "DatabaseManagement\DatabaseManagement.csproj", "{F972386A-B03D-4453-88C7-948CB107C029}"
EndProject
Expand All @@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzureFunctions", "AzureFunc
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonPartitionContainerMigration", "NonPartitionContainerMigration\NonPartitionContainerMigration.csproj", "{C1A42351-39FC-4600-A235-FF5A90B02628}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSerializer", "CustomSerializer\CustomSerializer.csproj", "{1D0DD61B-9CA2-4F48-87E5-FB839749FC6B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -63,6 +65,10 @@ Global
{C1A42351-39FC-4600-A235-FF5A90B02628}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1A42351-39FC-4600-A235-FF5A90B02628}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C1A42351-39FC-4600-A235-FF5A90B02628}.Release|Any CPU.Build.0 = Release|Any CPU
{1D0DD61B-9CA2-4F48-87E5-FB839749FC6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1D0DD61B-9CA2-4F48-87E5-FB839749FC6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D0DD61B-9CA2-4F48-87E5-FB839749FC6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D0DD61B-9CA2-4F48-87E5-FB839749FC6B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
<ItemGroup>
<None Include="..\AppSettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
@@ -0,0 +1,93 @@
namespace Cosmos.Samples.Shared
{
using System;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;

class CustomSerializerProgram
{
// Async main requires c# 7.1 which is set in the csproj with the LangVersion attribute
// <Main>
public static async Task Main(string[] args)
{
try
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.AddJsonFile("appSettings.json")
.Build();

string endpoint = configuration["EndPointUrl"];
if (string.IsNullOrEmpty(endpoint))
{
throw new ArgumentNullException("Please specify a valid endpoint in the appSettings.json");
}

string authKey = configuration["AuthorizationKey"];
if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret key"))
{
throw new ArgumentException("Please specify a valid AuthorizationKey in the appSettings.json");
}

//Read the Cosmos endpointUrl and authorisationKeys from configuration
//These values are available from the Azure Management Portal on the Cosmos Account Blade under "Keys"
//NB > Keep these values in a safe & secure location. Together they provide Administrative access to your Cosmos account
CustomSerializerProgram program = new CustomSerializerProgram();
await program.RunDemo(endpoint, authKey);

}
catch (CosmosException cre)
{
Console.WriteLine(cre.ToString());
}
catch (Exception e)
{
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
finally
{
Console.WriteLine("End of demo, press any key to exit.");
Console.ReadKey();
}
}

public async Task RunDemo(string endpoint, string key)
{
CosmosClientOptions options = new CosmosClientOptions()
{
Serializer = new JsonSerializerIgnoreNull(),
};

using (CosmosClient client = new CosmosClient(endpoint, key, options))
{
Database db = null;
try
{
db = await client.CreateDatabaseIfNotExistsAsync("CustomSerializerDemo");
Container container = await db.CreateContainerIfNotExistsAsync(
id: "ContainerDemo",
partitionKeyPath: "/pk");

dynamic testItem = new { id = "MyTestItemWithIgnoreNull" + Guid.NewGuid(), pk = "ItExists", description = (string)null };
ItemResponse<dynamic> itemResponse = await container.CreateItemAsync<dynamic>(testItem, new PartitionKey(testItem.pk));
dynamic responseObject = itemResponse.Resource;
if (responseObject["description"] != null)
{
throw new InvalidOperationException("Description was not ignored");
}

Console.WriteLine($"Item created: {responseObject}");
}
finally
{
if(db != null)
{
await db.DeleteAsync();
}
}
}
}
}
}
@@ -0,0 +1,58 @@
namespace Cosmos.Samples.Shared
{
using System;
using System.IO;
using System.Text;
using Microsoft.Azure.Cosmos;
using Newtonsoft.Json;

class JsonSerializerIgnoreNull : CosmosSerializer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more option is to make it generic to take JsonSerializerSettings and we can use it as reference for V2 -> V3 migration. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a separate issue to track that. #551

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON.net implementation as public contract will force its dependency even in future when implementation moved to .NET core JSON parser.

{
private static readonly Encoding DefaultEncoding = new UTF8Encoding(false, true);
private static readonly JsonSerializer Serializer = new JsonSerializer()
{
NullValueHandling = NullValueHandling.Ignore
};

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

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

public override Stream ToStream<T>(T input)
{
MemoryStream streamPayload = new MemoryStream();
using (StreamWriter streamWriter = new StreamWriter(
streamPayload,
encoding: JsonSerializerIgnoreNull.DefaultEncoding,
bufferSize: 1024,
leaveOpen: true))
{
using (JsonWriter writer = new JsonTextWriter(streamWriter))
{
writer.Formatting = Newtonsoft.Json.Formatting.None;
JsonSerializerIgnoreNull.Serializer.Serialize(writer, input);
writer.Flush();
streamWriter.Flush();
}
}

streamPayload.Position = 0;
return streamPayload;
}
}
}