Skip to content

Commit

Permalink
Added field support to JSON serializer (#36986)
Browse files Browse the repository at this point in the history
* Added field support to JSON serializer

* Addressed issues

* Added tests

* Addressed issues
  • Loading branch information
YohDeadfall authored Jul 14, 2020
1 parent afdd38c commit 8892364
Show file tree
Hide file tree
Showing 29 changed files with 1,621 additions and 232 deletions.
12 changes: 7 additions & 5 deletions src/libraries/System.Text.Json/ref/System.Text.Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ public JsonSerializerOptions(System.Text.Json.JsonSerializerDefaults defaults) {
public System.Text.Encodings.Web.JavaScriptEncoder? Encoder { get { throw null; } set { } }
public bool IgnoreNullValues { get { throw null; } set { } }
public bool IgnoreReadOnlyProperties { get { throw null; } set { } }
public bool IgnoreReadOnlyFields { get { throw null; } set { } }
public bool IncludeFields { get { throw null; } set { } }
public int MaxDepth { get { throw null; } set { } }
public bool PropertyNameCaseInsensitive { get { throw null; } set { } }
public System.Text.Json.JsonNamingPolicy? PropertyNamingPolicy { get { throw null; } set { } }
Expand Down Expand Up @@ -502,7 +504,7 @@ public abstract partial class JsonConverter
internal JsonConverter() { }
public abstract bool CanConvert(System.Type typeToConvert);
}
[System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Enum | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple=false)]
[System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple=false)]
public partial class JsonConverterAttribute : System.Text.Json.Serialization.JsonAttribute
{
protected JsonConverterAttribute() { }
Expand Down Expand Up @@ -535,23 +537,23 @@ public sealed partial class JsonConstructorAttribute : System.Text.Json.Serializ
{
public JsonConstructorAttribute() { }
}
[System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false)]
[System.AttributeUsageAttribute(System.AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple=false)]
public sealed partial class JsonExtensionDataAttribute : System.Text.Json.Serialization.JsonAttribute
{
public JsonExtensionDataAttribute() { }
}
[System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false)]
[System.AttributeUsageAttribute(System.AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple=false)]
public sealed partial class JsonIgnoreAttribute : System.Text.Json.Serialization.JsonAttribute
{
public JsonIgnoreAttribute() { }
public System.Text.Json.Serialization.JsonIgnoreCondition Condition { get { throw null; } set { } }
}
[System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple = false)]
[System.AttributeUsageAttribute(System.AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple = false)]
public sealed partial class JsonIncludeAttribute : System.Text.Json.Serialization.JsonAttribute
{
public JsonIncludeAttribute() { }
}
[System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false)]
[System.AttributeUsageAttribute(System.AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple=false)]
public sealed partial class JsonPropertyNameAttribute : System.Text.Json.Serialization.JsonAttribute
{
public JsonPropertyNameAttribute(string name) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
namespace System.Text.Json.Serialization
{
/// <summary>
/// When placed on a property or type, specifies the converter type to use.
/// When placed on a property, field, or type, specifies the converter type to use.
/// </summary>
/// <remarks>
/// The specified converter type must derive from <see cref="JsonConverter"/>.
/// When placed on a property, the specified converter will always be used.
/// When placed on a property or field, the specified converter will always be used.
/// When placed on a type, the specified converter will be used unless a compatible converter is added to
/// <see cref="JsonSerializerOptions.Converters"/> or there is another <see cref="JsonConverterAttribute"/> on a property
/// <see cref="JsonSerializerOptions.Converters"/> or there is another <see cref="JsonConverterAttribute"/> on a member
/// of the same type.
/// </remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple = false)]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class JsonConverterAttribute : JsonAttribute
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
namespace System.Text.Json.Serialization
{
/// <summary>
/// When placed on a property of type <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>, any
/// properties that do not have a matching member are added to that Dictionary during deserialization and written during serialization.
/// When placed on a property or field of type <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>, any
/// properties that do not have a matching property or field are added to that Dictionary during deserialization and written during serialization.
/// </summary>
/// <remarks>
/// The TKey value must be <see cref="string"/> and TValue must be <see cref="JsonElement"/> or <see cref="object"/>.
///
/// During deserializing, when using <see cref="object"/> a "null" JSON value is treated as a <c>null</c> object reference, and when using
/// <see cref="JsonElement"/> a "null" is treated as a JsonElement with <see cref="JsonElement.ValueKind"/> set to <see cref="JsonValueKind.Null"/>.
///
/// During serializing, the name of the extension data property is not included in the JSON;
/// During serializing, the name of the extension data member is not included in the JSON;
/// the data contained within the extension data is serialized as properties of the JSON object.
///
/// If there is more than one extension property on a type, or it the property is not of the correct type,
/// If there is more than one extension member on a type, or it the member is not of the correct type,
/// an <see cref="InvalidOperationException"/> is thrown during the first serialization or deserialization of that type.
/// </remarks>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public sealed class JsonExtensionDataAttribute : JsonAttribute
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
namespace System.Text.Json.Serialization
{
/// <summary>
/// Prevents a property from being serialized or deserialized.
/// Prevents a property or field from being serialized or deserialized.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public sealed class JsonIgnoreAttribute : JsonAttribute
{
/// <summary>
/// Specifies the condition that must be met before a property will be ignored.
/// Specifies the condition that must be met before a property or field will be ignored.
/// </summary>
/// <remarks>The default value is <see cref="JsonIgnoreCondition.Always"/>.</remarks>
public JsonIgnoreCondition Condition { get; set; } = JsonIgnoreCondition.Always;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace System.Text.Json.Serialization
/// <remarks>
/// When applied to a property, indicates that non-public getters and setters can be used for serialization and deserialization.
/// </remarks>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
[AttributeUsage(AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple = false)]
public sealed class JsonIncludeAttribute : JsonAttribute
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace System.Text.Json.Serialization
/// Specifies the property name that is present in the JSON when serializing and deserializing.
/// This overrides any naming policy specified by <see cref="JsonNamingPolicy"/>.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public sealed class JsonPropertyNameAttribute : JsonAttribute
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,26 @@ internal sealed partial class JsonClassInfo
// Use an array (instead of List<T>) for highest performance.
private volatile PropertyRef[]? _propertyRefsSorted;

public static JsonPropertyInfo AddProperty(PropertyInfo propertyInfo, Type parentClassType, JsonSerializerOptions options)
public static JsonPropertyInfo AddProperty(MemberInfo memberInfo, Type memberType, Type parentClassType, JsonSerializerOptions options)
{
JsonIgnoreCondition? ignoreCondition = JsonPropertyInfo.GetAttribute<JsonIgnoreAttribute>(propertyInfo)?.Condition;
JsonIgnoreCondition? ignoreCondition = JsonPropertyInfo.GetAttribute<JsonIgnoreAttribute>(memberInfo)?.Condition;

if (ignoreCondition == JsonIgnoreCondition.Always)
{
return JsonPropertyInfo.CreateIgnoredPropertyPlaceholder(propertyInfo, options);
return JsonPropertyInfo.CreateIgnoredPropertyPlaceholder(memberInfo, options);
}

Type propertyType = propertyInfo.PropertyType;

JsonConverter converter = GetConverter(
propertyType,
memberType,
parentClassType,
propertyInfo,
memberInfo,
out Type runtimeType,
options);

return CreateProperty(
declaredPropertyType: propertyType,
declaredPropertyType: memberType,
runtimePropertyType: runtimeType,
propertyInfo,
memberInfo,
parentClassType,
converter,
options,
Expand All @@ -83,7 +81,7 @@ public static JsonPropertyInfo AddProperty(PropertyInfo propertyInfo, Type paren
internal static JsonPropertyInfo CreateProperty(
Type declaredPropertyType,
Type? runtimePropertyType,
PropertyInfo? propertyInfo,
MemberInfo? memberInfo,
Type parentClassType,
JsonConverter converter,
JsonSerializerOptions options,
Expand All @@ -97,7 +95,7 @@ internal static JsonPropertyInfo CreateProperty(
declaredPropertyType,
runtimePropertyType,
runtimeClassType: converter.ClassType,
propertyInfo,
memberInfo,
converter,
ignoreCondition,
options);
Expand All @@ -118,7 +116,7 @@ internal static JsonPropertyInfo CreatePropertyInfoForClassInfo(
JsonPropertyInfo jsonPropertyInfo = CreateProperty(
declaredPropertyType: declaredPropertyType,
runtimePropertyType: runtimePropertyType,
propertyInfo: null, // Not a real property so this is null.
memberInfo: null, // Not a real property so this is null.
parentClassType: JsonClassInfo.ObjectType, // a dummy value (not used)
converter: converter,
options);
Expand Down
Loading

0 comments on commit 8892364

Please sign in to comment.