From a835ac807e32aecd22879d1489f4fb67daa277ff Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Fri, 14 Nov 2025 18:16:22 +0100 Subject: [PATCH 01/11] Json : Normalize --- .../Config/NewtonsoftJsonParsingConfig.cs | 17 +- ...izationNonExistingPropertyValueBehavior.cs | 17 ++ .../JsonValueInfo.cs | 10 ++ .../NewtonsoftJsonExtensions.cs | 9 +- .../Utils/NormalizeUtils.cs | 131 +++++++++++++++ ...izationNonExistingPropertyValueBehavior.cs | 17 ++ .../Config/SystemTextJsonParsingConfig.cs | 20 ++- .../Extensions/JsonValueExtensions.cs | 21 +++ .../JsonValueInfo.cs | 8 + .../SystemTextJsonExtensions.cs | 10 +- .../Utils/NormalizeUtils.cs | 156 ++++++++++++++++++ .../NewtonsoftJsonTests.cs | 54 +++--- .../SystemTextJsonTests.cs | 29 ++++ 13 files changed, 466 insertions(+), 33 deletions(-) create mode 100644 src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyValueBehavior.cs create mode 100644 src/System.Linq.Dynamic.Core.NewtonsoftJson/JsonValueInfo.cs create mode 100644 src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs create mode 100644 src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyValueBehavior.cs create mode 100644 src/System.Linq.Dynamic.Core.SystemTextJson/Extensions/JsonValueExtensions.cs create mode 100644 src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs create mode 100644 src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs index fad7f9f1..fd4363d3 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs @@ -15,5 +15,20 @@ public class NewtonsoftJsonParsingConfig : ParsingConfig /// /// The default to use. /// - public DynamicJsonClassOptions? DynamicJsonClassOptions { get; set; } + public DynamicJsonClassOptions? DynamicJsonClassOptions { get; set; } + + /// + /// Gets or sets a value indicating whether the objecs in an array should be normalized before processing. + /// + public bool Normalize { get; set; } = true; + + /// + /// Gets or sets the behavior to apply when a property value does not exist during normalization. + /// + /// + /// Use this property to control how the normalization process handles properties that are missing or undefined. + /// The selected behavior may affect the output or error handling of normalization operations. + /// The default value is . + /// + public NormalizationNonExistingPropertyValueBehavior NormalizationNonExistingPropertyValueBehavior { get; set; } } \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyValueBehavior.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyValueBehavior.cs new file mode 100644 index 00000000..4b70b624 --- /dev/null +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyValueBehavior.cs @@ -0,0 +1,17 @@ +namespace System.Linq.Dynamic.Core.NewtonsoftJson.Config; + +/// +/// Specifies the behavior to use when setting a property vlue that does not exist or is missing during normalization. +/// +public enum NormalizationNonExistingPropertyValueBehavior +{ + /// + /// Specifies that the default value should be used. + /// + UseDefaultValue = 0, + + /// + /// Specifies that null values should be used. + /// + UseNull = 1 +} \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/JsonValueInfo.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/JsonValueInfo.cs new file mode 100644 index 00000000..f5f60b22 --- /dev/null +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/JsonValueInfo.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json.Linq; + +namespace ConsoleApp3; + +internal struct JsonValueInfo(JTokenType type, object? value) +{ + public JTokenType Type { get; } = type; + + public object? Value { get; } = value; +} \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/NewtonsoftJsonExtensions.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/NewtonsoftJsonExtensions.cs index 8aefa397..943df3dd 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/NewtonsoftJsonExtensions.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/NewtonsoftJsonExtensions.cs @@ -1,6 +1,7 @@ using System.Collections; using System.Linq.Dynamic.Core.NewtonsoftJson.Config; using System.Linq.Dynamic.Core.NewtonsoftJson.Extensions; +using System.Linq.Dynamic.Core.NewtonsoftJson.Utils; using System.Linq.Dynamic.Core.Validation; using JetBrains.Annotations; using Newtonsoft.Json.Linq; @@ -870,7 +871,13 @@ private static JArray ToJArray(Func func) private static IQueryable ToQueryable(JArray source, NewtonsoftJsonParsingConfig? config = null) { - return source.ToDynamicJsonClassArray(config?.DynamicJsonClassOptions).AsQueryable(); + var normalized = config?.Normalize == true ? + NormalizeUtils.NormalizeArray(source, config.NormalizationNonExistingPropertyValueBehavior): + source; + + return normalized + .ToDynamicJsonClassArray(config?.DynamicJsonClassOptions) + .AsQueryable(); } #endregion } \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs new file mode 100644 index 00000000..2fde9492 --- /dev/null +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using System.Linq.Dynamic.Core.NewtonsoftJson.Config; +using ConsoleApp3; +using Newtonsoft.Json.Linq; + +namespace System.Linq.Dynamic.Core.NewtonsoftJson.Utils; + +internal static class NormalizeUtils +{ + /// + /// Normalizes an array of JSON objects so that each object contains all properties found in the array, + /// including nested objects. Missing properties will have null values. + /// + internal static JArray NormalizeArray(JArray jsonArray, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + { + if (jsonArray.Count(item => item is not JObject) > 0) + { + return jsonArray; + } + + var schema = BuildSchema(jsonArray); + var normalizedArray = new JArray(); + + foreach (var jo in jsonArray.OfType()) + { + var normalizedObj = NormalizeObject(jo, schema, normalizationBehavior); + normalizedArray.Add(normalizedObj); + } + + return normalizedArray; + } + + private static Dictionary BuildSchema(JArray array) + { + var schema = new Dictionary(); + + foreach (var item in array) + { + if (item is JObject obj) + { + MergeSchema(schema, obj); + } + } + + return schema; + } + + private static void MergeSchema(Dictionary schema, JObject obj) + { + foreach (var prop in obj.Properties()) + { + if (prop.Value is JObject nested) + { + if (!schema.ContainsKey(prop.Name)) + { + schema[prop.Name] = new JsonValueInfo(JTokenType.Object, new Dictionary()); + } + + MergeSchema((Dictionary)schema[prop.Name].Value!, nested); + } + else + { + if (!schema.ContainsKey(prop.Name)) + { + schema[prop.Name] = new JsonValueInfo(prop.Value.Type, null); + } + } + } + } + + private static JObject NormalizeObject(JObject source, Dictionary schema, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + { + var result = new JObject(); + + foreach (var key in schema.Keys) + { + if (schema[key].Value is Dictionary nestedSchema) + { + result[key] = source.ContainsKey(key) && source[key] is JObject jo ? NormalizeObject(jo, nestedSchema, normalizationBehavior) : CreateEmptyObject(nestedSchema, normalizationBehavior); + } + else + { + if (source.ContainsKey(key)) + { + result[key] = source[key]; + } + else + { + result[key] = normalizationBehavior == NormalizationNonExistingPropertyValueBehavior.UseDefaultValue ? GetDefaultValue(schema[key]) : JValue.CreateNull(); + } + } + } + + return result; + } + + private static JObject CreateEmptyObject(Dictionary schema, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + { + var obj = new JObject(); + foreach (var key in schema.Keys) + { + if (schema[key].Value is Dictionary nestedSchema) + { + obj[key] = CreateEmptyObject(nestedSchema, normalizationBehavior); + } + else + { + obj[key] = normalizationBehavior == NormalizationNonExistingPropertyValueBehavior.UseDefaultValue ? GetDefaultValue(schema[key]) : JValue.CreateNull(); + } + } + + return obj; + } + + private static JToken GetDefaultValue(JsonValueInfo jType) + { + return jType.Type switch + { + JTokenType.Array => new JArray(), + JTokenType.Boolean => default(bool), + JTokenType.Bytes => new byte[0], + JTokenType.Date => DateTime.MinValue, + JTokenType.Float => default(float), + JTokenType.Guid => Guid.Empty, + JTokenType.Integer => default(int), + JTokenType.String => string.Empty, + JTokenType.TimeSpan => TimeSpan.MinValue, + _ => JValue.CreateNull(), + }; + } +} \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyValueBehavior.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyValueBehavior.cs new file mode 100644 index 00000000..060b8a10 --- /dev/null +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyValueBehavior.cs @@ -0,0 +1,17 @@ +namespace System.Linq.Dynamic.Core.SystemTextJson.Config; + +/// +/// Specifies the behavior to use when setting a property vlue that does not exist or is missing during normalization. +/// +public enum NormalizationNonExistingPropertyValueBehavior +{ + /// + /// Specifies that the default value should be used. + /// + UseDefaultValue = 0, + + /// + /// Specifies that null values should be used. + /// + UseNull = 1 +} \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs index eb42ff6d..df20eaea 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs @@ -8,5 +8,23 @@ public class SystemTextJsonParsingConfig : ParsingConfig /// /// The default ParsingConfig for . /// - public new static SystemTextJsonParsingConfig Default { get; } = new(); + public new static SystemTextJsonParsingConfig Default { get; } = new SystemTextJsonParsingConfig + { + ConvertObjectToSupportComparison = true + }; + + /// + /// Gets or sets a value indicating whether the objecs in an array should be normalized before processing. + /// + public bool Normalize { get; set; } = true; + + /// + /// Gets or sets the behavior to apply when a property value does not exist during normalization. + /// + /// + /// Use this property to control how the normalization process handles properties that are missing or undefined. + /// The selected behavior may affect the output or error handling of normalization operations. + /// The default value is . + /// + public NormalizationNonExistingPropertyValueBehavior NormalizationNonExistingPropertyValueBehavior { get; set; } } \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Extensions/JsonValueExtensions.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Extensions/JsonValueExtensions.cs new file mode 100644 index 00000000..907f7bf3 --- /dev/null +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Extensions/JsonValueExtensions.cs @@ -0,0 +1,21 @@ +#if !NET8_0_OR_GREATER +namespace System.Text.Json.Nodes; + +internal static class JsonValueExtensions +{ + internal static JsonValueKind? GetValueKind(this JsonNode node) + { + if (node is JsonObject) + { + return JsonValueKind.Object; + } + + if (node is JsonArray) + { + return JsonValueKind.Array; + } + + return node.GetValue() is JsonElement je ? je.ValueKind : null; + } +} +#endif \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs new file mode 100644 index 00000000..01f69b07 --- /dev/null +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs @@ -0,0 +1,8 @@ +using System.Text.Json; + +internal struct JsonValueInfo(JsonValueKind type, object? value) +{ + public JsonValueKind Type { get; } = type; + + public object? Value { get; } = value; +} \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/SystemTextJsonExtensions.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/SystemTextJsonExtensions.cs index 8d1671a0..a60c72db 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/SystemTextJsonExtensions.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/SystemTextJsonExtensions.cs @@ -5,6 +5,7 @@ using System.Linq.Dynamic.Core.SystemTextJson.Utils; using System.Linq.Dynamic.Core.Validation; using System.Text.Json; +using ConsoleApp3; using JetBrains.Annotations; namespace System.Linq.Dynamic.Core.SystemTextJson; @@ -1093,13 +1094,20 @@ private static JsonDocument ToJsonDocumentArray(Func func) // ReSharper disable once UnusedParameter.Local private static IQueryable ToQueryable(JsonDocument source, SystemTextJsonParsingConfig? config = null) { + config = config ?? SystemTextJsonParsingConfig.Default; + config.ConvertObjectToSupportComparison = true; + var array = source.RootElement; if (array.ValueKind != JsonValueKind.Array) { throw new NotSupportedException("The source is not a JSON array."); } - return JsonDocumentExtensions.ToDynamicJsonClassArray(array).AsQueryable(); + var normalized = config.Normalize ? + NormalizeUtils.NormalizeJsonDocument(source, config.NormalizationNonExistingPropertyValueBehavior) : + source; + + return JsonDocumentExtensions.ToDynamicJsonClassArray(normalized.RootElement).AsQueryable(); } #endregion } \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs new file mode 100644 index 00000000..d901c1f3 --- /dev/null +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core.SystemTextJson.Config; +using System.Text.Json; +using System.Text.Json.Nodes; + +namespace ConsoleApp3; + +internal static class NormalizeUtils +{ + /// + /// Normalizes an document that each object contains all properties found in the array, including nested objects. + /// + internal static JsonDocument NormalizeJsonDocument(JsonDocument jsonDocument, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + { + if (jsonDocument.RootElement.ValueKind != JsonValueKind.Array) + { + throw new NotSupportedException("The source is not a JSON array."); + } + + var jsonArray = JsonNode.Parse(jsonDocument.RootElement.GetRawText())!.AsArray(); + var normalizedArray = NormalizeJsonArray(jsonArray, normalizationBehavior); + + return JsonDocument.Parse(normalizedArray.ToJsonString()); + } + + /// + /// Normalizes an array of JSON objects so that each object contains all properties found in the array, including nested objects. + /// + internal static JsonArray NormalizeJsonArray(JsonArray jsonArray, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + { + if (jsonArray.Any(item => item != null && item.GetValueKind() != JsonValueKind.Object)) + { + return jsonArray; + } + + var schema = BuildSchema(jsonArray); + var normalizedArray = new JsonArray(); + + foreach (var item in jsonArray) + { + if (item is JsonObject obj) + { + var normalizedObj = NormalizeObject(obj, schema, normalizationBehavior); + normalizedArray.Add(normalizedObj); + } + } + + return normalizedArray; + } + + private static Dictionary BuildSchema(JsonArray array) + { + var schema = new Dictionary(); + + foreach (var item in array) + { + if (item is JsonObject obj) + { + MergeSchema(schema, obj); + } + } + + return schema; + } + + private static void MergeSchema(Dictionary schema, JsonObject obj) + { + foreach (var prop in obj) + { + if (prop.Value is JsonObject nested) + { + if (!schema.ContainsKey(prop.Key)) + { + schema[prop.Key] = new JsonValueInfo(JsonValueKind.Object, new Dictionary()); + } + + MergeSchema((Dictionary)schema[prop.Key].Value!, nested); + } + else + { + if (!schema.ContainsKey(prop.Key)) + { + schema[prop.Key] = new JsonValueInfo(prop.Value?.GetValueKind() ?? JsonValueKind.Null, null); + } + } + } + } + + private static JsonObject NormalizeObject(JsonObject source, Dictionary schema, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + { + var result = new JsonObject(); + + foreach (var kvp in schema) + { + var key = kvp.Key; + var jType = kvp.Value; + + if (jType.Value is Dictionary nestedSchema) + { + result[key] = source.ContainsKey(key) && source[key] is JsonObject jo ? NormalizeObject(jo, nestedSchema, normalizationBehavior) : CreateEmptyObject(nestedSchema, normalizationBehavior); + } + else + { + if (source.ContainsKey(key)) + { +#if NET8_0_OR_GREATER + result[key] = source[key]!.DeepClone(); +#else + result[key] = JsonNode.Parse(source[key]!.ToJsonString()); +#endif + } + else + { + result[key] = normalizationBehavior == NormalizationNonExistingPropertyValueBehavior.UseDefaultValue ? GetDefaultValue(jType) : null; + } + } + } + + return result; + } + + private static JsonObject CreateEmptyObject(Dictionary schema, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + { + var obj = new JsonObject(); + foreach (var kvp in schema) + { + var key = kvp.Key; + var jType = kvp.Value; + + if (jType.Value is Dictionary nestedSchema) + { + obj[key] = CreateEmptyObject(nestedSchema, normalizationBehavior); + } + else + { + obj[key] = normalizationBehavior == NormalizationNonExistingPropertyValueBehavior.UseDefaultValue ? GetDefaultValue(jType) : null; + } + } + + return obj; + } + + private static JsonNode? GetDefaultValue(JsonValueInfo jType) + { + return jType.Type switch + { + JsonValueKind.Array => new JsonArray(), + JsonValueKind.False => false, + JsonValueKind.True => false, + JsonValueKind.Number => default(int), + _ => null, + }; + } +} \ No newline at end of file diff --git a/test/System.Linq.Dynamic.Core.NewtonsoftJson.Tests/NewtonsoftJsonTests.cs b/test/System.Linq.Dynamic.Core.NewtonsoftJson.Tests/NewtonsoftJsonTests.cs index 40185d45..4387e730 100644 --- a/test/System.Linq.Dynamic.Core.NewtonsoftJson.Tests/NewtonsoftJsonTests.cs +++ b/test/System.Linq.Dynamic.Core.NewtonsoftJson.Tests/NewtonsoftJsonTests.cs @@ -508,35 +508,31 @@ public void Where_With_Select() first.Value().Should().Be("Doe"); } - //[Fact] - //public void Where_OptionalProperty() - //{ - // // Arrange - // var config = new NewtonsoftJsonParsingConfig - // { - // ConvertObjectToSupportComparison = true - // }; - // var array = - // """ - // [ - // { - // "Name": "John", - // "Age": 30 - // }, - // { - // "Name": "Doe" - // } - // ] - // """; - - // // Act - // var result = JArray.Parse(array).Where(config, "Age > 30").Select("Name"); - - // // Assert - // result.Should().HaveCount(1); - // var first = result.First(); - // first.Value().Should().Be("John"); - //} + [Fact] + public void Where_OptionalProperty() + { + // Arrange + var array = + """ + [ + { + "Name": "John", + "Age": 30 + }, + { + "Name": "Doe" + } + ] + """; + + // Act + var result = JArray.Parse(array).Where("Age >= 30").Select("Name"); + + // Assert + result.Should().HaveCount(1); + var first = result.First(); + first.Value().Should().Be("John"); + } [Theory] [InlineData("notExisting == true")] diff --git a/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs b/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs index 1e817664..3ff80829 100644 --- a/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs +++ b/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs @@ -1,6 +1,7 @@ using System.Linq.Dynamic.Core.SystemTextJson.Config; using System.Text.Json; using FluentAssertions; +using Newtonsoft.Json.Linq; using Xunit; namespace System.Linq.Dynamic.Core.SystemTextJson.Tests; @@ -537,6 +538,34 @@ public void Where_With_Select() array.First().GetString().Should().Be("Doe"); } + [Fact] + public void Where_OptionalProperty() + { + // Arrange + var data = + """ + [ + { + "Name": "John", + "Age": 30 + }, + { + "Name": "Doe" + } + ] + """; + var source = JsonDocument.Parse(data); + + // Act + var result = source.Where("Age >= 30").Select("Name"); + + // Assert + var array = result.RootElement.EnumerateArray(); + array.Should().HaveCount(1); + var first = result.First(); + array.First().GetString().Should().Be("John"); + } + [Theory] [InlineData("notExisting == true")] [InlineData("notExisting == \"true\"")] From 812e0ce0eaabfba2e0ce27748faf975b082fce31 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 08:40:03 +0100 Subject: [PATCH 02/11] . --- .../Config/NewtonsoftJsonParsingConfig.cs | 4 ++-- ...ormalizationNonExistingPropertyBehavior.cs} | 2 +- .../JsonValueInfo.cs | 4 ++-- .../Utils/NormalizeUtils.cs | 11 +++++------ ...ormalizationNonExistingPropertyBehavior.cs} | 2 +- .../Config/SystemTextJsonParsingConfig.cs | 4 ++-- .../JsonValueInfo.cs | 2 +- .../SystemTextJsonExtensions.cs | 1 - .../Utils/NormalizeUtils.cs | 18 ++++++++---------- 9 files changed, 22 insertions(+), 26 deletions(-) rename src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/{NormalizationNonExistingPropertyValueBehavior.cs => NormalizationNonExistingPropertyBehavior.cs} (88%) rename src/System.Linq.Dynamic.Core.SystemTextJson/Config/{NormalizationNonExistingPropertyValueBehavior.cs => NormalizationNonExistingPropertyBehavior.cs} (88%) diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs index fd4363d3..3a6a7002 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs @@ -28,7 +28,7 @@ public class NewtonsoftJsonParsingConfig : ParsingConfig /// /// Use this property to control how the normalization process handles properties that are missing or undefined. /// The selected behavior may affect the output or error handling of normalization operations. - /// The default value is . + /// The default value is . /// - public NormalizationNonExistingPropertyValueBehavior NormalizationNonExistingPropertyValueBehavior { get; set; } + public NormalizationNonExistingPropertyBehavior NormalizationNonExistingPropertyValueBehavior { get; set; } } \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyValueBehavior.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyBehavior.cs similarity index 88% rename from src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyValueBehavior.cs rename to src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyBehavior.cs index 4b70b624..4af8a320 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyValueBehavior.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyBehavior.cs @@ -3,7 +3,7 @@ /// /// Specifies the behavior to use when setting a property vlue that does not exist or is missing during normalization. /// -public enum NormalizationNonExistingPropertyValueBehavior +public enum NormalizationNonExistingPropertyBehavior { /// /// Specifies that the default value should be used. diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/JsonValueInfo.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/JsonValueInfo.cs index f5f60b22..963ff37d 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/JsonValueInfo.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/JsonValueInfo.cs @@ -1,8 +1,8 @@ using Newtonsoft.Json.Linq; -namespace ConsoleApp3; +namespace System.Linq.Dynamic.Core.NewtonsoftJson; -internal struct JsonValueInfo(JTokenType type, object? value) +internal readonly struct JsonValueInfo(JTokenType type, object? value) { public JTokenType Type { get; } = type; diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs index 2fde9492..c46d160a 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq.Dynamic.Core.NewtonsoftJson.Config; -using ConsoleApp3; using Newtonsoft.Json.Linq; namespace System.Linq.Dynamic.Core.NewtonsoftJson.Utils; @@ -11,7 +10,7 @@ internal static class NormalizeUtils /// Normalizes an array of JSON objects so that each object contains all properties found in the array, /// including nested objects. Missing properties will have null values. /// - internal static JArray NormalizeArray(JArray jsonArray, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + internal static JArray NormalizeArray(JArray jsonArray, NormalizationNonExistingPropertyBehavior normalizationBehavior) { if (jsonArray.Count(item => item is not JObject) > 0) { @@ -68,7 +67,7 @@ private static void MergeSchema(Dictionary schema, JObjec } } - private static JObject NormalizeObject(JObject source, Dictionary schema, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + private static JObject NormalizeObject(JObject source, Dictionary schema, NormalizationNonExistingPropertyBehavior normalizationBehavior) { var result = new JObject(); @@ -86,7 +85,7 @@ private static JObject NormalizeObject(JObject source, Dictionary schema, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + private static JObject CreateEmptyObject(Dictionary schema, NormalizationNonExistingPropertyBehavior normalizationBehavior) { var obj = new JObject(); foreach (var key in schema.Keys) @@ -105,7 +104,7 @@ private static JObject CreateEmptyObject(Dictionary schem } else { - obj[key] = normalizationBehavior == NormalizationNonExistingPropertyValueBehavior.UseDefaultValue ? GetDefaultValue(schema[key]) : JValue.CreateNull(); + obj[key] = normalizationBehavior == NormalizationNonExistingPropertyBehavior.UseDefaultValue ? GetDefaultValue(schema[key]) : JValue.CreateNull(); } } diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyValueBehavior.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyBehavior.cs similarity index 88% rename from src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyValueBehavior.cs rename to src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyBehavior.cs index 060b8a10..daafaa4b 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyValueBehavior.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/NormalizationNonExistingPropertyBehavior.cs @@ -3,7 +3,7 @@ /// /// Specifies the behavior to use when setting a property vlue that does not exist or is missing during normalization. /// -public enum NormalizationNonExistingPropertyValueBehavior +public enum NormalizationNonExistingPropertyBehavior { /// /// Specifies that the default value should be used. diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs index df20eaea..6bc69d4f 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs @@ -24,7 +24,7 @@ public class SystemTextJsonParsingConfig : ParsingConfig /// /// Use this property to control how the normalization process handles properties that are missing or undefined. /// The selected behavior may affect the output or error handling of normalization operations. - /// The default value is . + /// The default value is . /// - public NormalizationNonExistingPropertyValueBehavior NormalizationNonExistingPropertyValueBehavior { get; set; } + public NormalizationNonExistingPropertyBehavior NormalizationNonExistingPropertyValueBehavior { get; set; } } \ No newline at end of file diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs index 01f69b07..2a413078 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs @@ -1,6 +1,6 @@ using System.Text.Json; -internal struct JsonValueInfo(JsonValueKind type, object? value) +internal readonly struct JsonValueInfo(JsonValueKind type, object? value) { public JsonValueKind Type { get; } = type; diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/SystemTextJsonExtensions.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/SystemTextJsonExtensions.cs index a60c72db..6d8a5aa0 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/SystemTextJsonExtensions.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/SystemTextJsonExtensions.cs @@ -5,7 +5,6 @@ using System.Linq.Dynamic.Core.SystemTextJson.Utils; using System.Linq.Dynamic.Core.Validation; using System.Text.Json; -using ConsoleApp3; using JetBrains.Annotations; namespace System.Linq.Dynamic.Core.SystemTextJson; diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs index d901c1f3..c569504b 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs @@ -1,18 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Linq.Dynamic.Core.SystemTextJson.Config; using System.Text.Json; using System.Text.Json.Nodes; -namespace ConsoleApp3; +namespace System.Linq.Dynamic.Core.SystemTextJson.Utils; internal static class NormalizeUtils { /// /// Normalizes an document that each object contains all properties found in the array, including nested objects. /// - internal static JsonDocument NormalizeJsonDocument(JsonDocument jsonDocument, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + internal static JsonDocument NormalizeJsonDocument(JsonDocument jsonDocument, NormalizationNonExistingPropertyBehavior normalizationBehavior) { if (jsonDocument.RootElement.ValueKind != JsonValueKind.Array) { @@ -28,7 +26,7 @@ internal static JsonDocument NormalizeJsonDocument(JsonDocument jsonDocument, No /// /// Normalizes an array of JSON objects so that each object contains all properties found in the array, including nested objects. /// - internal static JsonArray NormalizeJsonArray(JsonArray jsonArray, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + internal static JsonArray NormalizeJsonArray(JsonArray jsonArray, NormalizationNonExistingPropertyBehavior normalizationBehavior) { if (jsonArray.Any(item => item != null && item.GetValueKind() != JsonValueKind.Object)) { @@ -88,7 +86,7 @@ private static void MergeSchema(Dictionary schema, JsonOb } } - private static JsonObject NormalizeObject(JsonObject source, Dictionary schema, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + private static JsonObject NormalizeObject(JsonObject source, Dictionary schema, NormalizationNonExistingPropertyBehavior normalizationBehavior) { var result = new JsonObject(); @@ -113,7 +111,7 @@ private static JsonObject NormalizeObject(JsonObject source, Dictionary schema, NormalizationNonExistingPropertyValueBehavior normalizationBehavior) + private static JsonObject CreateEmptyObject(Dictionary schema, NormalizationNonExistingPropertyBehavior normalizationBehavior) { var obj = new JsonObject(); foreach (var kvp in schema) @@ -135,7 +133,7 @@ private static JsonObject CreateEmptyObject(Dictionary sc } else { - obj[key] = normalizationBehavior == NormalizationNonExistingPropertyValueBehavior.UseDefaultValue ? GetDefaultValue(jType) : null; + obj[key] = normalizationBehavior == NormalizationNonExistingPropertyBehavior.UseDefaultValue ? GetDefaultValue(jType) : null; } } From bee9dea075b9638bad4814df06538980c431881c Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 09:28:16 +0100 Subject: [PATCH 03/11] tst --- .../NewtonsoftJsonTests.cs | 62 +++++++++-------- .../SystemTextJsonTests.cs | 67 ++++++++++--------- 2 files changed, 70 insertions(+), 59 deletions(-) diff --git a/test/System.Linq.Dynamic.Core.NewtonsoftJson.Tests/NewtonsoftJsonTests.cs b/test/System.Linq.Dynamic.Core.NewtonsoftJson.Tests/NewtonsoftJsonTests.cs index 4387e730..e391ed29 100644 --- a/test/System.Linq.Dynamic.Core.NewtonsoftJson.Tests/NewtonsoftJsonTests.cs +++ b/test/System.Linq.Dynamic.Core.NewtonsoftJson.Tests/NewtonsoftJsonTests.cs @@ -1,4 +1,5 @@ -using System.Linq.Dynamic.Core.NewtonsoftJson.Config; +using System.Linq.Dynamic.Core.Exceptions; +using System.Linq.Dynamic.Core.NewtonsoftJson.Config; using FluentAssertions; using Newtonsoft.Json.Linq; using Xunit; @@ -508,32 +509,6 @@ public void Where_With_Select() first.Value().Should().Be("Doe"); } - [Fact] - public void Where_OptionalProperty() - { - // Arrange - var array = - """ - [ - { - "Name": "John", - "Age": 30 - }, - { - "Name": "Doe" - } - ] - """; - - // Act - var result = JArray.Parse(array).Where("Age >= 30").Select("Name"); - - // Assert - result.Should().HaveCount(1); - var first = result.First(); - first.Value().Should().Be("John"); - } - [Theory] [InlineData("notExisting == true")] [InlineData("notExisting == \"true\"")] @@ -561,4 +536,37 @@ public void Where_NonExistingMember_EmptyResult(string predicate) // Assert result.Should().BeEmpty(); } + + [Theory] + [InlineData("""[ { "Name": "John", "Age": 30 }, { "Name": "Doe" }, { } ]""")] + [InlineData("""[ { "Name": "Doe" }, { "Name": "John", "Age": 30 }, { } ]""")] + public void NormalizeArray(string array) + { + // Act + var result = JArray.Parse(array) + .Where("Age >= 30") + .Select("Name"); + + // Assert + result.Should().HaveCount(1); + var first = result.First(); + first.Value().Should().Be("John"); + } + + [Fact] + public void NormalizeArray_When_NormalizeIsFalse_ShouldThrow() + { + // Arrange + var config = new NewtonsoftJsonParsingConfig + { + Normalize = false + }; + var array = """[ { "Name": "Doe" }, { "Name": "John", "Age": 30 }, { } ]"""; + + // Act + Action act = () => JArray.Parse(array).Where(config, "Age >= 30"); + + // Assert + act.Should().Throw().WithMessage("The binary operator GreaterThanOrEqual is not defined for the types 'System.Object' and 'System.Int32'."); + } } \ No newline at end of file diff --git a/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs b/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs index 3ff80829..de149028 100644 --- a/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs +++ b/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs @@ -1,7 +1,6 @@ using System.Linq.Dynamic.Core.SystemTextJson.Config; using System.Text.Json; using FluentAssertions; -using Newtonsoft.Json.Linq; using Xunit; namespace System.Linq.Dynamic.Core.SystemTextJson.Tests; @@ -538,34 +537,6 @@ public void Where_With_Select() array.First().GetString().Should().Be("Doe"); } - [Fact] - public void Where_OptionalProperty() - { - // Arrange - var data = - """ - [ - { - "Name": "John", - "Age": 30 - }, - { - "Name": "Doe" - } - ] - """; - var source = JsonDocument.Parse(data); - - // Act - var result = source.Where("Age >= 30").Select("Name"); - - // Assert - var array = result.RootElement.EnumerateArray(); - array.Should().HaveCount(1); - var first = result.First(); - array.First().GetString().Should().Be("John"); - } - [Theory] [InlineData("notExisting == true")] [InlineData("notExisting == \"true\"")] @@ -580,17 +551,49 @@ public void Where_OptionalProperty() [InlineData("\"something\" == notExisting")] [InlineData("1 < notExisting")] public void Where_NonExistingMember_EmptyResult(string predicate) + { + // Act + var result = _source.Where(predicate).RootElement.EnumerateArray(); + + // Assert + result.Should().BeEmpty(); + } + + [Theory] + [InlineData("""[ { "Name": "John", "Age": 30 }, { "Name": "Doe" }, { } ]""")] + [InlineData("""[ { "Name": "Doe" }, { "Name": "John", "Age": 30 }, { } ]""")] + public void NormalizeArray(string data) + { + // Arrange + var source = JsonDocument.Parse(data); + + // Act + var result = source + .Where("Age >= 30") + .Select("Name"); + + // Assert + var array = result.RootElement.EnumerateArray(); + array.Should().HaveCount(1); + var first = result.First(); + array.First().GetString().Should().Be("John"); + } + + [Fact] + public void NormalizeArray_When_NormalizeIsFalse_ShouldThrow() { // Arrange var config = new SystemTextJsonParsingConfig { - ConvertObjectToSupportComparison = true + Normalize = false }; + var data = """[ { "Name": "Doe" }, { "Name": "John", "Age": 30 }, { } ]"""; + var array = JsonDocument.Parse(data); // Act - var result = _source.Where(config, predicate).RootElement.EnumerateArray(); + Action act = () => JsonDocument.Parse(data).Where(config, "Age >= 30"); // Assert - result.Should().BeEmpty(); + act.Should().Throw().WithMessage("Unable to find property 'Age' on type '<>f__AnonymousType*"); } } \ No newline at end of file From e70bc42055d51bff30934ca5d3cabd9a09f8d552 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 10:07:17 +0100 Subject: [PATCH 04/11] ns --- src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs index 2a413078..da4f2b5d 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/JsonValueInfo.cs @@ -1,5 +1,7 @@ using System.Text.Json; +namespace System.Linq.Dynamic.Core.SystemTextJson; + internal readonly struct JsonValueInfo(JsonValueKind type, object? value) { public JsonValueKind Type { get; } = type; From 643bf5af8d1d6b677356cff9fcf74dc7580ac09d Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 10:12:34 +0100 Subject: [PATCH 05/11] sc --- .../Utils/NormalizeUtils.cs | 7 ++++--- .../Utils/NormalizeUtils.cs | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs index c46d160a..03165b54 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs @@ -50,12 +50,13 @@ private static void MergeSchema(Dictionary schema, JObjec { if (prop.Value is JObject nested) { - if (!schema.ContainsKey(prop.Name)) + if (!schema.TryGetValue(prop.Name, out var jsonValueInfo)) { - schema[prop.Name] = new JsonValueInfo(JTokenType.Object, new Dictionary()); + jsonValueInfo = new JsonValueInfo(JTokenType.Object, new Dictionary()); + schema[prop.Name] = jsonValueInfo; } - MergeSchema((Dictionary)schema[prop.Name].Value!, nested); + MergeSchema((Dictionary)jsonValueInfo.Value!, nested); } else { diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs index c569504b..7032af55 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs @@ -69,12 +69,13 @@ private static void MergeSchema(Dictionary schema, JsonOb { if (prop.Value is JsonObject nested) { - if (!schema.ContainsKey(prop.Key)) + if (!schema.TryGetValue(prop.Key, out var jsonValueInfo)) { - schema[prop.Key] = new JsonValueInfo(JsonValueKind.Object, new Dictionary()); + jsonValueInfo = new JsonValueInfo(JsonValueKind.Object, new Dictionary()); + schema[prop.Key] = jsonValueInfo; } - MergeSchema((Dictionary)schema[prop.Key].Value!, nested); + MergeSchema((Dictionary)jsonValueInfo.Value!, nested); } else { From 6392b729dc0eff532aa99dec1923bfc7e44181b9 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 10:19:15 +0100 Subject: [PATCH 06/11] any --- .../Utils/NormalizeUtils.cs | 2 +- .../Utils/NormalizeUtils.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs index 03165b54..5669915c 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Utils/NormalizeUtils.cs @@ -12,7 +12,7 @@ internal static class NormalizeUtils /// internal static JArray NormalizeArray(JArray jsonArray, NormalizationNonExistingPropertyBehavior normalizationBehavior) { - if (jsonArray.Count(item => item is not JObject) > 0) + if (jsonArray.Any(item => item is not JObject)) { return jsonArray; } diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs index 7032af55..1fc72556 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs @@ -147,8 +147,9 @@ private static JsonObject CreateEmptyObject(Dictionary sc { JsonValueKind.Array => new JsonArray(), JsonValueKind.False => false, - JsonValueKind.True => false, JsonValueKind.Number => default(int), + JsonValueKind.String => string.Empty, + JsonValueKind.True => false, _ => null, }; } From b9e13f34ce976efe741bfe99aa9abaf6d70b0368 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 10:44:14 +0100 Subject: [PATCH 07/11] Update src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyBehavior.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Config/NormalizationNonExistingPropertyBehavior.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyBehavior.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyBehavior.cs index 4af8a320..bb68277b 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyBehavior.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NormalizationNonExistingPropertyBehavior.cs @@ -1,7 +1,7 @@ namespace System.Linq.Dynamic.Core.NewtonsoftJson.Config; /// -/// Specifies the behavior to use when setting a property vlue that does not exist or is missing during normalization. +/// Specifies the behavior to use when setting a property value that does not exist or is missing during normalization. /// public enum NormalizationNonExistingPropertyBehavior { From e98ae23bf18cf9a2d8d7d0568ff8414fc955cdba Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 10:44:21 +0100 Subject: [PATCH 08/11] Update src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Config/SystemTextJsonParsingConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs index 6bc69d4f..a4c1e76a 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Config/SystemTextJsonParsingConfig.cs @@ -14,7 +14,7 @@ public class SystemTextJsonParsingConfig : ParsingConfig }; /// - /// Gets or sets a value indicating whether the objecs in an array should be normalized before processing. + /// Gets or sets a value indicating whether the objects in an array should be normalized before processing. /// public bool Normalize { get; set; } = true; From 96609580466e9cb55be7e755d63bbedf8cff0972 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 10:44:34 +0100 Subject: [PATCH 09/11] Update src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Config/NewtonsoftJsonParsingConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs index 3a6a7002..fbccbf64 100644 --- a/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs +++ b/src/System.Linq.Dynamic.Core.NewtonsoftJson/Config/NewtonsoftJsonParsingConfig.cs @@ -18,7 +18,7 @@ public class NewtonsoftJsonParsingConfig : ParsingConfig public DynamicJsonClassOptions? DynamicJsonClassOptions { get; set; } /// - /// Gets or sets a value indicating whether the objecs in an array should be normalized before processing. + /// Gets or sets a value indicating whether the objects in an array should be normalized before processing. /// public bool Normalize { get; set; } = true; From c1ffa97be8311bbaa1c6b007b81a42483e7027a1 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 10:44:42 +0100 Subject: [PATCH 10/11] Update src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Utils/NormalizeUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs index 1fc72556..fa5836d2 100644 --- a/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs +++ b/src/System.Linq.Dynamic.Core.SystemTextJson/Utils/NormalizeUtils.cs @@ -8,7 +8,7 @@ namespace System.Linq.Dynamic.Core.SystemTextJson.Utils; internal static class NormalizeUtils { /// - /// Normalizes an document that each object contains all properties found in the array, including nested objects. + /// Normalizes a document so that each object contains all properties found in the array, including nested objects. /// internal static JsonDocument NormalizeJsonDocument(JsonDocument jsonDocument, NormalizationNonExistingPropertyBehavior normalizationBehavior) { From b372a4d18df8d83f8f2f3708209c26095cf68932 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 15 Nov 2025 10:45:41 +0100 Subject: [PATCH 11/11] . --- .../SystemTextJsonTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs b/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs index de149028..7b27ec5c 100644 --- a/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs +++ b/test/System.Linq.Dynamic.Core.SystemTextJson.Tests/SystemTextJsonTests.cs @@ -588,7 +588,6 @@ public void NormalizeArray_When_NormalizeIsFalse_ShouldThrow() Normalize = false }; var data = """[ { "Name": "Doe" }, { "Name": "John", "Age": 30 }, { } ]"""; - var array = JsonDocument.Parse(data); // Act Action act = () => JsonDocument.Parse(data).Where(config, "Age >= 30");