Skip to content

Conversation

@huoyaoyuan
Copy link
Member

Closes #1235 .

I'm not sure how to test it. The existing tests are focused on data instead of overloads.

Contribution pain: I have never been satisfied by build /t:GenerateReferenceSource these days, for different reasons. For System.Text.Json, the reason is that attribute on generic parameter is not supported.

@Dotnet-GitSync-Bot
Copy link
Collaborator

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@layomia
Copy link
Contributor

layomia commented Sep 13, 2020

Contribution pain: I have never been satisfied by build /t:GenerateReferenceSource these days, for different reasons. For System.Text.Json, the reason is that attribute on generic parameter is not supported.

cc @safern on generic type parameters not being supported by /t:GenerateReferenceSource. Are we tracking this?

Opened #42186 to re-add linker attributes omitted from generic type params on JsonSerializer methods.


@huoyaoyuan what other pain points do you have with /t:GenerateReferenceSource?

@layomia
Copy link
Contributor

layomia commented Sep 13, 2020

I'm not sure how to test it. The existing tests are focused on data instead of overloads.

The way to test it is to add a new DeserializerWrapper, e.g:

private class StringDeserializerWrapper : DeserializationWrapper
{
protected internal override Task<T> DeserializeWrapper<T>(string json, JsonSerializerOptions options = null)
{
return Task.FromResult(JsonSerializer.Deserialize<T>(json, options));
}
protected internal override Task<object> DeserializeWrapper(string json, Type type, JsonSerializerOptions options = null)
{
return Task.FromResult(JsonSerializer.Deserialize(json, type, options));
}
}

Use the new wrapper wherever the existing ones are used.

We also need to add linker trimming tests for the new overloads. See the exisiting ones here. Each overload should map to a new .cs file. To run the tests run the following from the repo's root directory:

build.cmd -s libs.tests -c release /p:TestAssemblies=false /p:TestTrimming=true

Copy link
Contributor

@layomia layomia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. I just have a few comments and a pointer on the tests.

@safern
Copy link
Member

safern commented Sep 14, 2020

cc @safern on generic type parameters not being supported by /t:GenerateReferenceSource. Are we tracking this?

We have an issue for APICompat, since it is assigned to me I will look at GenAPI as well dotnet/arcade#5925

Comment on lines 55 to 56
/// <typeparamref name="TValue"/> is not compatible with the JSON,
/// or when there is remaining data in the Stream.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overload doesn't take a stream. Doc comment needs to be updated.

I recommend using the content from the official msft docs that have gone through content review to seed the new API docs rather than copying from an overload to avoid slight discrepancies.
https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer.deserialize?view=netcore-3.1#System_Text_Json_JsonSerializer_Deserialize__1_System_String_System_Text_Json_JsonSerializerOptions_

https://github.com/dotnet/dotnet-api-docs/blob/80088021b2151fd5af3cda6e759ec5e548c372c0/xml/System.Text.Json/JsonSerializer.xml#L281-L348

Comment on lines 118 to 119
/// the <paramref name="returnType"/> is not compatible with the JSON,
/// or when there is remaining data in the Stream.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@layomia layomia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested doc changes for consistency with what is in https://docs.microsoft.com/dotnet/api/system.text.json.jsonserializer.deserialize?view=netcore-3.1.

Linker trimming tests as described in #41957 (comment) are needed to merge this PR.

{
if (json == null)
{
throw new ArgumentNullException(nameof(json));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't throw ArgumentNullException for a value type. Instead we should let the reader throw a JsonException similar to the behavior for an empty ReadOnlySpan<byte>:

JsonSerializer.Deserialize(default(ReadOnlySpan<byte>), typeof(int));

Unhandled exception. System.Text.Json.JsonException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.

This applies to the other new overload as well. We should add a test for this scenario for both overloads and assert on the content of the exception. The path information should be present in the exception string "$ | LineNumber: 0 | BytePositionInLine: 0".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Comment suggests a special test for default span. Otherwise, default span will be treated same as empty span.
What's the final decision on this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise, default span will be treated same as empty span.

Default and empty spans should be treated the same. Adding a test passing in default span is good to have, but the null check within the source implementation isn't necessary and should be removed.

In the implementation of Deserialize, a default/empty span should be allowed to be passed to the Utf8JsonReader, and it will validate that empty JSON is invalid and throw JsonException. That is the desired behavior.


if (returnType == null)
{
throw new ArgumentNullException(nameof(returnType));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need test exercising this line.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, need to add to the doc comment that this method can throw ArgumentNullException in the list of Exceptions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to this:
https://github.com/dotnet/dotnet-api-docs/blob/fcf78e35bc4eca5734d3f248670b1ade805e2ed0/xml/System.Text.Json/JsonSerializer.xml#L75-L76

        <exception cref="T:System.ArgumentNullException">
          <paramref name="returnType" /> is <see langword="null" />.</exception>

huoyaoyuan and others added 2 commits September 19, 2020 15:12
Copy link
Contributor

@ahsonkhan ahsonkhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some docs feedback. Looks good otherwise.

/// There is remaining data in the span beyond a single JSON value.</exception>
/// <exception cref="NotSupportedException">
/// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/>
/// for <typeparamref name="TValue"/> or its serializable members.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huoyaoyuan and others added 2 commits September 23, 2020 16:13
Co-authored-by: Ahson Khan <ahkha@microsoft.com>
@ahsonkhan
Copy link
Contributor

@layomia - anything else left to do for this PR or is it ready for merging?

Copy link
Contributor

@layomia layomia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - will address linker tests for the new overload in a follow up.

@layomia layomia merged commit 7ca6d85 into dotnet:master Oct 14, 2020
@huoyaoyuan huoyaoyuan deleted the deserialization-char-span branch October 14, 2020 15:46
@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add ReadOnlySpan<char> overloads to JsonSerializer.Deserialize

5 participants