Skip to content

Commit 91bdc9e

Browse files
authored
Make parameter matching for custom properties map property Name with parameter (#16)
1 parent 01119a8 commit 91bdc9e

File tree

4 files changed

+73
-6
lines changed

4 files changed

+73
-6
lines changed

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ public JsonPropertyInfo CreateJsonPropertyInfo(Type propertyType, string name)
461461

462462
internal void CacheMember(JsonPropertyInfo jsonPropertyInfo, JsonPropertyDictionary<JsonPropertyInfo>? propertyCache, ref Dictionary<string, JsonPropertyInfo>? ignoredMembers)
463463
{
464-
string memberName = jsonPropertyInfo.ClrName!;
464+
Debug.Assert(jsonPropertyInfo.ClrName != null, "ClrName can be null in custom JsonPropertyInfo instances and should never be passed in this method");
465+
string memberName = jsonPropertyInfo.ClrName;
465466

466467
// The JsonPropertyNameAttribute or naming policy resulted in a collision.
467468
if (!propertyCache!.TryAdd(jsonPropertyInfo.Name, jsonPropertyInfo))
@@ -545,7 +546,7 @@ internal void InitializeConstructorParameters(JsonParameterInfoValues[] jsonPara
545546
foreach (KeyValuePair<string, JsonPropertyInfo?> kvp in PropertyCache.List)
546547
{
547548
JsonPropertyInfo jsonProperty = kvp.Value!;
548-
string propertyName = jsonProperty.ClrName!;
549+
string propertyName = jsonProperty.ClrName ?? jsonProperty.Name;
549550

550551
ParameterLookupKey key = new(propertyName, jsonProperty.PropertyType);
551552
ParameterLookupValue value = new(jsonProperty);
@@ -584,7 +585,8 @@ internal void InitializeConstructorParameters(JsonParameterInfoValues[] jsonPara
584585
else if (DataExtensionProperty != null &&
585586
StringComparer.OrdinalIgnoreCase.Equals(paramToCheck.Name, DataExtensionProperty.Name))
586587
{
587-
ThrowHelper.ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(DataExtensionProperty);
588+
Debug.Assert(DataExtensionProperty.ClrName != null, "Custom property info cannot be data extension property");
589+
ThrowHelper.ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(DataExtensionProperty.ClrName, DataExtensionProperty);
588590
}
589591
}
590592

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/SourceGenJsonTypeInfoOfT.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ internal void AddPropertiesUsingSourceGenInfo()
150150
{
151151
if (hasJsonInclude)
152152
{
153-
ThrowHelper.ThrowInvalidOperationException_JsonIncludeOnNonPublicInvalid(jsonPropertyInfo.ClrName!, jsonPropertyInfo.DeclaringType);
153+
Debug.Assert(jsonPropertyInfo.ClrName != null, "ClrName is not set by source gen");
154+
ThrowHelper.ThrowInvalidOperationException_JsonIncludeOnNonPublicInvalid(jsonPropertyInfo.ClrName, jsonPropertyInfo.DeclaringType);
154155
}
155156

156157
continue;

src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ public static void ThrowInvalidOperationException_ConstructorParameterIncomplete
228228
}
229229

230230
[DoesNotReturn]
231-
public static void ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(JsonPropertyInfo jsonPropertyInfo)
231+
public static void ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(string propertyName, JsonPropertyInfo jsonPropertyInfo)
232232
{
233-
throw new InvalidOperationException(SR.Format(SR.ExtensionDataCannotBindToCtorParam, jsonPropertyInfo.ClrName, jsonPropertyInfo.DeclaringType));
233+
throw new InvalidOperationException(SR.Format(SR.ExtensionDataCannotBindToCtorParam, propertyName, jsonPropertyInfo.DeclaringType));
234234
}
235235

236236
[DoesNotReturn]

src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonTypeInfo.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,70 @@ public ClassWithParametrizedConstructorAndWritableProperties(int a, string b)
720720
}
721721
}
722722

723+
[Fact]
724+
public static void SerializingTypeWithCustomNonSerializablePropertyAndJsonConstructorWorksCorrectly()
725+
{
726+
var resolver = new DefaultJsonTypeInfoResolver { Modifiers = { ContractModifier } };
727+
var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
728+
string json = JsonSerializer.Serialize(new PocoWithConstructor("str"), options);
729+
Assert.Equal("{}", json);
730+
731+
static void ContractModifier(JsonTypeInfo jti)
732+
{
733+
if (jti.Type == typeof(PocoWithConstructor))
734+
{
735+
jti.Properties.Add(jti.CreateJsonPropertyInfo(typeof(string), "someOtherName"));
736+
}
737+
}
738+
}
739+
740+
[Fact]
741+
public static void SerializingTypeWithCustomSerializablePropertyAndJsonConstructorWorksCorrectly()
742+
{
743+
var resolver = new DefaultJsonTypeInfoResolver { Modifiers = { ContractModifier } };
744+
var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
745+
string json = JsonSerializer.Serialize(new PocoWithConstructor("str"), options);
746+
Assert.Equal("""{"test":"asd"}""", json);
747+
748+
static void ContractModifier(JsonTypeInfo jti)
749+
{
750+
if (jti.Type == typeof(PocoWithConstructor))
751+
{
752+
JsonPropertyInfo pi = jti.CreateJsonPropertyInfo(typeof(string), "test");
753+
pi.Get = (o) => "asd";
754+
jti.Properties.Add(pi);
755+
}
756+
}
757+
}
758+
759+
[Fact]
760+
public static void SerializingTypeWithCustomPropertyAndJsonConstructorBindsParameter()
761+
{
762+
var resolver = new DefaultJsonTypeInfoResolver { Modifiers = { ContractModifier } };
763+
var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
764+
string json = """{"parameter":"asd"}""";
765+
PocoWithConstructor deserialized = JsonSerializer.Deserialize<PocoWithConstructor>(json, options);
766+
Assert.Equal("asd", deserialized.ParameterValue);
767+
768+
static void ContractModifier(JsonTypeInfo jti)
769+
{
770+
if (jti.Type == typeof(PocoWithConstructor))
771+
{
772+
jti.Properties.Add(jti.CreateJsonPropertyInfo(typeof(string), "parameter"));
773+
}
774+
}
775+
}
776+
777+
private class PocoWithConstructor
778+
{
779+
internal string ParameterValue { get; set; }
780+
781+
public PocoWithConstructor(string parameter)
782+
{
783+
ParameterValue = parameter;
784+
}
785+
}
786+
723787
[Fact]
724788
public static void JsonConstructorAttributeIsOverridenAndPropertiesAreSetWhenCreateObjectIsSet_LargeConstructor()
725789
{

0 commit comments

Comments
 (0)