-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support safe trimmability for System.Text.Json.Nodes.JsonValue #52773
Comments
Tagging subscribers to this area: @eiriktsarpalis, @layomia Issue DetailsBackground and MotivationThe existing public static JsonValue? Create<T>(T? value, JsonNodeOptions? options = null); When called with a primitive such as an Separating the safe vs. unsafe creation is necessary to avoid having to add unsafe trimming attributes to this method. See this issue for more information: #52002 Proposed APInamespace System.Text.Json.Nodes
{
public partial class JsonValue
{
// Here is the safe version that supports JsonTypeInfo with source-generated types:
+ public static JsonValue? Create<T>(T? value, JsonTypeInfo<T> jsonTypeInfo, JsonNodeOptions? options = null)
// Here is the unsafe version with a name that makes that clear:
- public static JsonValue? Create<T>(T? value, JsonNodeOptions? options = null)
+ public static JsonValue? CreateFromSerializableValue<T>(T? value, JsonNodeOptions? options = null)
}
// To maintain compatibility with the removed `Create<T>`, here are safe overloads for each supported primitive value:
+ public static JsonValue? Create(bool value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(byte value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(char value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTime value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTimeOffset value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(decimal value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(double value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Guid value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(short value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(int value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(long value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(bool? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(byte? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(char? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTimeOffset? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTime? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(decimal? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(double? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Guid? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(short? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(int? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(long? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(sbyte? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(float? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Text.Json.JsonElement? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ushort? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(uint? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ulong? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(sbyte value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(float value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(string value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Text.Json.JsonElement value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ushort value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(uint value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ulong value, JsonNodeOptions? options = default(JsonNodeOptions?));
} In addition, operators are added to support namespace System.Text.Json.Nodes
{
public partial class JsonNode
{
+ public static implicit operator JsonNode (System.Text.Json.JsonElement value);
+ public static implicit operator JsonNode? (System.Text.Json.JsonElement? value);
+ public static explicit operator System.Text.Json.JsonElement (JsonNode value);
+ public static explicit operator System.Text.Json.JsonElement? (JsonNode? value);
}
} Alternative DesignsOnly supporting primitive types and not custom data types, anonymous types, etc would prevent the need for
These may include invoking the non-trimmable serializer APIs and thus doesn't really help from a safe trimability perspective.
|
Tagging subscribers to 'linkable-framework': @eerhardt, @vitek-karas, @LakshanF, @sbomer Issue DetailsBackground and MotivationThe existing public static JsonValue? Create<T>(T? value, JsonNodeOptions? options = null); When called with a primitive such as an Separating the safe vs. unsafe creation is necessary to avoid having to add unsafe trimming attributes to this method. See this issue for more information: #52002 Proposed APInamespace System.Text.Json.Nodes
{
public partial class JsonValue
{
// Here is the safe version that supports JsonTypeInfo with source-generated types:
+ public static JsonValue? Create<T>(T? value, JsonTypeInfo<T> jsonTypeInfo, JsonNodeOptions? options = null)
// Here is the unsafe version with a name that makes that clear:
- public static JsonValue? Create<T>(T? value, JsonNodeOptions? options = null)
+ public static JsonValue? CreateFromSerializableValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)]T>(T? value, JsonNodeOptions? options = null)
}
// To maintain compatibility with the removed `Create<T>`, here are safe overloads for each supported primitive value:
+ public static JsonValue? Create(bool value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(byte value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(char value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTime value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTimeOffset value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(decimal value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(double value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Guid value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(short value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(int value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(long value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(bool? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(byte? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(char? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTimeOffset? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTime? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(decimal? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(double? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Guid? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(short? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(int? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(long? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(sbyte? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(float? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Text.Json.JsonElement? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ushort? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(uint? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ulong? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(sbyte value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(float value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(string value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Text.Json.JsonElement value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ushort value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(uint value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ulong value, JsonNodeOptions? options = default(JsonNodeOptions?));
} In addition, operators are added to support namespace System.Text.Json.Nodes
{
public partial class JsonNode
{
+ public static implicit operator JsonNode (System.Text.Json.JsonElement value);
+ public static implicit operator JsonNode? (System.Text.Json.JsonElement? value);
+ public static explicit operator System.Text.Json.JsonElement (JsonNode value);
+ public static explicit operator System.Text.Json.JsonElement? (JsonNode? value);
}
} Alternative DesignsOnly supporting primitive types and not custom data types, anonymous types, etc would prevent the need for
These may include invoking the non-trimmable serializer APIs and thus doesn't really help from a safe trimability perspective.
|
We didn't feel it was worth renaming the linker-unfriendly version. So now it's just adding the specialized versions. We discussed the operators, and had some mixed feelings. Since they're not quite related to the rest of the changes we removed them from here (they can be brought up later as a separate issue). namespace System.Text.Json.Nodes
{
public partial class JsonValue
{
+ public static JsonValue? Create<T>(T? value, JsonTypeInfo<T> jsonTypeInfo, JsonNodeOptions? options = null)
- public static JsonValue? Create<T>(T? value, JsonNodeOptions? options = null)
+ public static JsonValue? Create<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)]T>(T? value, JsonNodeOptions? options = null)
+ public static JsonValue Create(bool value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(byte value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(char value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(System.DateTime value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(System.DateTimeOffset value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(decimal value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(double value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(System.Guid value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(short value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(int value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(long value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(bool? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(byte? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(char? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTimeOffset? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.DateTime? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(decimal? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(double? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Guid? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(short? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(int? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(long? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(sbyte? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(float? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Text.Json.JsonElement? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ushort? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(uint? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue? Create(ulong? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue Create(sbyte value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue Create(float value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(string? value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ public static JsonValue? Create(System.Text.Json.JsonElement value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue Create(ushort value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue Create(uint value, JsonNodeOptions? options = default(JsonNodeOptions?));
+ [System.CLSCompliantAttribute(false)]
+ public static JsonValue Create(ulong value, JsonNodeOptions? options = default(JsonNodeOptions?));
} It also looks like |
Background and Motivation
The existing
JsonValue
class has a factory method like:When called with a primitive such as an
Int32
orstring
this method is safe for trimming. However, this method also supports any serializable CLR type including custom data types, anonymous types and even POCOs and collections, so it is unsafe for trimming since it needs to call the serializer.Separating the safe vs. unsafe creation is necessary to avoid having to add unsafe trimming attributes to this method.
See this issue for more information: #52002
Proposed API
In addition, operators are added to support
JsonElement
which is the only supported type that did not have operators yet:Note that
JsonElement
is handled specially: an internal value ofJsonValueKind.Null
is treated as anull
JsonValue
. This is required sinceJsonValue
is based onJsonElement
after aParse()
and treatsnull
JSON values as anull
CLR value.Alternative Designs
Only supporting primitive types and not custom data types, anonymous types, etc would prevent the need for
CreateFromSerializableValue()
but we would still likely want the various newCreate()
overloads for each supported value type to make the expected types known at compile-time (instead of throwing at run-time). If we did not support custom data types, etc then users would need to:These may include invoking the non-trimmable serializer APIs and thus doesn't really help from a safe trimability perspective.
The text was updated successfully, but these errors were encountered: