diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 86123a7..4ecd3f3 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -8,7 +8,7 @@ on: - master env: APP_NAME: DynamicExpression - VERSION: 10.0.0 + VERSION: 10.0.1 NUGET_HOST: https://api.nuget.org/v3/index.json NUGET_APIKEY: ${{ secrets.NUGET_APIKEY }} jobs: diff --git a/.tests/Tests.DynamicExpression/Tests.DynamicExpression.csproj b/.tests/Tests.DynamicExpression/Tests.DynamicExpression.csproj index 81ca19f..e60225e 100644 --- a/.tests/Tests.DynamicExpression/Tests.DynamicExpression.csproj +++ b/.tests/Tests.DynamicExpression/Tests.DynamicExpression.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/DynamicExpression/DynamicExpression.csproj b/DynamicExpression/DynamicExpression.csproj index 84e690b..c2eb8b1 100644 --- a/DynamicExpression/DynamicExpression.csproj +++ b/DynamicExpression/DynamicExpression.csproj @@ -3,9 +3,9 @@ net10.0 true AnyCPU + 10.0.0.0 10.0.0.0 10.0.0.0 - 10.0.0.0 latest Michael Vivet Dynamic Expression @@ -15,7 +15,8 @@ Lampda, Expression, Linq, Dynamic, Criteria, Query, Paging, Pagination, Sort, Sorting README.md - - Upgraded to .NET 10. + - Updated NuGets. + - Added Geometry converter for query model binder. https://raw.githubusercontent.com/vivet/DynamicExpression/master/LICENSE LICENSE @@ -47,8 +48,9 @@ - + + diff --git a/DynamicExpression/ModelBinders/Const/Constants.cs b/DynamicExpression/ModelBinders/Const/Constants.cs index 2d4e2b0..9daf667 100644 --- a/DynamicExpression/ModelBinders/Const/Constants.cs +++ b/DynamicExpression/ModelBinders/Const/Constants.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using DynamicExpression.ModelBinders.Converters; +using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace DynamicExpression.ModelBinders.Const; @@ -18,7 +19,8 @@ internal static class Constants PreserveReferencesHandling = PreserveReferencesHandling.None, Converters = { - new StringEnumConverter() + new StringEnumConverter(), + new GeometryConverterIgnoreCase() } }; } \ No newline at end of file diff --git a/DynamicExpression/ModelBinders/Converters/GeometryConverterIgnoreCase.cs b/DynamicExpression/ModelBinders/Converters/GeometryConverterIgnoreCase.cs new file mode 100644 index 0000000..cf2d4d8 --- /dev/null +++ b/DynamicExpression/ModelBinders/Converters/GeometryConverterIgnoreCase.cs @@ -0,0 +1,71 @@ +using System; +using NetTopologySuite.Geometries; +using NetTopologySuite.IO.Converters; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace DynamicExpression.ModelBinders.Converters; + +/// +/// A that ignores case when reading JSON properties for geometries. +/// +public class GeometryConverterIgnoreCase : GeometryConverter +{ + /// + /// Reads JSON into a object, renaming properties to match expected casing. + /// + /// The to read from. + /// The type of object to create. + /// The existing value of the object being read. + /// The used for deserialization. + /// The deserialized geometry object. + /// Thrown if , , or is null. + /// Thrown if the JSON token is not an object. + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + ArgumentNullException.ThrowIfNull(reader); + ArgumentNullException.ThrowIfNull(objectType); + ArgumentNullException.ThrowIfNull(serializer); + + var token = JToken.Load(reader); + + if (token.Type != JTokenType.Object) + { + throw new JsonSerializationException("Expected object"); + } + + var obj = (JObject)token; + + if (objectType.IsSubclassOf(typeof(Geometry))) + { + RenameProperty(obj, "Type", "type"); + RenameProperty(obj, "Coordinates", "coordinates"); + RenameProperty(obj, "Geometries", "geometries"); + } + + var jsonReader = new JTokenReader(obj); + + jsonReader + .Read(); + + return base.ReadJson(jsonReader, objectType, existingValue, serializer); + } + + + private static void RenameProperty(JObject @object, string from, string to) + { + ArgumentNullException.ThrowIfNull(@object); + ArgumentNullException.ThrowIfNull(from); + ArgumentNullException.ThrowIfNull(to); + + if (!@object.TryGetValue(from, StringComparison.OrdinalIgnoreCase, out var value)) + { + return; + } + + @object + .Remove(from); + + @object[to] = value; + } +} \ No newline at end of file