From fa75f622862fb9ba76ebbf687969d453c1774ce5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 7 Dec 2025 02:53:02 +0000
Subject: [PATCH 1/8] Initial plan
From ed028caca986d178a8b9e0072901acb4158e3744 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 7 Dec 2025 02:58:28 +0000
Subject: [PATCH 2/8] Fix SerializedMember JSON schema to accept any value type
- Remove type constraint from 'value' property in SerializedMemberConverter.Schema
- Add comprehensive tests in SerializedMemberSchemaTests
- All 584 existing tests still pass
Co-authored-by: IvanMurzak <9135028+IvanMurzak@users.noreply.github.com>
---
.../SerializedMemberSchemaTests.cs | 212 ++++++++++++++++++
.../Json/SerializedMemberConverter.cs | 1 -
2 files changed, 212 insertions(+), 1 deletion(-)
create mode 100644 ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
diff --git a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
new file mode 100644
index 00000000..18883cb0
--- /dev/null
+++ b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using com.IvanMurzak.ReflectorNet.Model;
+using com.IvanMurzak.ReflectorNet.Utils;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace com.IvanMurzak.ReflectorNet.Tests.SchemaTests
+{
+ ///
+ /// Tests to validate that SerializedMember JSON schema correctly represents
+ /// the actual serialized JSON for various value types.
+ ///
+ public class SerializedMemberSchemaTests : BaseTest
+ {
+ public SerializedMemberSchemaTests(ITestOutputHelper output) : base(output) { }
+
+ [Fact]
+ public void SerializedMember_Schema_Value_Should_Accept_Any_JsonType()
+ {
+ // Arrange
+ var reflector = new Reflector();
+ var schema = reflector.GetSchema();
+
+ // Assert - Check that schema was generated
+ Assert.NotNull(schema);
+
+ // Get the value property schema
+ var schemaObj = schema.AsObject();
+ Assert.True(schemaObj.TryGetPropertyValue(JsonSchema.Properties, out var propertiesNode));
+ var properties = propertiesNode!.AsObject();
+ Assert.True(properties.TryGetPropertyValue(SerializedMember.ValueName, out var valueSchemaNode));
+ var valueSchema = valueSchemaNode!.AsObject();
+
+ // The value schema should NOT have a "type" constraint
+ // This allows it to accept any JSON value type
+ Assert.False(valueSchema.TryGetPropertyValue(JsonSchema.Type, out _),
+ "The 'value' property schema should not have a 'type' constraint to allow any JSON value type");
+
+ // It should have a description
+ Assert.True(valueSchema.TryGetPropertyValue(JsonSchema.Description, out var descriptionNode));
+ Assert.NotNull(descriptionNode);
+
+ _output.WriteLine($"✓ SerializedMember schema allows 'value' to be any JSON type");
+ _output.WriteLine($"Schema:\n{schema.ToJsonString(new JsonSerializerOptions { WriteIndented = true })}");
+ }
+
+ [Theory]
+ [InlineData("test string", "string")]
+ [InlineData(42, "number")]
+ [InlineData(3.14, "number")]
+ [InlineData(true, "boolean")]
+ [InlineData(false, "boolean")]
+ public void SerializedMember_Should_Serialize_PrimitiveTypes_Correctly(object value, string expectedJsonType)
+ {
+ // Arrange
+ var reflector = new Reflector();
+
+ // Act
+ var serialized = reflector.Serialize(value, name: "testValue");
+ var json = serialized.ToJson(reflector);
+
+ // Parse and validate JSON structure
+ var jsonNode = JsonNode.Parse(json);
+ Assert.NotNull(jsonNode);
+
+ var jsonObj = jsonNode!.AsObject();
+ Assert.True(jsonObj.TryGetPropertyValue(SerializedMember.ValueName, out var valueNode));
+ Assert.NotNull(valueNode);
+
+ // Validate the value type matches expected
+ var actualJsonType = GetJsonValueType(valueNode);
+ _output.WriteLine($"Value: {value}, Expected type: {expectedJsonType}, Actual type: {actualJsonType}");
+ _output.WriteLine($"Serialized JSON: {json}");
+
+ Assert.Equal(expectedJsonType, actualJsonType);
+ }
+
+ [Fact]
+ public void SerializedMember_Should_Serialize_Null_Correctly()
+ {
+ // Arrange
+ var reflector = new Reflector();
+
+ // Act
+ var serialized = reflector.Serialize(null, typeof(string), name: "testValue");
+ var json = serialized.ToJson(reflector);
+
+ // Parse and validate JSON structure
+ var jsonNode = JsonNode.Parse(json);
+ Assert.NotNull(jsonNode);
+
+ var jsonObj = jsonNode!.AsObject();
+
+ // For null values, the value property should be absent or null
+ if (jsonObj.TryGetPropertyValue(SerializedMember.ValueName, out var valueNode))
+ {
+ Assert.Null(valueNode);
+ }
+
+ _output.WriteLine($"Serialized null value JSON: {json}");
+ }
+
+ [Fact]
+ public void SerializedMember_Should_Serialize_Array_Correctly()
+ {
+ // Arrange
+ var reflector = new Reflector();
+ var array = new[] { 1, 2, 3 };
+
+ // Act
+ var serialized = reflector.Serialize(array, name: "testArray");
+ var json = serialized.ToJson(reflector);
+
+ // Parse and validate JSON structure
+ var jsonNode = JsonNode.Parse(json);
+ Assert.NotNull(jsonNode);
+
+ var jsonObj = jsonNode!.AsObject();
+ Assert.True(jsonObj.TryGetPropertyValue(SerializedMember.ValueName, out var valueNode));
+ Assert.NotNull(valueNode);
+
+ // The value should be a JSON array
+ Assert.IsType(valueNode);
+
+ _output.WriteLine($"Serialized array JSON: {json}");
+ }
+
+ [Fact]
+ public void SerializedMember_Should_Serialize_Object_Correctly()
+ {
+ // Arrange
+ var reflector = new Reflector();
+ var obj = new TestClass { Name = "Test", Value = 123 };
+
+ // Act
+ var serialized = reflector.Serialize(obj, name: "testObject");
+ var json = serialized.ToJson(reflector);
+
+ // Parse and validate JSON structure
+ var jsonNode = JsonNode.Parse(json);
+ Assert.NotNull(jsonNode);
+
+ var jsonObj = jsonNode!.AsObject();
+ Assert.True(jsonObj.TryGetPropertyValue(SerializedMember.ValueName, out var valueNode));
+ Assert.NotNull(valueNode);
+
+ // For complex objects, the value is typically an empty object {}
+ // and the actual data is in props/fields
+ Assert.IsType(valueNode);
+
+ _output.WriteLine($"Serialized object JSON: {json}");
+ }
+
+ [Fact]
+ public void SerializedMember_RoundTrip_Should_Preserve_AllValueTypes()
+ {
+ // Arrange
+ var reflector = new Reflector();
+ var testValues = new object[]
+ {
+ "string value",
+ 42,
+ 3.14159,
+ true,
+ false
+ };
+
+ foreach (var originalValue in testValues)
+ {
+ // Act
+ var serialized = reflector.Serialize(originalValue, name: "test");
+ var deserialized = reflector.Deserialize(serialized);
+
+ // Assert
+ var originalJson = originalValue.ToJson(reflector);
+ var deserializedJson = deserialized.ToJson(reflector);
+
+ _output.WriteLine($"Original: {originalValue} ({originalValue.GetType().Name})");
+ _output.WriteLine($"Original JSON: {originalJson}");
+ _output.WriteLine($"Deserialized JSON: {deserializedJson}");
+
+ Assert.Equal(originalJson, deserializedJson);
+ }
+ }
+
+ ///
+ /// Helper method to determine the JSON value type from a JsonNode
+ ///
+ private string GetJsonValueType(JsonNode node)
+ {
+ return node switch
+ {
+ JsonObject => "object",
+ JsonArray => "array",
+ JsonValue value when value.TryGetValue(out _) => "string",
+ JsonValue value when value.TryGetValue(out _) => "boolean",
+ JsonValue value when value.TryGetValue(out _) || value.TryGetValue(out _) ||
+ value.TryGetValue(out _) || value.TryGetValue(out _) => "number",
+ _ => "unknown"
+ };
+ }
+
+ private class TestClass
+ {
+ public string Name { get; set; } = string.Empty;
+ public int Value { get; set; }
+ }
+ }
+}
diff --git a/ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs b/ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs
index 4f818b8d..501c5beb 100644
--- a/ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs
+++ b/ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs
@@ -40,7 +40,6 @@ public class SerializedMemberConverter : JsonSchemaConverter,
},
[SerializedMember.ValueName] = new JsonObject
{
- [JsonSchema.Type] = JsonSchema.Object,
[JsonSchema.Description] = TypeUtils.GetDescription(
typeof(SerializedMember)
.GetMember(nameof(SerializedMember.valueJsonElement))
From 7f0a91a41b286670bd71a92516e7272ab8f088da Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 7 Dec 2025 03:01:41 +0000
Subject: [PATCH 3/8] Improve numeric type detection in
SerializedMemberSchemaTests
- Extract numeric detection logic into separate IsNumericJsonValue method
- Add support for all numeric types (float, byte, short, uint, ulong, ushort, sbyte)
Co-authored-by: IvanMurzak <9135028+IvanMurzak@users.noreply.github.com>
---
.../SerializedMemberSchemaTests.cs | 21 +++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
index 18883cb0..49a75bd2 100644
--- a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
+++ b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
@@ -197,12 +197,29 @@ private string GetJsonValueType(JsonNode node)
JsonArray => "array",
JsonValue value when value.TryGetValue(out _) => "string",
JsonValue value when value.TryGetValue(out _) => "boolean",
- JsonValue value when value.TryGetValue(out _) || value.TryGetValue(out _) ||
- value.TryGetValue(out _) || value.TryGetValue(out _) => "number",
+ JsonValue value when IsNumericJsonValue(value) => "number",
_ => "unknown"
};
}
+ ///
+ /// Helper method to check if a JsonValue represents a numeric type
+ ///
+ private bool IsNumericJsonValue(JsonValue value)
+ {
+ return value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
+ value.TryGetValue(out _);
+ }
+
private class TestClass
{
public string Name { get; set; } = string.Empty;
From 985a7d43e52118cd1a9228baa3c9838b66354d82 Mon Sep 17 00:00:00 2001
From: Ivan Murzak
Date: Sun, 7 Dec 2025 00:04:12 -0800
Subject: [PATCH 4/8] Remove unnecessary value name from SerializedMember JSON
schema requirements
---
ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs b/ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs
index 501c5beb..1365c046 100644
--- a/ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs
+++ b/ReflectorNet/src/Convertor/Json/SerializedMemberConverter.cs
@@ -72,7 +72,7 @@ public class SerializedMemberConverter : JsonSchemaConverter,
.First())
}
},
- [JsonSchema.Required] = new JsonArray { nameof(SerializedMember.typeName), SerializedMember.ValueName },
+ [JsonSchema.Required] = new JsonArray { nameof(SerializedMember.typeName) },
[JsonSchema.AdditionalProperties] = false
};
public static JsonNode SchemaRef => new JsonObject
From 2bc71f99e31207736392c56cea36187f408b8c63 Mon Sep 17 00:00:00 2001
From: Ivan Murzak
Date: Sun, 7 Dec 2025 00:13:22 -0800
Subject: [PATCH 5/8] Enable inclusion of public fields in JSON serialization
---
ReflectorNet/src/Utils/Json/JsonSerializer.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/ReflectorNet/src/Utils/Json/JsonSerializer.cs b/ReflectorNet/src/Utils/Json/JsonSerializer.cs
index 5342d411..611e55a6 100644
--- a/ReflectorNet/src/Utils/Json/JsonSerializer.cs
+++ b/ReflectorNet/src/Utils/Json/JsonSerializer.cs
@@ -80,6 +80,7 @@ public JsonSerializer(Reflector reflector)
// ReferenceHandler = ReferenceHandler.Preserve,
PropertyNamingPolicy = null,
PropertyNameCaseInsensitive = true,
+ IncludeFields = true, // Include public fields in serialization
WriteIndented = true,
TypeInfoResolver = JsonTypeInfoResolver.Combine(
new DefaultJsonTypeInfoResolver()
From 451d60b53b9c1edbbe0c4a10b1202a6c0d9410af Mon Sep 17 00:00:00 2001
From: Ivan Murzak
Date: Sun, 7 Dec 2025 00:21:29 -0800
Subject: [PATCH 6/8] Simplify JSON schema output formatting in
SerializedMemberSchemaTests
---
.../src/SchemaTests/SerializedMemberSchemaTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
index 49a75bd2..6ee961ea 100644
--- a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
+++ b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
@@ -44,7 +44,7 @@ public void SerializedMember_Schema_Value_Should_Accept_Any_JsonType()
Assert.NotNull(descriptionNode);
_output.WriteLine($"✓ SerializedMember schema allows 'value' to be any JSON type");
- _output.WriteLine($"Schema:\n{schema.ToJsonString(new JsonSerializerOptions { WriteIndented = true })}");
+ _output.WriteLine($"Schema:\n{schema.ToJsonString()}");
}
[Theory]
From 672865c0c888bd5e6111b5b4d0afe1904939a4f7 Mon Sep 17 00:00:00 2001
From: Ivan Murzak
Date: Sun, 7 Dec 2025 00:23:01 -0800
Subject: [PATCH 7/8] Refactor SerializedMemberSchemaTests to remove
unnecessary using directives and clean up whitespace
---
.../SerializedMemberSchemaTests.cs | 42 +++++++++----------
1 file changed, 19 insertions(+), 23 deletions(-)
diff --git a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
index 6ee961ea..acc525ff 100644
--- a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
+++ b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
@@ -1,10 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Text.Json;
using System.Text.Json.Nodes;
using com.IvanMurzak.ReflectorNet.Model;
using com.IvanMurzak.ReflectorNet.Utils;
-using Xunit;
using Xunit.Abstractions;
namespace com.IvanMurzak.ReflectorNet.Tests.SchemaTests
@@ -26,7 +22,7 @@ public void SerializedMember_Schema_Value_Should_Accept_Any_JsonType()
// Assert - Check that schema was generated
Assert.NotNull(schema);
-
+
// Get the value property schema
var schemaObj = schema.AsObject();
Assert.True(schemaObj.TryGetPropertyValue(JsonSchema.Properties, out var propertiesNode));
@@ -61,11 +57,11 @@ public void SerializedMember_Should_Serialize_PrimitiveTypes_Correctly(object va
// Act
var serialized = reflector.Serialize(value, name: "testValue");
var json = serialized.ToJson(reflector);
-
+
// Parse and validate JSON structure
var jsonNode = JsonNode.Parse(json);
Assert.NotNull(jsonNode);
-
+
var jsonObj = jsonNode!.AsObject();
Assert.True(jsonObj.TryGetPropertyValue(SerializedMember.ValueName, out var valueNode));
Assert.NotNull(valueNode);
@@ -74,7 +70,7 @@ public void SerializedMember_Should_Serialize_PrimitiveTypes_Correctly(object va
var actualJsonType = GetJsonValueType(valueNode);
_output.WriteLine($"Value: {value}, Expected type: {expectedJsonType}, Actual type: {actualJsonType}");
_output.WriteLine($"Serialized JSON: {json}");
-
+
Assert.Equal(expectedJsonType, actualJsonType);
}
@@ -87,19 +83,19 @@ public void SerializedMember_Should_Serialize_Null_Correctly()
// Act
var serialized = reflector.Serialize(null, typeof(string), name: "testValue");
var json = serialized.ToJson(reflector);
-
+
// Parse and validate JSON structure
var jsonNode = JsonNode.Parse(json);
Assert.NotNull(jsonNode);
-
+
var jsonObj = jsonNode!.AsObject();
-
+
// For null values, the value property should be absent or null
if (jsonObj.TryGetPropertyValue(SerializedMember.ValueName, out var valueNode))
{
Assert.Null(valueNode);
}
-
+
_output.WriteLine($"Serialized null value JSON: {json}");
}
@@ -113,18 +109,18 @@ public void SerializedMember_Should_Serialize_Array_Correctly()
// Act
var serialized = reflector.Serialize(array, name: "testArray");
var json = serialized.ToJson(reflector);
-
+
// Parse and validate JSON structure
var jsonNode = JsonNode.Parse(json);
Assert.NotNull(jsonNode);
-
+
var jsonObj = jsonNode!.AsObject();
Assert.True(jsonObj.TryGetPropertyValue(SerializedMember.ValueName, out var valueNode));
Assert.NotNull(valueNode);
// The value should be a JSON array
Assert.IsType(valueNode);
-
+
_output.WriteLine($"Serialized array JSON: {json}");
}
@@ -138,11 +134,11 @@ public void SerializedMember_Should_Serialize_Object_Correctly()
// Act
var serialized = reflector.Serialize(obj, name: "testObject");
var json = serialized.ToJson(reflector);
-
+
// Parse and validate JSON structure
var jsonNode = JsonNode.Parse(json);
Assert.NotNull(jsonNode);
-
+
var jsonObj = jsonNode!.AsObject();
Assert.True(jsonObj.TryGetPropertyValue(SerializedMember.ValueName, out var valueNode));
Assert.NotNull(valueNode);
@@ -150,7 +146,7 @@ public void SerializedMember_Should_Serialize_Object_Correctly()
// For complex objects, the value is typically an empty object {}
// and the actual data is in props/fields
Assert.IsType(valueNode);
-
+
_output.WriteLine($"Serialized object JSON: {json}");
}
@@ -177,11 +173,11 @@ public void SerializedMember_RoundTrip_Should_Preserve_AllValueTypes()
// Assert
var originalJson = originalValue.ToJson(reflector);
var deserializedJson = deserialized.ToJson(reflector);
-
+
_output.WriteLine($"Original: {originalValue} ({originalValue.GetType().Name})");
_output.WriteLine($"Original JSON: {originalJson}");
_output.WriteLine($"Deserialized JSON: {deserializedJson}");
-
+
Assert.Equal(originalJson, deserializedJson);
}
}
@@ -207,10 +203,10 @@ JsonValue value when IsNumericJsonValue(value) => "number",
///
private bool IsNumericJsonValue(JsonValue value)
{
- return value.TryGetValue(out _) ||
- value.TryGetValue(out _) ||
+ return value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
value.TryGetValue(out _) ||
- value.TryGetValue(out _) ||
+ value.TryGetValue(out _) ||
value.TryGetValue(out _) ||
value.TryGetValue(out _) ||
value.TryGetValue(out _) ||
From 94f422a6c7dd84fd8f100eff0a99e49a861f163b Mon Sep 17 00:00:00 2001
From: Ivan Murzak
Date: Sun, 7 Dec 2025 00:28:02 -0800
Subject: [PATCH 8/8] Fix JSON value type detection order in GetJsonValueType
method
---
.../src/SchemaTests/SerializedMemberSchemaTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
index acc525ff..5b60a1fc 100644
--- a/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
+++ b/ReflectorNet.Tests/src/SchemaTests/SerializedMemberSchemaTests.cs
@@ -191,9 +191,9 @@ private string GetJsonValueType(JsonNode node)
{
JsonObject => "object",
JsonArray => "array",
- JsonValue value when value.TryGetValue(out _) => "string",
JsonValue value when value.TryGetValue(out _) => "boolean",
JsonValue value when IsNumericJsonValue(value) => "number",
+ JsonValue value when value.TryGetValue(out _) => "string",
_ => "unknown"
};
}