diff --git a/src/Elastic.Clients.Elasticsearch/Client/ElasticsearchClient.cs b/src/Elastic.Clients.Elasticsearch/Client/ElasticsearchClient.cs index 5e957e0b0bf..2542b8a8265 100644 --- a/src/Elastic.Clients.Elasticsearch/Client/ElasticsearchClient.cs +++ b/src/Elastic.Clients.Elasticsearch/Client/ElasticsearchClient.cs @@ -4,6 +4,8 @@ using System; using System.Linq; +using System.Runtime.CompilerServices; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Elastic.Transport; @@ -15,6 +17,8 @@ public sealed partial class ElasticsearchClient { private readonly ITransport _transport; + internal static ConditionalWeakTable SettingsTable { get; } = new(); + /// /// Creates a client configured to connect to localhost:9200. /// diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/CustomizedNamingPolicy.cs b/src/Elastic.Clients.Elasticsearch/Serialization/CustomizedNamingPolicy.cs new file mode 100644 index 00000000000..e3f283364ac --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/Serialization/CustomizedNamingPolicy.cs @@ -0,0 +1,17 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json; + +namespace Elastic.Clients.Elasticsearch; + +internal class CustomizedNamingPolicy : JsonNamingPolicy +{ + private readonly Func _namingAction; + + public CustomizedNamingPolicy(Func namingAction) => _namingAction = namingAction; + + public override string ConvertName(string name) => _namingAction(name); +} diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/DefaultRequestResponseSerializer.cs b/src/Elastic.Clients.Elasticsearch/Serialization/DefaultRequestResponseSerializer.cs index a018f0cd9e8..48fdd7bd2e5 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/DefaultRequestResponseSerializer.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/DefaultRequestResponseSerializer.cs @@ -13,15 +13,6 @@ namespace Elastic.Clients.Elasticsearch; -internal class CustomizedNamingPolicy : JsonNamingPolicy -{ - private readonly Func _namingAction; - - public CustomizedNamingPolicy(Func namingAction) => _namingAction = namingAction; - - public override string ConvertName(string name) => _namingAction(name); -} - /// /// The built in internal serializer that the high level client Elastic.Clients.Elasticsearch uses. /// @@ -65,6 +56,8 @@ public DefaultRequestResponseSerializer(IElasticsearchClientSettings settings) PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + ElasticsearchClient.SettingsTable.Add(Options, settings); + _settings = settings; } diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/FieldNameQueryConverterBase.cs b/src/Elastic.Clients.Elasticsearch/Serialization/FieldNameQueryConverterBase.cs index 5a5f8a7f284..b07735ccaa7 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/FieldNameQueryConverterBase.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/FieldNameQueryConverterBase.cs @@ -41,10 +41,16 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions if (value.Field is null) writer.WriteNullValue(); - writer.WriteStartObject(); - writer.WritePropertyName(value.Field.ToString()); - WriteInternal(writer, value, options); - writer.WriteEndObject(); + if (options.TryGetClientSettings(out var settings)) + { + writer.WriteStartObject(); + writer.WritePropertyName(settings.Inferrer.Field(value.Field)); + WriteInternal(writer, value, options); + writer.WriteEndObject(); + return; + } + + throw new JsonException("Unable to retrieve client settings to infer field."); } internal abstract T? ReadInternal(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options); diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/JsonSerializerOptionsExtensions.cs b/src/Elastic.Clients.Elasticsearch/Serialization/JsonSerializerOptionsExtensions.cs new file mode 100644 index 00000000000..5d5b267d0dc --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/Serialization/JsonSerializerOptionsExtensions.cs @@ -0,0 +1,13 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +using System.Text.Json; + +namespace Elastic.Clients.Elasticsearch; + +internal static class JsonSerializerOptionsExtensions +{ + public static bool TryGetClientSettings(this JsonSerializerOptions options, out IElasticsearchClientSettings settings) => + ElasticsearchClient.SettingsTable.TryGetValue(options, out settings); +} diff --git a/tests/Tests/Serialization/Queries/SearchSerializationTests.cs b/tests/Tests/Serialization/Queries/SearchSerializationTests.cs new file mode 100644 index 00000000000..b3bacbeac28 --- /dev/null +++ b/tests/Tests/Serialization/Queries/SearchSerializationTests.cs @@ -0,0 +1,28 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch.QueryDsl; +using Tests.Domain; +using VerifyXunit; + +namespace Tests.Serialization.Queries; + +[UsesVerify] +public class SearchSerializationTests : SerializerTestBase +{ + [U] + public async Task Search_WithMatchQuery_SerializesInferredField_ForObjectInitializer() + { + var container = QueryContainer.Match(new MatchQuery + { + Field = Infer.Field(d => d.Description), + Query = "testing" + }); + + var json = SerializeAndGetJsonString(container); + + await Verifier.VerifyJson(json); + } +} diff --git a/tests/Tests/_VerifySnapshots/SearchSerializationTests.Search_WithMatchQuery_SerializesInferredField_ForObjectInitializer.verified.txt b/tests/Tests/_VerifySnapshots/SearchSerializationTests.Search_WithMatchQuery_SerializesInferredField_ForObjectInitializer.verified.txt new file mode 100644 index 00000000000..a9ff7967110 --- /dev/null +++ b/tests/Tests/_VerifySnapshots/SearchSerializationTests.Search_WithMatchQuery_SerializesInferredField_ForObjectInitializer.verified.txt @@ -0,0 +1,7 @@ +{ + match: { + description: { + query: testing + } + } +} \ No newline at end of file