Skip to content

Commit b36a3a6

Browse files
authored
feat(csharp): add discriminator for deserialization (#2678)
1 parent bd5b3a0 commit b36a3a6

File tree

4 files changed

+34
-35
lines changed

4 files changed

+34
-35
lines changed

clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,4 @@ internal static class JsonConfig
2222
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
2323
MissingMemberHandling = MissingMemberHandling.Ignore,
2424
};
25-
26-
// When DeserializeOneOfSettings is used, we set MissingMemberHandling to Error to throw an exception if a property is missing
27-
public static readonly JsonSerializerSettings DeserializeOneOfSettings = new()
28-
{
29-
Formatting = Formatting.None,
30-
NullValueHandling = NullValueHandling.Ignore,
31-
ContractResolver = Resolver,
32-
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
33-
DateParseHandling = DateParseHandling.DateTime,
34-
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
35-
MissingMemberHandling = MissingMemberHandling.Error,
36-
};
3725
}
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
using System.Runtime.Serialization;
12
using Algolia.Search.Models.Search;
23

34
public class TestObject : Hit
45
{
5-
public string? value { get; set; }
6-
public string? otherValue { get; set; }
6+
[DataMember(Name = "value")]
7+
public string? Value { get; set; }
8+
9+
[DataMember(Name = "otherValue")]
10+
public string? OtherValue { get; set; }
711
}

playground/csharp/Playground/Playgrounds/Search.cs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Diagnostics;
21
using Algolia.Search.Clients;
32
using Algolia.Search.Exceptions;
43
using Algolia.Search.Models.Common;
@@ -28,7 +27,7 @@ public static async Task Run(Configuration configuration)
2827

2928

3029
var loggerFactory = LoggerFactory.Create(i => i.AddFilter("Algolia", LogLevel.Information)
31-
.AddConsole());
30+
.AddConsole());
3231

3332
var client = new SearchClient(searchConfig, loggerFactory);
3433

@@ -75,7 +74,8 @@ await PlaygroundHelper.Start(
7574
Console.WriteLine("--- Browse all objects, one page `BrowseAsync` ---");
7675
var r = await client.BrowseAsync<TestObject>(defaultIndex,
7776
new BrowseParams(new BrowseParamsObject { HitsPerPage = 100 }));
78-
r.Hits.ForEach(h => Console.WriteLine($" - Record ObjectID: {h.ObjectID}"));
77+
r.Hits.ForEach(h => Console.WriteLine($" - Record ObjectID: {h.ObjectID}, {h.AdditionalProperties.Count}"));
78+
7979

8080
// Browse Helper, to fetch all pages
8181
Console.WriteLine("--- Browse all objects, all pages `BrowseObjectsAsync` ---");
@@ -102,14 +102,13 @@ await PlaygroundHelper.Start(
102102

103103
var getObjResults = await client.GetObjectsAsync<TestObject>(new GetObjectsParams(getObjRequests));
104104
getObjResults.Results.ForEach(t =>
105-
Console.WriteLine($" - Record ObjectID: {t.ObjectID} - Property `otherValue`: {t.otherValue}"));
105+
Console.WriteLine($" - Record ObjectID: {t.ObjectID} - Property `otherValue`: {t.OtherValue}"));
106106

107107
// Search single index
108108
Console.WriteLine("--- Search single index `SearchSingleIndexAsync` ---");
109109
var t = await client.SearchSingleIndexAsync<TestObject>(defaultIndex);
110110
t.Hits.ForEach(h => Console.WriteLine($" - Record ObjectID: {h.ObjectID}"));
111111

112-
// Search
113112
Console.WriteLine("--- Search multiple indices `SearchAsync` ---");
114113
var searchQueries = new List<SearchQuery>
115114
{
@@ -122,7 +121,8 @@ await PlaygroundHelper.Start(
122121
{
123122
if (result.IsSearchResponse())
124123
{
125-
Console.WriteLine($"Record with Hits: ObjectID = {result.AsSearchResponse().Hits.First().ObjectID}");
124+
Console.WriteLine(
125+
$"Record with Hits: ObjectID = {result.AsSearchResponse().Hits.First().ObjectID}, {result.AsSearchResponse().Hits.First().AdditionalProperties.Count}");
126126
}
127127
else if (result.IsSearchForFacetValuesResponse())
128128
{
@@ -189,7 +189,7 @@ await PlaygroundHelper.Start("Deleting API Key", async () =>
189189
},
190190
}).ConfigureAwait(false);
191191

192-
await PlaygroundHelper.Start("Creating new Synonyms - Async TaskID: `{synonymsResponse.TaskID}`", async () =>
192+
await PlaygroundHelper.Start($"Creating new Synonyms - Async TaskID: `{synonymsResponse.TaskID}`", async () =>
193193
await client.WaitForTaskAsync(defaultIndex, synonymsResponse.TaskID), "New Synonyms has been created !");
194194

195195
// Search Synonyms
@@ -198,13 +198,16 @@ await PlaygroundHelper.Start("Deleting API Key", async () =>
198198
.SearchSynonymsAsync(defaultIndex,
199199
new SearchSynonymsParams { Query = "", Type = SynonymType.Onewaysynonym, HitsPerPage = 1 })
200200
.ConfigureAwait(false);
201-
Console.WriteLine(searchSynonymsAsync.Hits.Count);
201+
202+
searchSynonymsAsync.Hits.ForEach(s => Console.WriteLine("Found :" + string.Join(',', s.Synonyms)));
202203

203204
// Browse Synonyms
204-
// var configuredTaskAwaitable = await client
205-
// .BrowseSynonymsAsync("test-csharp-new-client", SynonymType.Onewaysynonym, new SearchSynonymsParams { Query = "" })
206-
// .ConfigureAwait(false);
207-
// configuredTaskAwaitable.ToList().ForEach(s => Console.WriteLine("Found :" + string.Join(',', s.Synonyms)));
205+
Console.WriteLine("--- Browse Synonyms `BrowseSynonymsAsync` ---");
206+
var configuredTaskAwaitable = await client
207+
.BrowseSynonymsAsync("test-csharp-new-client",
208+
new SearchSynonymsParams { Query = "", Type = SynonymType.Onewaysynonym })
209+
.ConfigureAwait(false);
210+
configuredTaskAwaitable.ToList().ForEach(s => Console.WriteLine("Found :" + string.Join(',', s.Synonyms)));
208211

209212
// Add Rule
210213
Console.WriteLine("--- Create new Rule `SaveRulesAsync` ---");

templates/csharp/modelOneOf.mustache

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,20 @@
150150
{{/discriminator}}
151151
{{/useOneOfDiscriminatorLookup}}
152152
{{#vendorExtensions}}
153+
var jToken = JToken.Parse(jsonString);
153154
{{#composedSchemas.oneOf}}
154-
try
155-
{
156-
return new {{classname}}{{#x-has-child-generic}}<T>{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}<T>{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.DeserializeOneOfSettings));
157-
}
158-
catch (Exception exception)
159-
{
160-
// deserialization failed, try the next one
161-
System.Diagnostics.Debug.WriteLine($"Failed to deserialize `{jsonString}` into {{{datatypeWithEnum}}}: {exception}");
162-
}
155+
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}})
156+
{
157+
try
158+
{
159+
return new {{classname}}{{#x-has-child-generic}}<T>{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}<T>{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.AlgoliaJsonSerializerSettings));
160+
}
161+
catch (Exception exception)
162+
{
163+
// deserialization failed, try the next one
164+
System.Diagnostics.Debug.WriteLine($"Failed to deserialize `{jsonString}` into {{{datatypeWithEnum}}}: {exception}");
165+
}
166+
}
163167
{{/composedSchemas.oneOf}}
164168
{{/vendorExtensions}}
165169

0 commit comments

Comments
 (0)