-
Notifications
You must be signed in to change notification settings - Fork 492
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
Add System.Text.Json
converters for our Newtonsoft JSON converters + add tests
#11840
Conversation
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
By the latest commit, deserializing:
In these cases, either both succeded or both failed, meaning their behaviour is the same. |
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneyBtcJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
I moved |
@kiminuo I don't know if this "typo" was intentional or not, but the missing public override Money? ReadJson(JsonReader reader, Type objectType, Money? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var stringValue = reader.Value as string;
return Parse(stringValue);
} and System.Text.Json throws json exception at public override Money? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.String)
{
throw new JsonException("Expected a JSON number value.");
} |
if (reader.TokenType != JsonTokenType.String)
{
throw new JsonException("Expected a JSON number value.");
} This is weird, based on the if, we don't expect a number value here, it's the opposite. We expect string value, and throw if it's not. |
Also FYI, there are big inconsistency in how we handle different values in json. Some numbers are numeric, some or strings, and I can't really see the pattern, why its like this. For example here, Also if you look at
Do you know why? |
The goal is not to change behavior, if possible. Changes in behavior should be IMHO documented in the post here. |
@turbolay @adamPetho I think this is quite close to being done. Could you review it one more time please? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overally LGTM.
Questions and nitpicks below.
WalletWasabi.Tests/UnitTests/JsonConverters/FeeRateJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/FeeRateJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/JsonConverters/MoneySatoshiJsonConverterTests.cs
Outdated
Show resolved
Hide resolved
public override bool HandleNull => true; | ||
|
||
/// <inheritdoc/> | ||
public override Network? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can get rid of the nullability of the return type if at the end we do a check like this.
Network network = Network.GetNetwork(networkString);
if (network is null) => throw Exception
return network
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we can do:
networkString = reader.GetString()?.Trim();
if (networkString is null)
{
throw new ArgumentNullException(nameof(networkString));
}
->
networkString = reader.GetString()!.Trim();
That makes sense to me because null
is checked before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured out that changing the nullability breaks the test.
If we don't allow to return null
, I think we change the behavior, too. Which goes against the goal of this PR.
It's up to you guys, if you want to deal with this in this PR or in another PR or never.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I applied my patch and it does not break tests.
} | ||
|
||
string? stringValue = reader.GetString(); | ||
return Parse(stringValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's wrong with TimeSpan.Parse(stringValue)
?
Does that behave so differently that we need our own parser function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's wrong with
TimeSpan.Parse(stringValue)
?
Nothing IMO.
Does that behave so differently that we need our own parser function?
Dunno, it just looks like somebody prefered different format at that time. TimeSpan.Parse(s)
parses different format: [ws][-]{ d | [d.]hh:mm[:ss[.ff]] }[ws]
according to https://learn.microsoft.com/en-us/dotnet/api/system.timespan.parse?view=net-7.0#system-timespan-parse(system-string).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should look into this in another PR, it's weird
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But what do you guys want to achieve really?
If people like the format <days>d <hours>h <minutes>m <seconds>s
, then it does what it is supposed to do. It's implemented in an inefficient way but AFAIK there are not that many TimeSpan
s to convert, or not?
edit: I believe that a compiled regex would be pretty fast here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ | ||
string? networkString; | ||
|
||
if (reader.TokenType == JsonTokenType.Null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When is this the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you read null
as a JSON token. Not "null"
but simply null
- e.g. { "Network": null }
.
I merged the PR. I think it's finished. Feel free to create any follow-up PR if you have an idea what to improve. But I think everything was addressed. Thanks for the help guys. |
OP changed by Kimi:
The goal of this PR is to introduce STJ versions of NewtonSoft.JSON converters that behave the same (as much as possible). This PR adds tests to show behavior of STJ and NSJ converters. NSJ converters were not functionally changed.
STJ has the following properties:
The short term goal is to save some time in reading Client config JSON file.
Changes in behaviour
InvalidCastException
becameJsonException
at in:NetworkJsonConverter
MoneySatoshiJsonConverter
FeeRateJsonConverter
EndPointJsonConverterNg
accepts null value forJsonWriter
to write. The same is true forNetworkJsonConverterNg
here. The reason being thatEndPointJsonConverter
andNetworkJsonConverter
skips theWriteJson
call when the value to write isnull
, so the exceptions here and here are not thrown.Resources
Footnotes
Newtonsoft.json was for a long time the number one library for JSON support but it certainly does not have the level of design work behind. ↩