From b36a3a6fa8e66ecf8b977c6f0821db2d72cc1079 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Fri, 9 Feb 2024 17:27:23 +0100 Subject: [PATCH] feat(csharp): add discriminator for deserialization (#2678) --- .../algoliasearch/Serializer/JsonConfig.cs | 12 --------- .../csharp/Playground/Model/TestObject.cs | 8 ++++-- .../csharp/Playground/Playgrounds/Search.cs | 27 ++++++++++--------- templates/csharp/modelOneOf.mustache | 22 ++++++++------- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs b/clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs index 40c695bf2d..2aeded18b4 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs @@ -22,16 +22,4 @@ internal static class JsonConfig ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, MissingMemberHandling = MissingMemberHandling.Ignore, }; - - // When DeserializeOneOfSettings is used, we set MissingMemberHandling to Error to throw an exception if a property is missing - public static readonly JsonSerializerSettings DeserializeOneOfSettings = new() - { - Formatting = Formatting.None, - NullValueHandling = NullValueHandling.Ignore, - ContractResolver = Resolver, - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - DateParseHandling = DateParseHandling.DateTime, - ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, - MissingMemberHandling = MissingMemberHandling.Error, - }; } diff --git a/playground/csharp/Playground/Model/TestObject.cs b/playground/csharp/Playground/Model/TestObject.cs index 0d5e3eb9fe..80264f34f1 100644 --- a/playground/csharp/Playground/Model/TestObject.cs +++ b/playground/csharp/Playground/Model/TestObject.cs @@ -1,7 +1,11 @@ +using System.Runtime.Serialization; using Algolia.Search.Models.Search; public class TestObject : Hit { - public string? value { get; set; } - public string? otherValue { get; set; } + [DataMember(Name = "value")] + public string? Value { get; set; } + + [DataMember(Name = "otherValue")] + public string? OtherValue { get; set; } } diff --git a/playground/csharp/Playground/Playgrounds/Search.cs b/playground/csharp/Playground/Playgrounds/Search.cs index b4e23eb4c2..64afb67f77 100644 --- a/playground/csharp/Playground/Playgrounds/Search.cs +++ b/playground/csharp/Playground/Playgrounds/Search.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using Algolia.Search.Clients; using Algolia.Search.Exceptions; using Algolia.Search.Models.Common; @@ -28,7 +27,7 @@ public static async Task Run(Configuration configuration) var loggerFactory = LoggerFactory.Create(i => i.AddFilter("Algolia", LogLevel.Information) - .AddConsole()); + .AddConsole()); var client = new SearchClient(searchConfig, loggerFactory); @@ -75,7 +74,8 @@ await PlaygroundHelper.Start( Console.WriteLine("--- Browse all objects, one page `BrowseAsync` ---"); var r = await client.BrowseAsync(defaultIndex, new BrowseParams(new BrowseParamsObject { HitsPerPage = 100 })); - r.Hits.ForEach(h => Console.WriteLine($" - Record ObjectID: {h.ObjectID}")); + r.Hits.ForEach(h => Console.WriteLine($" - Record ObjectID: {h.ObjectID}, {h.AdditionalProperties.Count}")); + // Browse Helper, to fetch all pages Console.WriteLine("--- Browse all objects, all pages `BrowseObjectsAsync` ---"); @@ -102,14 +102,13 @@ await PlaygroundHelper.Start( var getObjResults = await client.GetObjectsAsync(new GetObjectsParams(getObjRequests)); getObjResults.Results.ForEach(t => - Console.WriteLine($" - Record ObjectID: {t.ObjectID} - Property `otherValue`: {t.otherValue}")); + Console.WriteLine($" - Record ObjectID: {t.ObjectID} - Property `otherValue`: {t.OtherValue}")); // Search single index Console.WriteLine("--- Search single index `SearchSingleIndexAsync` ---"); var t = await client.SearchSingleIndexAsync(defaultIndex); t.Hits.ForEach(h => Console.WriteLine($" - Record ObjectID: {h.ObjectID}")); - // Search Console.WriteLine("--- Search multiple indices `SearchAsync` ---"); var searchQueries = new List { @@ -122,7 +121,8 @@ await PlaygroundHelper.Start( { if (result.IsSearchResponse()) { - Console.WriteLine($"Record with Hits: ObjectID = {result.AsSearchResponse().Hits.First().ObjectID}"); + Console.WriteLine( + $"Record with Hits: ObjectID = {result.AsSearchResponse().Hits.First().ObjectID}, {result.AsSearchResponse().Hits.First().AdditionalProperties.Count}"); } else if (result.IsSearchForFacetValuesResponse()) { @@ -189,7 +189,7 @@ await PlaygroundHelper.Start("Deleting API Key", async () => }, }).ConfigureAwait(false); - await PlaygroundHelper.Start("Creating new Synonyms - Async TaskID: `{synonymsResponse.TaskID}`", async () => + await PlaygroundHelper.Start($"Creating new Synonyms - Async TaskID: `{synonymsResponse.TaskID}`", async () => await client.WaitForTaskAsync(defaultIndex, synonymsResponse.TaskID), "New Synonyms has been created !"); // Search Synonyms @@ -198,13 +198,16 @@ await PlaygroundHelper.Start("Deleting API Key", async () => .SearchSynonymsAsync(defaultIndex, new SearchSynonymsParams { Query = "", Type = SynonymType.Onewaysynonym, HitsPerPage = 1 }) .ConfigureAwait(false); - Console.WriteLine(searchSynonymsAsync.Hits.Count); + + searchSynonymsAsync.Hits.ForEach(s => Console.WriteLine("Found :" + string.Join(',', s.Synonyms))); // Browse Synonyms - // var configuredTaskAwaitable = await client - // .BrowseSynonymsAsync("test-csharp-new-client", SynonymType.Onewaysynonym, new SearchSynonymsParams { Query = "" }) - // .ConfigureAwait(false); - // configuredTaskAwaitable.ToList().ForEach(s => Console.WriteLine("Found :" + string.Join(',', s.Synonyms))); + Console.WriteLine("--- Browse Synonyms `BrowseSynonymsAsync` ---"); + var configuredTaskAwaitable = await client + .BrowseSynonymsAsync("test-csharp-new-client", + new SearchSynonymsParams { Query = "", Type = SynonymType.Onewaysynonym }) + .ConfigureAwait(false); + configuredTaskAwaitable.ToList().ForEach(s => Console.WriteLine("Found :" + string.Join(',', s.Synonyms))); // Add Rule Console.WriteLine("--- Create new Rule `SaveRulesAsync` ---"); diff --git a/templates/csharp/modelOneOf.mustache b/templates/csharp/modelOneOf.mustache index 4c1f882a4f..9324a576e8 100644 --- a/templates/csharp/modelOneOf.mustache +++ b/templates/csharp/modelOneOf.mustache @@ -150,16 +150,20 @@ {{/discriminator}} {{/useOneOfDiscriminatorLookup}} {{#vendorExtensions}} + var jToken = JToken.Parse(jsonString); {{#composedSchemas.oneOf}} - try - { - return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.DeserializeOneOfSettings)); - } - catch (Exception exception) - { - // deserialization failed, try the next one - System.Diagnostics.Debug.WriteLine($"Failed to deserialize `{jsonString}` into {{{datatypeWithEnum}}}: {exception}"); - } + if (jToken.Type == JTokenType.{{#isModel}}Object{{#vendorExtensions.x-discriminator-fields}} && jToken["{{{.}}}"] != null{{/vendorExtensions.x-discriminator-fields}}{{/isModel}}{{#isEnumRef}}String{{/isEnumRef}}{{#isArray}}Array{{/isArray}}{{#isInteger}}Integer{{/isInteger}}{{#isLong}}Integer{{/isLong}}{{#isDouble}}Float{{/isDouble}}{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isEnumRef}}{{^isModel}}{{^isArray}}{{^isInteger}}{{^isLong}}{{^isDouble}}{{^isBoolean}}{{^isString}}Object{{/isString}}{{/isBoolean}}{{/isDouble}}{{/isLong}}{{/isInteger}}{{/isArray}}{{/isModel}}{{/isEnumRef}}) + { + try + { + return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.AlgoliaJsonSerializerSettings)); + } + catch (Exception exception) + { + // deserialization failed, try the next one + System.Diagnostics.Debug.WriteLine($"Failed to deserialize `{jsonString}` into {{{datatypeWithEnum}}}: {exception}"); + } + } {{/composedSchemas.oneOf}} {{/vendorExtensions}}