Skip to content

Conversation

@kasiabulat
Copy link
Owner

I implemented JsonNumber methods using string to keep the actual value (and added more tests for it). I also added more equals-related methods to JsonNumber, JsonBoolean and JsonString.

cc: @joperezr @bartonjs @ericstj @ahsonkhan @terrajobst

}
public void SetDouble(double value)
{
_value = value.ToString();

Choose a reason for hiding this comment

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

question: will this roundtrip when using exponential notation?

namespace System.Text.Json
{
public partial class JsonNumber : JsonNode
public partial class JsonNumber : JsonNode, IEquatable<JsonNumber>

Choose a reason for hiding this comment

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

Would it also make sense to implement IComperable?

@ahsonkhan
Copy link

cc @JamesNK

@JamesNK
Copy link

JamesNK commented Jul 29, 2019

cc @JamesNK

I don't have any context here. Could you point me at a spec/proposal/issue that discusses what these APIs are for

@ahsonkhan
Copy link

ahsonkhan commented Jul 30, 2019

I don't have any context here. Could you point me at a spec/proposal/issue that discusses what these APIs are for

This is still in the initial prototype/design phase and maybe @joperezr / @kasiabulat have some doc/spec they can point you to (if we don't have one yet, it might be good to write one up at some point).

We are starting to fill in implementation details and then go through the API review/design in corefx within the next month or so (before @kasiabulat's internship ends), so there is no issue yet.

Essentially, we are looking to create a modifiable, dictionary-backed Json DOM API to complement the readonly JsonDocument/JsonElement, with type hierarchy consisting of the base type JsonNode (rather than a single union type JsonElement).
The user should be able to build up a structured in-memory representation of the JSON payload and modify it. That includes, remove, add, and update (similar to Newtonsoft.Json's JToken).

The WritableJsonApiTests.cs contains a bunch of usage scenarios that we want to enable with these types. For example:

public static void TestCreatingJsonObject()
{
var developer = new JsonObject
{
{ "name", "Kasia" },
{ "age", 22 },
{ "is developer", true },
{ "null property", (JsonNode) null }
};
Assert.IsType<JsonString>(developer["name"]);
var developerNameCasted = developer["name"] as JsonString;
Assert.Equal("Kasia", developerNameCasted.Value);
Assert.IsType<JsonNumber>(developer["age"]);
var developerAgeCasted = developer["age"] as JsonNumber;
Assert.Equal(22, developerAgeCasted.GetInt32());
Assert.IsType<JsonBoolean>(developer["is developer"]);
var isDeveloperCasted = developer["is developer"] as JsonBoolean;
Assert.Equal(true, isDeveloperCasted.Value);
Assert.Null(developer["null property"]);
}

I cc'd you primarily to get your eyes on it, and to get your insights early (if applicable), especially to avoid common pitfalls or design mistakes that you may have encountered (and to get your general opinion on the design). If you see any big rocks or have significant concerns, it would be great to discuss and address them before we have gone too deep with the current approach.

@kasiabulat
Copy link
Owner Author

kasiabulat commented Jul 30, 2019

I changed methods into one-liners and added more tests, but still need to add some for Get/TryGet for different types (correct and incorrect examples). Personally, I think it should be possible to GetInt after setting something that fits into int and not possible if it doesn't etc. And in current implementation I forget the information of what exact type was stored.

if (value == "")
throw new ArgumentException("Expected number, but instead got empty string.");

JsonWriterHelper.ValidateNumber(Encoding.UTF8.GetBytes(value).AsSpan());

Choose a reason for hiding this comment

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

Consider adding "throw argumentexception" validation to a copy of JsonWriterHelper.ValidateNumber (with Debug.Asserts changed to actual checks).

The length check can go there as well:
https://github.com/dotnet/corefx/blob/9d6729a940952dcc14dc8683218684f4da29198a/src/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs#L137-L148

throw new ArgumentException("Expected number, but instead got empty string.");

JsonWriterHelper.ValidateNumber(Encoding.UTF8.GetBytes(value).AsSpan());
_value = value;

Choose a reason for hiding this comment

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

I would suspect these strings to generally be small (say < 256 characters). Consider instead, stackalloc a span and use the Span<byte> overload of Encoding.UTF8.GetBytes to avoid the allocation on .NET Core 3.0 (and use the arraypool for larger length strings).
https://github.com/dotnet/corefx/blob/ef5b086fc5f134e3244d0bca10d70db8055fa1c6/src/System.Runtime/ref/System.Runtime.cs#L7683

OR

Validate the value as chars.

Something to consider to optimize the implementation a bit (but that can be deferred to later, if you like).


public float GetSingle() => float.Parse(_value);

public double GetDouble() => double.Parse(_value);

Choose a reason for hiding this comment

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

Question: Would escaped characters be supported? Especially since the Utf8JsonWriter escapes the + character by default (since it uses JavascriptEncoder.Default).

Console.WriteLine(double.Parse("25.1e+1")); // valid - 251
Console.WriteLine(double.Parse("25.1e\\u002B1")); // Fails

@kasiabulat
Copy link
Owner Author

I added decimal support and addressed other minor issues. There are still some questions left to discuss, but I am merging this PR and I will create one to the main corefx fork.

@kasiabulat kasiabulat merged commit 9dcfc4b into master Jul 30, 2019
@kasiabulat kasiabulat deleted the kasiabulat/writable-json-dom branch July 30, 2019 20:58
@kasiabulat
Copy link
Owner Author

I created the issue for my project: https://github.com/dotnet/corefx/issues/39922

kasiabulat added a commit that referenced this pull request Aug 9, 2019
* Json prototype (#1)

Basic API for Json writable DOM with scenarios including collection initialization, accessing and modifying Json nodes.

* Json prototype - transformation API  (#2)

* transformation API added
* assertions to existing scenarios added

* Json prototype (#1)

Basic API for Json writable DOM with scenarios including collection initialization, accessing and modifying Json nodes.

* Json prototype - transformation API  (#2)

* transformation API added
* assertions to existing scenarios added

* JsonNumber implementation and tests (#3)

* IEquatables added
* JsonNumber implementation and unit tests added
* pragmas deleted
* review comments included, more tests added
* decimal support added to JsonNumber
* decimal support added to JsonArray and JsonObject

* all unimplemented classes and methods with accompanying tests removed

* First part of documentation added

* documentation completed

* missing exceptions added

* JsonElement changes removed

* part of the review comments included

* work on review comments

* code refactor

* more decimal tests added using MemberData

* more decimal tests added using MemberData

* more test cases added

* equals summary adjusted, equals tests added

* more Equals tests added, GetHashCode tests added, minor changes

* scientifing notation support added, rational numbers tests fixes

* rational overflow tests added

* ulong maxvalue tests added to rational types

* presision problems fixes

* exception strings fixed

* CI failing fixes (hopefully), review comments included

* missing == tests added to achieve 100% branch coverage

* review comments included

* trailing whitespaces fixes

* equals comments added

* equals object refactored to call quals json number

* merge fix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants