diff --git a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/DTOs/Customer.cs b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/DTOs/Customer.cs new file mode 100644 index 0000000000..8cd7e8820a --- /dev/null +++ b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/DTOs/Customer.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; + +namespace RetrieveJSONProperty.DTOs; + +public class Customer +{ + [JsonPropertyName("FirstName")] + public string? Name { get; set; } + + [JsonIgnore] + public string? Password { get; set; } + + public int Age { get; set; } +} diff --git a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Helper/JsonHelper.cs b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Helper/JsonHelper.cs index 0a7ac85cc6..037bc6ed95 100644 --- a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Helper/JsonHelper.cs +++ b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Helper/JsonHelper.cs @@ -22,7 +22,7 @@ public static IEnumerable RetrievalUsingSerialization(object obj) { string json = JsonConvert.SerializeObject(obj); - var values = JsonConvert.DeserializeObject>(json); + var values = JsonConvert.DeserializeObject>(json); return values != null ? values.Keys diff --git a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Helper/JsonTextImplementation.cs b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Helper/JsonTextImplementation.cs index d13ed00cee..31c5f6048d 100644 --- a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Helper/JsonTextImplementation.cs +++ b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Helper/JsonTextImplementation.cs @@ -1,4 +1,6 @@ using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; using System.Text.Json.Serialization; namespace RetrieveJSONProperty.Helper; @@ -16,4 +18,17 @@ public static string[] GetJsonPropertyNames(object obj) return propertyNames; } -} \ No newline at end of file + + public static string[] GetSerializedPropertyNames(JsonSerializerOptions? options = null) + { + options ??= JsonSerializerOptions.Default; + options.MakeReadOnly(populateMissingResolver: true); + + JsonTypeInfo typeInfo = options.GetTypeInfo(typeof(T)); + + return typeInfo.Properties + .Where(property => property.Get is not null || property.Set is not null) + .Select(property => property.Name) + .ToArray(); + } +} diff --git a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Program.cs b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Program.cs index cd5d4bb409..14ef0d317c 100644 --- a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Program.cs +++ b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/Program.cs @@ -11,6 +11,7 @@ Console.WriteLine("2. ListPropertywithValue"); Console.WriteLine("3. ResolverImplementation"); Console.WriteLine("4. AlternateImplementation();"); + Console.WriteLine("5. SerializerMetadataImplementation"); string? option = Console.ReadLine(); @@ -32,6 +33,10 @@ AlternateImplementation(); break; + case "5": + SerializerMetadataImplementation(); + break; + case "exit": continueExecution = false; break; @@ -92,6 +97,17 @@ static void AlternateImplementation() } } +static void SerializerMetadataImplementation() +{ + var propertyNames = JsonTextImplementation.GetSerializedPropertyNames(); + + Console.WriteLine("JSON property names:"); + foreach (var propertyName in propertyNames) + { + Console.WriteLine(propertyName); + } +} + static Sales CreateSalesObject() { Console.WriteLine("Enter YearlySales:"); diff --git a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/RetrieveJSONProperty.csproj b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/RetrieveJSONProperty.csproj index c17e0d2275..9ddf40bd52 100644 --- a/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/RetrieveJSONProperty.csproj +++ b/json-csharp/RetrieveJSONProperty/RetrieveJSONProperty/RetrieveJSONProperty.csproj @@ -2,13 +2,13 @@ Exe - net7.0 + net10.0 enable enable - + diff --git a/json-csharp/RetrieveJSONProperty/Tests/RetrieveJSONPropertyUnitTest.cs b/json-csharp/RetrieveJSONProperty/Tests/RetrieveJSONPropertyUnitTest.cs index c100449fbb..28d36ad28e 100644 --- a/json-csharp/RetrieveJSONProperty/Tests/RetrieveJSONPropertyUnitTest.cs +++ b/json-csharp/RetrieveJSONProperty/Tests/RetrieveJSONPropertyUnitTest.cs @@ -1,3 +1,5 @@ +using System.Text.Json; + namespace Tests; [TestFixture] @@ -17,7 +19,7 @@ public void GivenObjectWithJsonPropertyAttribute_WhenRetrievalUsingReflection_Th var result = JsonHelper.RetrievalUsingReflection(sales); // Assert - CollectionAssert.AreEquivalent(new[] { "Slx_PER_Year", "Slx_PER_DAY" }, result); + Assert.That(result, Is.EquivalentTo(new[] { "Slx_PER_Year", "Slx_PER_DAY" })); } [Test] @@ -34,7 +36,20 @@ public void GivenSalesObject_WhenRetrievingKeyValuesUsingSerialization_ThenRetur var result = JsonHelper.RetrievalUsingSerialization(sales); // Assert - CollectionAssert.AreEqual(new[] { "Slx_PER_Year", "Slx_PER_DAY" }, result); + Assert.That(result, Is.EqualTo(new[] { "Slx_PER_Year", "Slx_PER_DAY" })); + } + + [Test] + public void GivenObjectWithNonStringProperty_WhenRetrievingUsingSerialization_ThenReturnsAllNames() + { + // Arrange + var testObject = new NewtonsoftObjectWithNumber { Name = "Widget", Quantity = 3 }; + + // Act + var result = JsonHelper.RetrievalUsingSerialization(testObject); + + // Assert + Assert.That(result, Is.EqualTo(new[] { "product_name", "Quantity" })); } [Test] @@ -51,6 +66,83 @@ public void Given_ObjectWithJsonPropertyAttributes_WhenGetJsonPropertyNames_Then Assert.That(result, Is.EqualTo(expected)); } + [Test] + public void GivenSalesType_WhenGetSerializedPropertyNames_ThenReturnJsonPropertyNames() + { + // Act + string[] result = JsonTextImplementation.GetSerializedPropertyNames(); + + // Assert + Assert.That(result, Is.EqualTo(new[] { "Slx_PER_Year", "Slx_PER_DAY" })); + } + + [Test] + public void GivenWebDefaults_WhenGetSerializedPropertyNames_ThenNamingPolicyAppliesOnlyWithoutAttribute() + { + // Arrange + var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); + + // Act + string[] result = JsonTextImplementation.GetSerializedPropertyNames(options); + + // Assert + Assert.That(result, Is.EqualTo(new[] { "FirstName", "LastName", "age" })); + } + + [Test] + public void GivenWebDefaults_WhenSerializing_ThenOutputUsesSameNamesAsGetSerializedPropertyNames() + { + // Arrange + var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); + var testObject = new TestObjectWithAttributes { Name = "Ana", Surname = "Lee", Age = 30 }; + + // Act + string json = System.Text.Json.JsonSerializer.Serialize(testObject, options); + string[] namesInJson = JsonDocument.Parse(json).RootElement + .EnumerateObject() + .Select(property => property.Name) + .ToArray(); + + // Assert + Assert.That(namesInJson, + Is.EqualTo(JsonTextImplementation.GetSerializedPropertyNames(options))); + } + + [Test] + public void GivenIgnoredProperty_WhenGetSerializedPropertyNames_ThenSkipsIt() + { + // Act + string[] result = JsonTextImplementation.GetSerializedPropertyNames(); + + // Assert + Assert.That(result, Is.EqualTo(new[] { "id" })); + } + + [Test] + public void GivenIgnoredProperty_WhenGetJsonPropertyNames_ThenReflectionStillReturnsIt() + { + // Act + string[] result = JsonTextImplementation.GetJsonPropertyNames(new ObjectWithIgnoredProperty()); + + // Assert + Assert.That(result, Is.EqualTo(new[] { "id", "Password" })); + } + + [Test] + public void GivenCustomer_WhenComparingReflectionWithWebDefaultsMetadata_ThenOnlyMetadataAppliesPolicyAndIgnore() + { + // Arrange + var webOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web); + + // Act + string[] fromReflection = JsonTextImplementation.GetJsonPropertyNames(new Customer()); + string[] fromSerializer = JsonTextImplementation.GetSerializedPropertyNames(webOptions); + + // Assert + Assert.That(fromReflection, Is.EqualTo(new[] { "FirstName", "Password", "Age" })); + Assert.That(fromSerializer, Is.EqualTo(new[] { "FirstName", "age" })); + } + [Test] public void GivenValidProductObject_WhenGettingJsonPropertyForProductName_ThenReturnCorrectProperty() { @@ -65,10 +157,9 @@ public void GivenValidProductObject_WhenGettingJsonPropertyForProductName_ThenRe var property = ResolverHelper.GetJsonProperty(sales, "Slx_per_day"); // Assert - Assert.IsNotNull(property); + Assert.That(property, Is.Not.Null); Assert.That(property.PropertyName, Is.EqualTo("Slx_PER_DAY")); Assert.That(property.PropertyType, Is.EqualTo(typeof(string))); - } private class TestObjectWithAttributes @@ -81,4 +172,21 @@ private class TestObjectWithAttributes public int Age { get; set; } } + + private class NewtonsoftObjectWithNumber + { + [JsonProperty("product_name")] + public string? Name { get; set; } + + public int Quantity { get; set; } + } + + private class ObjectWithIgnoredProperty + { + [JsonPropertyName("id")] + public int Id { get; set; } + + [System.Text.Json.Serialization.JsonIgnore] + public string? Password { get; set; } + } } diff --git a/json-csharp/RetrieveJSONProperty/Tests/Tests.csproj b/json-csharp/RetrieveJSONProperty/Tests/Tests.csproj index 23cafc2805..d3f95d58b0 100644 --- a/json-csharp/RetrieveJSONProperty/Tests/Tests.csproj +++ b/json-csharp/RetrieveJSONProperty/Tests/Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net10.0 enable enable @@ -10,12 +10,12 @@ - - - - - - + + + + + +