From 25249aa534e493d9e1e4fa4b75da9839b5b4dc39 Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Wed, 6 Jan 2021 15:38:11 -0800 Subject: [PATCH 1/3] Prepare release of Azure.Core JSON helpers --- .../README.md | 101 +++++++++++++-- ...Microsoft.Azure.Core.NewtonsoftJson.csproj | 2 +- .../src/NewtonsoftJsonObjectSerializer.cs | 3 + ...oft.Azure.Core.NewtonsoftJson.Tests.csproj | 2 + .../tests/Samples/Readme.cs | 115 ++++++++++++++++++ .../README.md | 2 +- ...t.Azure.Core.Spatial.NewtonsoftJson.csproj | 2 +- .../Microsoft.Azure.Core.Spatial/README.md | 2 +- .../src/Microsoft.Azure.Core.Spatial.csproj | 2 +- 9 files changed, 213 insertions(+), 18 deletions(-) create mode 100644 sdk/core/Microsoft.Azure.Core.NewtonsoftJson/tests/Samples/Readme.cs diff --git a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/README.md b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/README.md index 515818587a41..803252db0fd7 100644 --- a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/README.md +++ b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/README.md @@ -5,35 +5,107 @@ This library contains converters dependent on the [Newtonsoft.Json package][newt ## Getting started -TODO +Install this package if you want to use Newtonsoft.Json to serialize and deserialize model types with some Azure SDKs. ### Install the package -TODO +Install this package from [NuGet] using the .NET CLI: -### Prerequisites +```bash +dotnet add package Microsoft.Azure.Core.NewtonsoftJson +``` -TODO +## Key concepts -### Authenticate the client +This support package contains the `NewtonsoftJsonObjectSerializer` class which can be passed to some Azure SDKs' client options classes, as shown in the examples below. -TODO +The following converters are added automatically to the `NewtonsoftJsonObjectSerializer` if you do not pass your own `JsonSerializerSettings`: -## Key concepts +- `NewtonsoftJsonETagConverter` to convert `Azure.ETag` properties. -TODO +See the example [Using default converters](#using-default-converters) below for getting an instance of `JsonSerializerSettings` with this default list you can then modify as needed. ## Examples -TODO +The [Azure.Search.Documents package][azure_search_documents_package] is used in examples to show how search results can be deserialized. For more information and examples using Azure.Search.Documents, see its [README][azure_search_documents_readme]. + +### Deserializing models + +Consider a model class containing information about movies: + +```C# Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_Model +public class Movie +{ + [JsonProperty("uuid")] + public string Id { get; private set; } = Guid.NewGuid().ToString(); + + public string Title { get; set; } + + public string Description { get; set; } + + public float Rating { get; set; } +} +``` + +Our Azure Cognitive Search index is defined using camelCase fields, and the `Id` field is actually defined as "uuid"; however, we can provide an idiomatic model without having to attribute all properties by setting the `JsonSerializerSettings.ContractResolver` property as shown below: + +```C# Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_SearchSample +// Get the Azure Cognitive Search endpoint and read-only API key. +Uri endpoint = new Uri(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); +AzureKeyCredential credential = new AzureKeyCredential(Environment.GetEnvironmentVariable("SEARCH_API_KEY")); + +// Create serializer options with default converters for Azure SDKs. +JsonSerializerSettings serializerSettings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings(); + +// Serialize property names using camelCase by default. +serializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + +SearchClientOptions clientOptions = new SearchClientOptions +{ + Serializer = new NewtonsoftJsonObjectSerializer(serializerSettings) +}; + +SearchClient client = new SearchClient(endpoint, "movies", credential, clientOptions); +Response> results = client.Search("Return of the King"); + +foreach (SearchResult result in results.Value.GetResults()) +{ + Movie movie = result.Document; + + Console.WriteLine(movie.Title); + Console.WriteLine(movie.Description); + Console.WriteLine($"Rating: {movie.Rating}\n"); +} +``` + +If searching an index full of movies, the following may be printed: + +```text +The Lord of the Rings: The Return of the King +Gandalf and Aragorn lead the World of Men against Sauron's army to draw his gaze from Frodo and Sam as they approach Mount Doom with the One Ring. +Rating: 9.1 +``` + +### Using default converters + +If you instantiate a `NewtonsoftJsonObjectSerializer` using the default constructor, some converters for common Azure SDKs are added automatically as listed above in [Key concepts](#key-concepts). To modify these default settings, you can create a new `JsonSerializerSettings` like in the following example: + +```C# Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_DefaultSerializerSettings +JsonSerializerSettings serializerSettings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings(); -## Troubleshooting +// Serialize property names using camelCase by default. +serializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); -TODO +// Add converters as needed, for example, to convert movie genres to an enum. +serializerSettings.Converters.Add(new StringEnumConverter()); -## Next steps +SearchClientOptions clientOptions = new SearchClientOptions +{ + Serializer = new NewtonsoftJsonObjectSerializer(serializerSettings) +}; +``` -TODO +You can add or remove converters, set the `ContractResolver`, or any other members of `JsonSerializerSettings` you need. ## Contributing @@ -46,6 +118,9 @@ This project has adopted the [Microsoft Open Source Code of Conduct][code_of_con ![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net%2Fsdk%2Fcore%2FMicrosoft.Azure.Core.NewtonsoftJson%2FREADME.png) [azure_core_package]: https://www.nuget.org/packages/Azure.Core/ +[azure_search_documents_package]: https://www.nuget.org/packages/Azure.Search.Documents/ +[azure_search_documents_readme]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/search/Azure.Search.Documents/README.md [code_of_conduct]: https://opensource.microsoft.com/codeofconduct [code_of_conduct_faq]: https://opensource.microsoft.com/codeofconduct/faq/ [newtonsoft_json_package]: https://www.nuget.org/packages/Newtonsoft.Json/ +[NuGet]: https://www.nuget.org diff --git a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/Microsoft.Azure.Core.NewtonsoftJson.csproj b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/Microsoft.Azure.Core.NewtonsoftJson.csproj index 5c54061af95f..1c8dc1dacc1b 100644 --- a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/Microsoft.Azure.Core.NewtonsoftJson.csproj +++ b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/Microsoft.Azure.Core.NewtonsoftJson.csproj @@ -2,7 +2,7 @@ Newtonsoft.Json support for Azure Core shared client library for .NET Azure.Core.Serialization - 1.0.0-preview.2 + 1.0.0 This library contains converters dependent on the Newtonsoft.Json package for use with Azure.Core. Microsoft Azure SDK Newtonsoft Json enable diff --git a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/NewtonsoftJsonObjectSerializer.cs b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/NewtonsoftJsonObjectSerializer.cs index cd893ef35cb5..d0071f7da512 100644 --- a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/NewtonsoftJsonObjectSerializer.cs +++ b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/NewtonsoftJsonObjectSerializer.cs @@ -42,7 +42,10 @@ public NewtonsoftJsonObjectSerializer() : this(CreateJsonSerializerSettings()) public static JsonSerializerSettings CreateJsonSerializerSettings() { var settings = new JsonSerializerSettings(); + + // TODO: Update the README when converters are added by default. settings.Converters.Add(new NewtonsoftJsonETagConverter()); + return settings; } diff --git a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/tests/Microsoft.Azure.Core.NewtonsoftJson.Tests.csproj b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/tests/Microsoft.Azure.Core.NewtonsoftJson.Tests.csproj index 665b4a7247e5..a6c4e558aee6 100644 --- a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/tests/Microsoft.Azure.Core.NewtonsoftJson.Tests.csproj +++ b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/tests/Microsoft.Azure.Core.NewtonsoftJson.Tests.csproj @@ -5,6 +5,7 @@ + @@ -12,6 +13,7 @@ + \ No newline at end of file diff --git a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/tests/Samples/Readme.cs b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/tests/Samples/Readme.cs new file mode 100644 index 000000000000..d75975638e73 --- /dev/null +++ b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/tests/Samples/Readme.cs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Linq; +using Azure; +using Azure.Core.Serialization; +using Azure.Core.TestFramework; +using Azure.Search.Documents; +using Azure.Search.Documents.Indexes; +using Azure.Search.Documents.Indexes.Models; +using Azure.Search.Documents.Models; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; +using NUnit.Framework; + +namespace Microsoft.Azure.Core.NewtonsoftJson.Tests.Samples +{ + public class Readme + { + [Test] + public void SearchSample() + { + MockResponse response = new MockResponse(200); + response.SetContent(@"{ + ""value"": [ + { + ""@search.score"": 1.0, + ""uuid"": ""efe8857f-1d74-41e2-9ff1-4943a9ad69d5"", + ""title"": ""The Lord of the Rings: The Return of the King"", + ""description"": ""Gandalf and Aragorn lead the World of Men against Sauron's army to draw his gaze from Frodo and Sam as they approach Mount Doom with the One Ring."", + ""rating"": 9.1 + } + ] + }"); + + Environment.SetEnvironmentVariable("SEARCH_ENDPOINT", "https://sample.search.windows.net"); + Environment.SetEnvironmentVariable("SEARCH_API_KEY", "sample"); + + #region Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_SearchSample + // Get the Azure Cognitive Search endpoint and read-only API key. + Uri endpoint = new Uri(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); + AzureKeyCredential credential = new AzureKeyCredential(Environment.GetEnvironmentVariable("SEARCH_API_KEY")); + + // Create serializer options with default converters for Azure SDKs. + JsonSerializerSettings serializerSettings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings(); + + // Serialize property names using camelCase by default. + serializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + + SearchClientOptions clientOptions = new SearchClientOptions + { + /*@@*/ Transport = new MockTransport(response), + Serializer = new NewtonsoftJsonObjectSerializer(serializerSettings) + }; + + SearchClient client = new SearchClient(endpoint, "movies", credential, clientOptions); + Response> results = client.Search("Return of the King"); + + foreach (SearchResult result in results.Value.GetResults()) + { + Movie movie = result.Document; + + Console.WriteLine(movie.Title); + Console.WriteLine(movie.Description); + Console.WriteLine($"Rating: {movie.Rating}\n"); + } + #endregion Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_SearchSample + + Movie _movie = results.Value.GetResults().Single().Document; + Assert.AreEqual("efe8857f-1d74-41e2-9ff1-4943a9ad69d5", _movie.Id); + Assert.AreEqual("The Lord of the Rings: The Return of the King", _movie.Title); + Assert.AreEqual("Gandalf and Aragorn lead the World of Men against Sauron's army to draw his gaze from Frodo and Sam as they approach Mount Doom with the One Ring.", _movie.Description); + Assert.AreEqual(9.1, _movie.Rating, 0.01); + } + + [Test] + public void DefaultSerializerSettings() + { + #region Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_DefaultSerializerSettings + JsonSerializerSettings serializerSettings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings(); + + // Serialize property names using camelCase by default. + serializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + + // Add converters as needed, for example, to convert movie genres to an enum. + serializerSettings.Converters.Add(new StringEnumConverter()); + + SearchClientOptions clientOptions = new SearchClientOptions + { + Serializer = new NewtonsoftJsonObjectSerializer(serializerSettings) + }; + #endregion Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_DefaultSerializerSettings + + Assert.AreEqual(2, serializerSettings.Converters.Count); + Assert.That(serializerSettings.Converters, Has.Some.TypeOf(typeof(NewtonsoftJsonETagConverter))); + Assert.That(serializerSettings.Converters, Has.Some.TypeOf(typeof(StringEnumConverter))); + } + + #region Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_Model + public class Movie + { + [JsonProperty("uuid")] + public string Id { get; private set; } = Guid.NewGuid().ToString(); + + public string Title { get; set; } + + public string Description { get; set; } + + public float Rating { get; set; } + } + #endregion Snippet:Microsoft_Azure_Core_NewtonsoftJson_Samples_Readme_Model + } +} diff --git a/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/README.md b/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/README.md index 01c7ebd0a68a..08cad0bc57f5 100644 --- a/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/README.md +++ b/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/README.md @@ -11,7 +11,7 @@ Install this package if you use the Microsoft.Spatial package in your applicatio Install this package from [NuGet] using the .NET CLI: ```bash -dotnet add package Microsoft.Azure.Core.Spatial.NewtonsoftJson --version 1.0.0-beta.1 +dotnet add package Microsoft.Azure.Core.Spatial.NewtonsoftJson ``` ## Key concepts diff --git a/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/src/Microsoft.Azure.Core.Spatial.NewtonsoftJson.csproj b/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/src/Microsoft.Azure.Core.Spatial.NewtonsoftJson.csproj index a5e01ed8fc90..d324c36fc711 100644 --- a/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/src/Microsoft.Azure.Core.Spatial.NewtonsoftJson.csproj +++ b/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/src/Microsoft.Azure.Core.Spatial.NewtonsoftJson.csproj @@ -3,7 +3,7 @@ Newtonsoft.Json support for the Microsoft.Spatial library This library contains converters dependent on the Newtonsoft.Json package for use with Microsoft.Spatial when using the Azure SDK for .NET. Azure.Core.Serialization - 1.0.0-beta.2 + 1.0.0 Microsoft Azure SDK Spatial Newtonsoft Json $(RequiredTargetFrameworks) false diff --git a/sdk/core/Microsoft.Azure.Core.Spatial/README.md b/sdk/core/Microsoft.Azure.Core.Spatial/README.md index cceb9100b5d7..c4eb1498ffbc 100644 --- a/sdk/core/Microsoft.Azure.Core.Spatial/README.md +++ b/sdk/core/Microsoft.Azure.Core.Spatial/README.md @@ -11,7 +11,7 @@ Install this package if you use the Microsoft.Spatial package in your applicatio Install this package from [NuGet] using the .NET CLI: ```bash -dotnet add package Microsoft.Azure.Core.Spatial --version 1.0.0-beta.1 +dotnet add package Microsoft.Azure.Core.Spatial ``` ## Key concepts diff --git a/sdk/core/Microsoft.Azure.Core.Spatial/src/Microsoft.Azure.Core.Spatial.csproj b/sdk/core/Microsoft.Azure.Core.Spatial/src/Microsoft.Azure.Core.Spatial.csproj index dcf1a2fcf7ba..261d05b0bc58 100644 --- a/sdk/core/Microsoft.Azure.Core.Spatial/src/Microsoft.Azure.Core.Spatial.csproj +++ b/sdk/core/Microsoft.Azure.Core.Spatial/src/Microsoft.Azure.Core.Spatial.csproj @@ -3,7 +3,7 @@ System.Text.Json support for the Microsoft.Spatial library This library contains converters for System.Text.Json for use with Microsoft.Spatial when using the Azure SDK for .NET. Azure.Core - 1.0.0-beta.2 + 1.0.0 Microsoft Azure SDK Spatial System Text Json $(RequiredTargetFrameworks) false From 9b09f30bdf7f77a95e6ce6e2b4eecccc5f51abb2 Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Wed, 6 Jan 2021 16:38:44 -0800 Subject: [PATCH 2/3] Update CHANGELOGs --- sdk/core/Microsoft.Azure.Core.NewtonsoftJson/CHANGELOG.md | 4 ++-- .../Microsoft.Azure.Core.Spatial.NewtonsoftJson/CHANGELOG.md | 3 ++- sdk/core/Microsoft.Azure.Core.Spatial/CHANGELOG.md | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/CHANGELOG.md b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/CHANGELOG.md index 714334cc43f3..785f1634f53a 100644 --- a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/CHANGELOG.md +++ b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/CHANGELOG.md @@ -1,10 +1,10 @@ # Release History -## 1.0.0-preview.2 (2020-11-10) +## 1.0.0 (2021-01-06) ### Added -- `Newtonsoft.Json.JsonConverter` implementation for the `ETag` +- `Newtonsoft.Json.JsonConverter` implementation for the `ETag` ## 1.0.0-preview.1 (2020-08-07) diff --git a/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/CHANGELOG.md b/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/CHANGELOG.md index 5754644c04b8..12a3e6003582 100644 --- a/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/CHANGELOG.md +++ b/sdk/core/Microsoft.Azure.Core.Spatial.NewtonsoftJson/CHANGELOG.md @@ -1,7 +1,8 @@ # Release History -## 1.0.0-beta.2 (Unreleased) +## 1.0.0 (2021-01-06) +Released. ## 1.0.0-beta.1 (2020-10-08) diff --git a/sdk/core/Microsoft.Azure.Core.Spatial/CHANGELOG.md b/sdk/core/Microsoft.Azure.Core.Spatial/CHANGELOG.md index 4ad59c1e8d8f..97d9c125b69e 100644 --- a/sdk/core/Microsoft.Azure.Core.Spatial/CHANGELOG.md +++ b/sdk/core/Microsoft.Azure.Core.Spatial/CHANGELOG.md @@ -1,7 +1,8 @@ # Release History -## 1.0.0-beta.2 (Unreleased) +## 1.0.0 (2021-01-06) +Released. ## 1.0.0-beta.1 (2020-10-08) From 1151fd065e079fef475a6ee30046651366c55873 Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Wed, 6 Jan 2021 16:40:36 -0800 Subject: [PATCH 3/3] Resolve PR feedback --- .../src/NewtonsoftJsonObjectSerializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/NewtonsoftJsonObjectSerializer.cs b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/NewtonsoftJsonObjectSerializer.cs index d0071f7da512..fba48eab8f46 100644 --- a/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/NewtonsoftJsonObjectSerializer.cs +++ b/sdk/core/Microsoft.Azure.Core.NewtonsoftJson/src/NewtonsoftJsonObjectSerializer.cs @@ -43,7 +43,7 @@ public static JsonSerializerSettings CreateJsonSerializerSettings() { var settings = new JsonSerializerSettings(); - // TODO: Update the README when converters are added by default. + // NOTE: Update the README when converters are added by default. settings.Converters.Add(new NewtonsoftJsonETagConverter()); return settings;