From 80138655dd4135f163376f3e945936baf90ceb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katarzyna=20Bu=C5=82at?= Date: Wed, 17 Jul 2019 13:19:54 -0700 Subject: [PATCH 01/30] Json prototype (#1) Basic API for Json writable DOM with scenarios including collection initialization, accessing and modifying Json nodes. --- src/System.Text.Json/ref/System.Text.Json.cs | 244 ++++++- .../src/System.Text.Json.csproj | 6 + .../src/System/Text/Json/Node/JsonArray.cs | 104 +++ .../src/System/Text/Json/Node/JsonBoolean.cs | 24 + .../src/System/Text/Json/Node/JsonNode.cs | 16 + .../src/System/Text/Json/Node/JsonNumber.cs | 96 +++ .../src/System/Text/Json/Node/JsonObject.cs | 64 ++ .../src/System/Text/Json/Node/JsonString.cs | 24 + .../tests/System.Text.Json.Tests.csproj | 3 +- .../tests/WritableJsonApiTests.cs | 629 ++++++++++++++++++ 10 files changed, 1198 insertions(+), 12 deletions(-) create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.cs diff --git a/src/System.Text.Json/ref/System.Text.Json.cs b/src/System.Text.Json/ref/System.Text.Json.cs index b4120e2b2e8e..4e62192a4b1c 100644 --- a/src/System.Text.Json/ref/System.Text.Json.cs +++ b/src/System.Text.Json/ref/System.Text.Json.cs @@ -7,6 +7,97 @@ namespace System.Text.Json { + public partial class JsonArray : System.Text.Json.JsonNode, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable + { + public JsonArray() { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + [System.CLSCompliantAttribute(false)] + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + [System.CLSCompliantAttribute(false)] + public JsonArray(System.Collections.Generic.IEnumerable values) { } + [System.CLSCompliantAttribute(false)] + public JsonArray(System.Collections.Generic.IEnumerable values) { } + [System.CLSCompliantAttribute(false)] + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public int Count { get { throw null; } } + public bool IsReadOnly { get { throw null; } } + public System.Text.Json.JsonNode this[int idx] { get { throw null; } set { } } + public void Add(bool value) { } + public void Add(byte value) { } + public void Add(double value) { } + public void Add(short value) { } + public void Add(int value) { } + public void Add(long value) { } + [System.CLSCompliantAttribute(false)] + public void Add(sbyte value) { } + public void Add(float value) { } + public void Add(string value) { } + public void Add(System.Text.Json.JsonNode value) { } + [System.CLSCompliantAttribute(false)] + public void Add(ushort value) { } + [System.CLSCompliantAttribute(false)] + public void Add(uint value) { } + [System.CLSCompliantAttribute(false)] + public void Add(ulong value) { } + public void Clear() { } + public bool Contains(bool value) { throw null; } + public bool Contains(byte value) { throw null; } + public bool Contains(double value) { throw null; } + public bool Contains(short value) { throw null; } + public bool Contains(int value) { throw null; } + public bool Contains(long value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool Contains(sbyte value) { throw null; } + public bool Contains(float value) { throw null; } + public bool Contains(string value) { throw null; } + public bool Contains(System.Text.Json.JsonNode value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool Contains(ushort value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool Contains(uint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool Contains(ulong value) { throw null; } + public System.Collections.Generic.IEnumerator GetEnumerator() { throw null; } + public int IndexOf(System.Text.Json.JsonNode item) { throw null; } + public void Insert(int index, bool item) { } + public void Insert(int index, byte item) { } + public void Insert(int index, double item) { } + public void Insert(int index, short item) { } + public void Insert(int index, int item) { } + public void Insert(int index, long item) { } + [System.CLSCompliantAttribute(false)] + public void Insert(int index, sbyte item) { } + public void Insert(int index, float item) { } + public void Insert(int index, string item) { } + public void Insert(int index, System.Text.Json.JsonNode item) { } + [System.CLSCompliantAttribute(false)] + public void Insert(int index, ushort item) { } + [System.CLSCompliantAttribute(false)] + public void Insert(int index, uint item) { } + [System.CLSCompliantAttribute(false)] + public void Insert(int index, ulong item) { } + public bool Remove(System.Text.Json.JsonNode item) { throw null; } + public void RemoveAt(int index) { } + void System.Collections.Generic.ICollection.CopyTo(System.Text.Json.JsonNode[] array, int arrayIndex) { } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } + } + public partial class JsonBoolean : System.Text.Json.JsonNode + { + public JsonBoolean() { } + public JsonBoolean(bool value) { } + public bool Value { get { throw null; } set { } } + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + public static implicit operator System.Text.Json.JsonBoolean (bool value) { throw null; } + } public enum JsonCommentHandling : byte { Disallow = (byte)0, @@ -156,6 +247,130 @@ protected JsonNamingPolicy() { } public static System.Text.Json.JsonNamingPolicy CamelCase { get { throw null; } } public abstract string ConvertName(string name); } + public partial class JsonNode + { + public JsonNode() { } + } + public partial class JsonNumber : System.Text.Json.JsonNode + { + public JsonNumber() { } + public JsonNumber(byte value) { } + public JsonNumber(double value) { } + public JsonNumber(short value) { } + public JsonNumber(int value) { } + public JsonNumber(long value) { } + [System.CLSCompliantAttribute(false)] + public JsonNumber(sbyte value) { } + public JsonNumber(float value) { } + public JsonNumber(string value) { } + [System.CLSCompliantAttribute(false)] + public JsonNumber(ushort value) { } + [System.CLSCompliantAttribute(false)] + public JsonNumber(uint value) { } + [System.CLSCompliantAttribute(false)] + public JsonNumber(ulong value) { } + public override bool Equals(object obj) { throw null; } + public byte GetByte() { throw null; } + public double GetDouble() { throw null; } + public override int GetHashCode() { throw null; } + public short GetInt16() { throw null; } + public int GetInt32() { throw null; } + public long GetInt64() { throw null; } + [System.CLSCompliantAttribute(false)] + public sbyte GetSByte() { throw null; } + public float GetSingle() { throw null; } + public string GetString() { throw null; } + [System.CLSCompliantAttribute(false)] + public ushort GetUInt16() { throw null; } + [System.CLSCompliantAttribute(false)] + public uint GetUInt32() { throw null; } + [System.CLSCompliantAttribute(false)] + public ulong GetUInt64() { throw null; } + public static implicit operator System.Text.Json.JsonNumber (byte value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (double value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (short value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (int value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (long value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Text.Json.JsonNumber (sbyte value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (float value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Text.Json.JsonNumber (ushort value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Text.Json.JsonNumber (uint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Text.Json.JsonNumber (ulong value) { throw null; } + public void SetByte(byte value) { } + public void SetDouble(double value) { } + public void SetInt16(short value) { } + public void SetInt32(int value) { } + public void SetInt64(long value) { } + [System.CLSCompliantAttribute(false)] + public void SetSByte(sbyte value) { } + public void SetSingle(float value) { } + public void SetString(string value) { } + [System.CLSCompliantAttribute(false)] + public void SetUInt16(ushort value) { } + [System.CLSCompliantAttribute(false)] + public void SetUInt32(uint value) { } + [System.CLSCompliantAttribute(false)] + public void SetUInt64(ulong value) { } + public bool TryGetByte(out byte value) { throw null; } + public bool TryGetDouble(out double value) { throw null; } + public bool TryGetInt16(out short value) { throw null; } + public bool TryGetInt32(out int value) { throw null; } + public bool TryGetInt64(out long value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool TryGetSByte(out sbyte value) { throw null; } + public bool TryGetSingle(out float value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool TryGetUInt16(out ushort value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool TryGetUInt32(out uint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool TryGetUInt64(out ulong value) { throw null; } + } + public partial class JsonObject : System.Text.Json.JsonNode, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable + { + public JsonObject() { } + public JsonObject(System.Collections.Generic.IEnumerable> jsonProperties) { } + public System.Text.Json.JsonNode this[string key] { get { throw null; } set { } } + public System.Collections.Generic.ICollection PropertyNames { get { throw null; } } + public System.Collections.Generic.ICollection Values { get { throw null; } } + public void Add(System.Collections.Generic.KeyValuePair jsonProperty) { } + public void Add(string propertyName, bool propertyValue) { } + public void Add(string propertyName, byte propertyValue) { } + public void Add(string propertyName, System.Collections.Generic.IEnumerable propertyValue) { } + public void Add(string propertyName, double propertyValue) { } + public void Add(string propertyName, short propertyValue) { } + public void Add(string propertyName, int propertyValue) { } + public void Add(string propertyName, long propertyValue) { } + [System.CLSCompliantAttribute(false)] + public void Add(string propertyName, sbyte propertyValue) { } + public void Add(string propertyName, float propertyValue) { } + public void Add(string propertyName, string propertyValue) { } + public void Add(string propertyName, System.Text.Json.JsonArray propertyValue) { } + public void Add(string propertyName, System.Text.Json.JsonNode propertyValue) { } + [System.CLSCompliantAttribute(false)] + public void Add(string propertyName, ushort propertyValue) { } + [System.CLSCompliantAttribute(false)] + public void Add(string propertyName, uint propertyValue) { } + [System.CLSCompliantAttribute(false)] + public void Add(string propertyName, ulong propertyValue) { } + public void AddRange(System.Collections.Generic.IEnumerable> jsonProperties) { } + public bool ContainsProperty(string propertyName) { throw null; } + public System.Collections.Generic.IEnumerable GetAllProperties(string propertyName) { throw null; } + public System.Text.Json.JsonArray GetArrayProperty(string propertyName) { throw null; } + public System.Collections.Generic.IEnumerator> GetEnumerator() { throw null; } + public System.Text.Json.JsonObject GetObjectProperty(string propertyName) { throw null; } + public System.Text.Json.JsonNode GetProperty(string propertyName) { throw null; } + public bool ModifyPropertyName(string oldName, string newName) { throw null; } + public bool Remove(string propertyName) { throw null; } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } + public bool TryGetArrayProperty(string propertyName, out System.Text.Json.JsonArray jsonArray) { throw null; } + public bool TryGetObjectProperty(string propertyName, out System.Text.Json.JsonObject jsonObject) { throw null; } + public bool TryGetProperty(string propertyName, out System.Text.Json.JsonNode jsonNode) { throw null; } + } public readonly partial struct JsonProperty { private readonly object _dummy; @@ -164,8 +379,8 @@ public readonly partial struct JsonProperty public bool NameEquals(System.ReadOnlySpan utf8Text) { throw null; } public bool NameEquals(System.ReadOnlySpan text) { throw null; } public bool NameEquals(string text) { throw null; } - public void WriteTo(System.Text.Json.Utf8JsonWriter writer) { } public override string ToString() { throw null; } + public void WriteTo(System.Text.Json.Utf8JsonWriter writer) { } } public partial struct JsonReaderOptions { @@ -185,20 +400,20 @@ public static partial class JsonSerializer { public static object Deserialize(System.ReadOnlySpan utf8Json, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } public static object Deserialize(string json, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static TValue Deserialize(System.ReadOnlySpan utf8Json, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static TValue Deserialize(string json, System.Text.Json.JsonSerializerOptions options = null) { throw null; } + public static object Deserialize(ref System.Text.Json.Utf8JsonReader reader, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static object Deserialize(ref System.Text.Json.Utf8JsonReader reader, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } + public static TValue Deserialize(System.ReadOnlySpan utf8Json, System.Text.Json.JsonSerializerOptions options = null) { throw null; } + public static TValue Deserialize(string json, System.Text.Json.JsonSerializerOptions options = null) { throw null; } public static TValue Deserialize(ref System.Text.Json.Utf8JsonReader reader, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static string Serialize(object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static string Serialize(TValue value, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static byte[] SerializeToUtf8Bytes(object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static byte[] SerializeToUtf8Bytes(TValue value, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static string Serialize(object value, System.Type type, System.Text.Json.JsonSerializerOptions options = null) { throw null; } + public static void Serialize(System.Text.Json.Utf8JsonWriter writer, object value, System.Type type, System.Text.Json.JsonSerializerOptions options = null) { } + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, object value, System.Type type, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, TValue value, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static void Serialize(System.Text.Json.Utf8JsonWriter writer, object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = null) { } + public static byte[] SerializeToUtf8Bytes(object value, System.Type type, System.Text.Json.JsonSerializerOptions options = null) { throw null; } + public static byte[] SerializeToUtf8Bytes(TValue value, System.Text.Json.JsonSerializerOptions options = null) { throw null; } public static void Serialize(System.Text.Json.Utf8JsonWriter writer, TValue value, System.Text.Json.JsonSerializerOptions options = null) { } + public static string Serialize(TValue value, System.Text.Json.JsonSerializerOptions options = null) { throw null; } } public sealed partial class JsonSerializerOptions { @@ -216,6 +431,15 @@ public JsonSerializerOptions() { } public bool WriteIndented { get { throw null; } set { } } public System.Text.Json.Serialization.JsonConverter GetConverter(System.Type typeToConvert) { throw null; } } + public partial class JsonString : System.Text.Json.JsonNode + { + public JsonString() { } + public JsonString(string value) { } + public string Value { get { throw null; } set { } } + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + public static implicit operator System.Text.Json.JsonString (string value) { throw null; } + } public enum JsonTokenType : byte { None = (byte)0, diff --git a/src/System.Text.Json/src/System.Text.Json.csproj b/src/System.Text.Json/src/System.Text.Json.csproj index 8d2f4ddc7fb4..c7a1c9fceba6 100644 --- a/src/System.Text.Json/src/System.Text.Json.csproj +++ b/src/System.Text.Json/src/System.Text.Json.csproj @@ -22,7 +22,13 @@ + + + + + + diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs new file mode 100644 index 000000000000..5f5f14cb1789 --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs @@ -0,0 +1,104 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonArray : JsonNode, IList, IReadOnlyList + { + public JsonArray() { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + [CLSCompliant(false)] + public JsonArray(IEnumerable values) { } + [CLSCompliant(false)] + public JsonArray(IEnumerable values) { } + [CLSCompliant(false)] + public JsonArray(IEnumerable values) { } + [CLSCompliant(false)] + public JsonArray(IEnumerable values) { } + + public JsonNode this[int idx] { get => throw null; set => throw null; } + + public void Add(JsonNode value) { } + public void Add(string value) { } + public void Add(bool value) { } + public void Add(byte value) { } + public void Add(short value) { } + public void Add(int value) { } + public void Add(long value) { } + public void Add(float value) { } + public void Add(double value) { } + [CLSCompliant(false)] + public void Add(sbyte value) { } + [CLSCompliant(false)] + public void Add(ushort value) { } + [CLSCompliant(false)] + public void Add(uint value) { } + [CLSCompliant(false)] + public void Add(ulong value) { } + + public void Insert(int index, JsonNode item) { throw null; } + public void Insert(int index, string item) { throw null; } + public void Insert(int index, bool item) { throw null; } + public void Insert(int index, byte item) { throw null; } + public void Insert(int index, short item) { throw null; } + public void Insert(int index, int item) { throw null; } + public void Insert(int index, long item) { throw null; } + public void Insert(int index, float item) { throw null; } + public void Insert(int index, double item) { throw null; } + [CLSCompliant(false)] + public void Insert(int index, sbyte item) { throw null; } + [CLSCompliant(false)] + public void Insert(int index, ushort item) { throw null; } + [CLSCompliant(false)] + public void Insert(int index, uint item) { throw null; } + [CLSCompliant(false)] + public void Insert(int index, ulong item) { throw null; } + + public bool Contains(JsonNode value) { throw null; } + public bool Contains(string value) { throw null; } + public bool Contains(bool value) { throw null; } + public bool Contains(byte value) { throw null; } + public bool Contains(short value) { throw null; } + public bool Contains(int value) { throw null; } + public bool Contains(long value) { throw null; } + public bool Contains(float value) { throw null; } + public bool Contains(double value) { throw null; } + [CLSCompliant(false)] + public bool Contains(sbyte value) { throw null; } + [CLSCompliant(false)] + public bool Contains(ushort value) { throw null; } + [CLSCompliant(false)] + public bool Contains(uint value) { throw null; } + [CLSCompliant(false)] + public bool Contains(ulong value) { throw null; } + + public int Count => throw new NotImplementedException(); + public bool IsReadOnly => throw new NotImplementedException(); + + public int IndexOf(JsonNode item) { throw null; } + public void RemoveAt(int index) { throw null; } + public void Clear() { throw null; } + public bool Remove(JsonNode item) { throw null; } + + void ICollection.CopyTo(JsonNode[] array, int arrayIndex) { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public IEnumerator GetEnumerator() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs new file mode 100644 index 000000000000..c18f85b01b32 --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonBoolean : JsonNode + { + public JsonBoolean() { } + public JsonBoolean(bool value) { } + + public bool Value { get; set; } + + public static implicit operator JsonBoolean(bool value) { throw null; } + + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs new file mode 100644 index 000000000000..7dd0d7206f19 --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonNode + { + + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs new file mode 100644 index 000000000000..7a9fd6337015 --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -0,0 +1,96 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonNumber : JsonNode + { + public JsonNumber() { } + public JsonNumber(string value) { } + public JsonNumber(byte value) { } + public JsonNumber(short value) { } + public JsonNumber(int value) { } + public JsonNumber(long value) { } + public JsonNumber(float value) { } + public JsonNumber(double value) { } + [CLSCompliant(false)] + public JsonNumber(sbyte value) { } + [CLSCompliant(false)] + public JsonNumber(ushort value) { } + [CLSCompliant(false)] + public JsonNumber(uint value) { } + [CLSCompliant(false)] + public JsonNumber(ulong value) { } + + public string GetString() { throw null; } + public byte GetByte() { throw null; } + public int GetInt32() { throw null; } + public short GetInt16() { throw null; } + public long GetInt64() { throw null; } + public float GetSingle() { throw null; } + public double GetDouble() { throw null; } + [CLSCompliant(false)] + public sbyte GetSByte() { throw null; } + [CLSCompliant(false)] + public ushort GetUInt16() { throw null; } + [CLSCompliant(false)] + public uint GetUInt32() { throw null; } + [CLSCompliant(false)] + public ulong GetUInt64() { throw null; } + + public bool TryGetByte(out byte value) { throw null; } + public bool TryGetInt32(out int value) { throw null; } + public bool TryGetInt16(out short value) { throw null; } + public bool TryGetInt64(out long value) { throw null; } + public bool TryGetSingle(out float value) { throw null; } + public bool TryGetDouble(out double value) { throw null; } + [CLSCompliant(false)] + public bool TryGetSByte(out sbyte value) { throw null; } + [CLSCompliant(false)] + public bool TryGetUInt16(out ushort value) { throw null; } + [CLSCompliant(false)] + public bool TryGetUInt32(out uint value) { throw null; } + [CLSCompliant(false)] + public bool TryGetUInt64(out ulong value) { throw null; } + + public void SetString(string value) { } + public void SetByte(byte value) { } + public void SetInt32(int value) { } + public void SetInt16(short value) { } + public void SetInt64(long value) { } + public void SetSingle(float value) { } + public void SetDouble(double value) { } + [CLSCompliant(false)] + public void SetSByte(sbyte value) { } + [CLSCompliant(false)] + public void SetUInt16(ushort value) { } + [CLSCompliant(false)] + public void SetUInt32(uint value) { } + [CLSCompliant(false)] + public void SetUInt64(ulong value) { } + + public static implicit operator JsonNumber(byte value) { throw null; } + public static implicit operator JsonNumber(int value) { throw null; } + public static implicit operator JsonNumber(short value) { throw null; } + public static implicit operator JsonNumber(long value) { throw null; } + public static implicit operator JsonNumber(float value) { throw null; } + public static implicit operator JsonNumber(double value) { throw null; } + [CLSCompliant(false)] + public static implicit operator JsonNumber(sbyte value) { throw null; } + [CLSCompliant(false)] + public static implicit operator JsonNumber(ushort value) { throw null; } + [CLSCompliant(false)] + public static implicit operator JsonNumber(uint value) { throw null; } + [CLSCompliant(false)] + public static implicit operator JsonNumber(ulong value) { throw null; } + + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs new file mode 100644 index 000000000000..c9a083f3a2da --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonObject : JsonNode, IEnumerable> + { + public JsonObject() { } + public JsonObject(IEnumerable> jsonProperties) { } + + public JsonNode this[string key] { get => throw null; set => throw null; } + public IEnumerator> GetEnumerator() { throw null; } + + public void Add(KeyValuePair jsonProperty) { } + public void Add(string propertyName, JsonArray propertyValue) { } + public void Add(string propertyName, JsonNode propertyValue) { } + public void Add(string propertyName, string propertyValue) { } + public void Add(string propertyName, bool propertyValue) { } + public void Add(string propertyName, byte propertyValue) { } + public void Add(string propertyName, short propertyValue) { } + public void Add(string propertyName, int propertyValue) { } + public void Add(string propertyName, long propertyValue) { } + public void Add(string propertyName, float propertyValue) { } + public void Add(string propertyName, double propertyValue) { } + [CLSCompliant(false)] + public void Add(string propertyName, sbyte propertyValue) { } + [CLSCompliant(false)] + public void Add(string propertyName, ushort propertyValue) { } + [CLSCompliant(false)] + public void Add(string propertyName, uint propertyValue) { } + [CLSCompliant(false)] + public void Add(string propertyName, ulong propertyValue) { } + public void Add(string propertyName, IEnumerable propertyValue) { } + public void AddRange(IEnumerable> jsonProperties) { } + + public bool Remove(string propertyName) { throw null; } + public bool ContainsProperty(string propertyName) { throw null; } + + public bool ModifyPropertyName(string oldName, string newName) { throw null; } + + public JsonNode GetProperty(string propertyName) { throw null; } + public bool TryGetProperty(string propertyName, out JsonNode jsonNode) { throw null; } + public JsonObject GetObjectProperty(string propertyName) { throw null; } + public bool TryGetObjectProperty(string propertyName, out JsonObject jsonObject) { throw null; } + public JsonArray GetArrayProperty(string propertyName) { throw null; } + public bool TryGetArrayProperty(string propertyName, out JsonArray jsonArray) { throw null; } + public IEnumerable GetAllProperties(string propertyName) { throw null; } + + + public ICollection PropertyNames => throw null; + public ICollection Values => throw null; + + IEnumerator IEnumerable.GetEnumerator() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs new file mode 100644 index 000000000000..9c993375209c --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonString : JsonNode + { + public JsonString() { } + public JsonString(string value) { } + + public string Value { get; set; } + + public static implicit operator JsonString(string value) { throw null; } + + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj index 40a4ad9d6e9c..9f89307ce25d 100644 --- a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -100,9 +100,8 @@ - - + diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.cs b/src/System.Text.Json/tests/WritableJsonApiTests.cs new file mode 100644 index 000000000000..2b66c6c8acab --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.cs @@ -0,0 +1,629 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Helper class simulating external library + /// + private static class EmployeesDatabase + { + private static int s_id = 0; + public static KeyValuePair GetNextEmployee() + { + return new KeyValuePair("employee" + s_id++, new JsonObject()); + } + + public static IEnumerable> GetTenBestEmployees() + { + for (int i = 0; i < 10; i++) + yield return GetNextEmployee(); + } + + /// + /// Returns following JsonObject: + /// { + /// { "name" : "John" } + /// { "phone numbers" : { "work" : "123-456-7890", "home": "123-456-7890" } } + /// { + /// "reporting employees" : + /// { + /// "software developers" : + /// { + /// "full time employees" : /JsonObject of 3 employees fromk database/ + /// "intern employees" : /JsonObject of 2 employees fromk database/ + /// }, + /// "HR" : /JsonObject of 10 employees fromk database/ + /// } + /// + /// + public static JsonObject GetManager() + { + return new JsonObject + { + { "name", "John" }, + { + "phone numbers", new JsonObject() + { + { "work", "123-456-7890" }, { "home", "123-456-7890" } + } + }, + { + "reporting employees", new JsonObject() + { + { + "software developers", new JsonObject() + { + { + "full time employees", new JsonObject() + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + } + }, + { + "intern employees", new JsonObject() + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + } + } + } + }, + { + "HR", new JsonObject() + { + { + "full time employees", new JsonObject(EmployeesDatabase.GetTenBestEmployees()) + } + } + } + } + } + }; + } + + public static bool CheckSSN(string ssnNumber) => true; + } + + /// + /// Helper class simulating enum + /// + private enum AvailableStateCodes + { + WA, + CA, + NY, + } + + /// + /// Creating simple Json object + /// + [Fact] + public static void TestCreatingJsonObject() + { + var developer = new JsonObject + { + { "name", "Kasia" }, + { "age", 22 }, + { "is developer", true }, + { "null property", (JsonNode) null } + }; + } + + /// + /// Creating simple Json object by new methods on primary types + /// + [Fact] + public static void TestCreatingJsonObjectNewMethods() + { + var developer = new JsonObject + { + { "name", new JsonString("Kasia") }, + { "age", new JsonNumber(22) }, + { "is developer", new JsonBoolean(true) } + }; + } + + /// + /// Creating and retriving different numeric values + /// + [Fact] + public static void TestNumerics() + { + double PI = 3.14159265359; + var circle = new JsonObject + { + { "radius", 1 }, + { "length", 2*PI }, + { "area", PI } + }; + + JsonNumber bigConstantBoxed = Int64.MaxValue; + long bigConstant = bigConstantBoxed.GetInt64(); + + var smallValueBoxed = new JsonNumber(17); + smallValueBoxed.TryGetInt16(out short smallValue); + } + + /// + /// Creating nested Json object + /// + [Fact] + public static void TestCreatingNestedJsonObject() + { + var person = new JsonObject + { + { "name", "John" }, + { "surname", "Smith" }, + { + "phone numbers", new JsonObject() + { + { "work", "123-456-7890" }, + { "home", "123-456-7890" } + } + }, + { + "addresses", new JsonObject() + { + { + "office", new JsonObject() + { + { "address line 1", "One Microsoft Way" }, + { "city" , "Redmond" } , + { "zip code" , 98052 } , + { "state" , (int) AvailableStateCodes.WA } + } + }, + { + "home", new JsonObject() + { + { "address line 1", "Pear Ave" }, + { "address line 2", "1288" }, + { "city" , "Mountain View" } , + { "zip code" , 94043 } , + { "state" , (int) AvailableStateCodes.CA } + } + } + } + } + }; + } + + /// + /// Defining as KeyValuePair value + /// + [Fact] + public static void TestAssignmentDefinition() + { + JsonNode employee = EmployeesDatabase.GetNextEmployee().Value; + } + + /// + /// Adding KeyValuePair from external library + /// + [Fact] + public static void TestAddingKeyValuePair() + { + var employees = new JsonObject + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + }; + } + + /// + /// Adding KeyValuePair from external library after initialization + /// + [Fact] + public static void TestAddingKeyValuePairAfterInitialization() + { + var employees = new JsonObject(); + foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) + { + employees.Add(employee); + } + } + + /// + /// Adding KeyValuePairs collection from external library + /// + [Fact] + public static void TestAddingKeyValuePairsCollection() + { + var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); + } + + /// + /// Adding KeyValuePairs collection from external library after initialization + /// + [Fact] + public static void TestAddingKeyValuePairsCollectionAfterInitialization() + { + var employees = new JsonObject(); + employees.AddRange(EmployeesDatabase.GetTenBestEmployees()); + } + + /// + /// Creating Json array + /// + [Fact] + public static void TestCreatingJsonArray() + { + string[] dishes = { "sushi", "pasta", "cucumber soup" }; + + var sportsExperienceYears = new JsonObject() + { + { "skiing", 5 }, + { "cycling", 8 }, + { "hiking", 6 }, + { "chess", 2 }, + { "skating", 1 }, + }; + + // choose only sports with > 2 experience years + IEnumerable sports = sportsExperienceYears.Where(sport => ((JsonNumber)sport.Value).GetInt32() > 2).Select(sport => sport.Key); + + var strangeWords = new JsonArray() + { + "supercalifragilisticexpialidocious", + "gladiolus", + "albumen", + "smaragdine" + }; + + var preferences = new JsonObject() + { + { "colours", new JsonArray { "red", "green", "purple" } }, + { "numbers", new JsonArray { 4, 123, 88 } }, + { "prime numbers", new JsonNumber[] { 19, 37 } }, + { "varia", new JsonArray { 17, "green", true } }, + { "dishes", new JsonArray(dishes) }, + { "sports", new JsonArray(sports) }, + { "strange words", strangeWords.Where(word => ((JsonString)word).Value.Length < 10) }, + }; + } + + /// + /// Creating nested Json array + /// + [Fact] + public static void TestCreatingNestedJsonArray() + { + var vertices = new JsonArray() + { + new JsonArray + { + new JsonArray + { + new JsonArray { 0, 0, 0 }, + new JsonArray { 0, 0, 1 } + }, + new JsonArray + { + new JsonArray { 0, 1, 0 }, + new JsonArray { 0, 1, 1 } + } + }, + new JsonArray + { + new JsonArray + { + new JsonArray { 1, 0, 0 }, + new JsonArray { 1, 0, 1 } + }, + new JsonArray + { + new JsonArray { 1, 1, 0 }, + new JsonArray { 1, 1, 1 } + } + }, + }; + } + + /// + /// Adding values to JsonArray + /// + [Fact] + public static void TestAddingToJsonArray() + { + var employeesIds = new JsonArray(); + + foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) + { + employeesIds.Add(employee.Key); + } + } + + /// + /// Creating Json array from collection + /// + [Fact] + public static void TestCreatingJsonArrayFromCollection() + { + var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => new JsonString(employee.Key))); + } + + /// + /// Creating Json array from collection of strings + /// + [Fact] + public static void TestCreatingJsonArrayFromCollectionOfString() + { + var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => employee.Key)); + } + + /// + /// Contains checks + /// + [Fact] + public static void TestContains() + { + var person = new JsonObject + { + { "name", "John" }, + { "ssn", "123456789" }, + }; + + if (person.ContainsProperty("ssn")) + { + EmployeesDatabase.CheckSSN(((JsonString)person["ssn"]).Value); + } + + var enabledOptions = new JsonArray + { + "readonly", + "no cache", + "continue on failure" + }; + + if (enabledOptions.Contains("no cache")) + { + // do sth without using caching + } + + var requiredOptions = new JsonArray + { + "readonly", + "continue on failure" + }; + + // if all required options are enabled + if (!requiredOptions.Select(option => !enabledOptions.Contains(option)).Any()) + { + // do sth without using caching + } + } + + /// + /// Replacing Json object's primnary types + /// + [Fact] + public static void TestReplacingsonObjectPrimaryTypes() + { + var person1 = new JsonObject + { + { "name", "John" }, + { "age", 45 }, + { "is_married", true } + }; + + // Assign by creating a new instance of primary Json type + person1["name"] = new JsonString("Bob"); + + // Assign by using an implicit operator on primary Json type + JsonNumber newAge = 55; + person1["age"] = newAge; + + // Assign by explicit cast from Json primary type + person1["is_married"] = (JsonBoolean)true; + + // Not possible scenario (wold require implicit cast operators in JsonNode): + // person["name"] = "Bob"; + + var person2 = new JsonObject + { + { "name", new JsonString[]{ "Emily", "Rosalie" } }, + { "age", 33 }, + { "is_married", true } + }; + + // Copy property from another JsonObject + person1["age"] = person2["age"]; + + // Copy property of different typoe + person1["name"] = person2["name"]; + } + + /// + /// Modifying Json object's primnary types + /// + [Fact] + public static void TestModifyingJsonObjectPrimaryTypes() + { + JsonString name = "previous name"; + name.Value = "new name"; + + bool shouldBeEnabled = true; + var isEnabled = new JsonBoolean(false); + isEnabled.Value = shouldBeEnabled; + + JsonNumber veryBigConstant = new JsonNumber(); + veryBigConstant.SetString("1e1000"); + string bigNumber = veryBigConstant.GetString(); + veryBigConstant.SetInt16(123); + short smallNumber = veryBigConstant.GetInt16(); + } + + /// + /// Accesing nested Json object - casting with as operator + /// + [Fact] + public static void TestAccesingNestedJsonObjectCastWithAs() + { + // Casting with as operator + JsonObject manager = EmployeesDatabase.GetManager(); + + var reportingEmployees = manager["reporting employees"] as JsonObject; + if (reportingEmployees == null) + throw new InvalidCastException(); + + var softwareDevelopers = reportingEmployees["software developers"] as JsonObject; + if (softwareDevelopers == null) + throw new InvalidCastException(); + + var internDevelopers = softwareDevelopers["intern employees"] as JsonObject; + if (internDevelopers == null) + throw new InvalidCastException(); + + internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - casting with is operator + /// + [Fact] + public static void TestAccesingNestedJsonObjectCastWithIs() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + if (manager["reporting employees"] is JsonObject reportingEmployees) + { + if (reportingEmployees["software developers"] is JsonObject softwareDevelopers) + { + if (softwareDevelopers["full time employees"] is JsonObject fullTimeEmployees) + { + fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); + } + } + } + } + + /// + /// Accesing nested Json object - explicit casting + /// + [Fact] + public static void TestAccesingNestedJsonObjectExplicitCast() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + ((JsonObject)((JsonObject)manager["reporting employees"])["HR"]).Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - GetObjectProperty method + /// + [Fact] + public static void TestAccesingNestedJsonObjectGetPropertyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject internDevelopers = manager.GetObjectProperty("reporting employees") + .GetObjectProperty("software developers") + .GetObjectProperty("intern employees"); + internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - TryGetObjectProperty method + /// + [Fact] + public static void TestAccesingNestedJsonObjectTryGetPropertyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + if (manager.TryGetObjectProperty("reporting employees", out JsonObject reportingEmployees)) + { + if (reportingEmployees.TryGetObjectProperty("software developers", out JsonObject softwareDevelopers)) + { + if (softwareDevelopers.TryGetObjectProperty("full time employees", out JsonObject fullTimeEmployees)) + { + fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); + } + } + } + } + + /// + /// Accesing nested Json array - GetArrayProperty method + /// + [Fact] + public static void TestAccesingNestedJsonArrayGetPropertyMethod() + { + var issues = new JsonObject() + { + { "features", new JsonArray{ "new functionality 1", "new functionality 2" } }, + { "bugs", new JsonArray{ "bug 123", "bug 4566", "bug 821" } }, + { "tests", new JsonArray{ "code coverage" } }, + }; + + issues.GetArrayProperty("bugs").Add("bug 12356"); + ((JsonString)issues.GetArrayProperty("features")[0]).Value = "feature 1569"; + ((JsonString)issues.GetArrayProperty("features")[1]).Value = "feature 56134"; + } + + /// + /// Modifying Json object key - remove and add + /// + [Fact] + public static void TestModifyingJsonObjectKeyRemoveAdd() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject reportingEmployees = manager.GetObjectProperty("reporting employees"); + + JsonNode softwareDevelopers = reportingEmployees["software developers"]; + reportingEmployees.Remove("software developers"); + reportingEmployees.Add("software engineers", softwareDevelopers); + } + + /// + /// Modifying Json object key - modify method + /// + [Fact] + public static void TestModifyingJsonObjectKeyModifyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject reportingEmployees = manager.GetObjectProperty("reporting employees"); + + reportingEmployees.ModifyPropertyName("software developers", "software engineers"); + } + + /// + /// Aquiring all values + /// + [Fact] + public static void TestAquiringAllValues() + { + var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); + ICollection employeesWithoutId = employees.Values; + } + + /// + /// Aquiring all properties + /// + [Fact] + public static void TestAquiringAllProperties() + { + var employees = new JsonObject() + { + { "FTE", "John Smith" }, + { "FTE", "Ann Predictable" }, + { "Intern", "Zoe Coder" }, + { "FTE", "Byron Shadow" }, + }; + + IEnumerable fullTimeEmployees = employees.GetAllProperties("FTE"); + } + } +} From 0f7df28f5f86030eaa5dde34047826e8f6906490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katarzyna=20Bu=C5=82at?= Date: Fri, 19 Jul 2019 15:21:28 -0700 Subject: [PATCH 02/30] Json prototype - transformation API (#2) * transformation API added * assertions to existing scenarios added --- src/System.Text.Json/ref/System.Text.Json.cs | 23 +- .../System/Text/Json/Document/JsonElement.cs | 5 + .../src/System/Text/Json/Node/JsonArray.cs | 5 +- .../src/System/Text/Json/Node/JsonNode.cs | 20 +- .../src/System/Text/Json/Node/JsonObject.cs | 4 +- .../tests/System.Text.Json.Tests.csproj | 4 + ...JsonApiTests.TestAccessingNestedMembers.cs | 146 +++++ .../tests/WritableJsonApiTests.TestData.cs | 136 +++++ .../WritableJsonApiTests.TestModifying.cs | 175 ++++++ ...ritableJsonApiTests.TestTransformations.cs | 232 ++++++++ .../tests/WritableJsonApiTests.cs | 548 ++++++++---------- 11 files changed, 977 insertions(+), 321 deletions(-) create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs diff --git a/src/System.Text.Json/ref/System.Text.Json.cs b/src/System.Text.Json/ref/System.Text.Json.cs index 4e62192a4b1c..821d2e72774f 100644 --- a/src/System.Text.Json/ref/System.Text.Json.cs +++ b/src/System.Text.Json/ref/System.Text.Json.cs @@ -84,6 +84,7 @@ public void Insert(int index, ushort item) { } public void Insert(int index, uint item) { } [System.CLSCompliantAttribute(false)] public void Insert(int index, ulong item) { } + public int LastIndexOf(System.Text.Json.JsonNode item) { throw null; } public bool Remove(System.Text.Json.JsonNode item) { throw null; } public void RemoveAt(int index) { } void System.Collections.Generic.ICollection.CopyTo(System.Text.Json.JsonNode[] array, int arrayIndex) { } @@ -130,6 +131,7 @@ public readonly partial struct JsonElement { private readonly object _dummy; private readonly int _dummyPrimitive; + public bool IsImmutable { get { throw null; } } public System.Text.Json.JsonElement this[int index] { get { throw null; } } public System.Text.Json.JsonValueKind ValueKind { get { throw null; } } public System.Text.Json.JsonElement Clone() { throw null; } @@ -247,9 +249,20 @@ protected JsonNamingPolicy() { } public static System.Text.Json.JsonNamingPolicy CamelCase { get { throw null; } } public abstract string ConvertName(string name); } - public partial class JsonNode - { - public JsonNode() { } + public abstract partial class JsonNode + { + internal JsonNode() { } + public System.Text.Json.JsonElement AsJsonElement() { throw null; } + public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonDocument jsonDocument) { throw null; } + public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonElement jsonElement) { throw null; } + public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonNode jsonNode) { throw null; } + public static System.Text.Json.JsonNode GetNode(System.Text.Json.JsonElement jsonElement) { throw null; } + public static System.Text.Json.JsonNode Parse(System.Buffers.ReadOnlySequence utf8Json) { throw null; } + public static System.Text.Json.JsonNode Parse(System.IO.Stream utf8Json) { throw null; } + public static System.Text.Json.JsonNode Parse(System.ReadOnlyMemory utf8Json) { throw null; } + public static System.Text.Json.JsonNode Parse(System.ReadOnlyMemory json) { throw null; } + public static System.Text.Json.JsonNode Parse(string json) { throw null; } + public static bool TryGetNode(System.Text.Json.JsonElement jsonElement, out System.Text.Json.JsonNode jsonNode) { throw null; } } public partial class JsonNumber : System.Text.Json.JsonNode { @@ -360,9 +373,9 @@ public void Add(string propertyName, ulong propertyValue) { } public void AddRange(System.Collections.Generic.IEnumerable> jsonProperties) { } public bool ContainsProperty(string propertyName) { throw null; } public System.Collections.Generic.IEnumerable GetAllProperties(string propertyName) { throw null; } - public System.Text.Json.JsonArray GetArrayProperty(string propertyName) { throw null; } public System.Collections.Generic.IEnumerator> GetEnumerator() { throw null; } - public System.Text.Json.JsonObject GetObjectProperty(string propertyName) { throw null; } + public System.Text.Json.JsonArray GetJsonArrayProperty(string propertyName) { throw null; } + public System.Text.Json.JsonObject GetJsonObjectProperty(string propertyName) { throw null; } public System.Text.Json.JsonNode GetProperty(string propertyName) { throw null; } public bool ModifyPropertyName(string oldName, string newName) { throw null; } public bool Remove(string propertyName) { throw null; } diff --git a/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs b/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs index 1b142fd5f6a8..39369b3828fd 100644 --- a/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs +++ b/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs @@ -1440,5 +1440,10 @@ private void CheckValidInstance() [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay => $"ValueKind = {ValueKind} : \"{ToString()}\""; + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + public bool IsImmutable => throw null; +#pragma warning restore CS1591 } } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs index 5f5f14cb1789..c2abffde5a74 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs @@ -87,10 +87,11 @@ public void Add(ulong value) { } [CLSCompliant(false)] public bool Contains(ulong value) { throw null; } - public int Count => throw new NotImplementedException(); - public bool IsReadOnly => throw new NotImplementedException(); + public int Count => throw null; + public bool IsReadOnly => throw null; public int IndexOf(JsonNode item) { throw null; } + public int LastIndexOf(JsonNode item) { throw null; } public void RemoveAt(int index) { throw null; } public void Clear() { throw null; } public bool Remove(JsonNode item) { throw null; } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs index 7dd0d7206f19..fc907402a258 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs @@ -5,11 +5,29 @@ // for now disabling error caused by not adding documentation to methods #pragma warning disable CS1591 +using System.Buffers; +using System.IO; + namespace System.Text.Json { - public partial class JsonNode + public abstract partial class JsonNode { + private protected JsonNode() { } + public JsonElement AsJsonElement() { throw null; } + + public static JsonNode GetNode(JsonElement jsonElement) { throw null; } + public static bool TryGetNode(JsonElement jsonElement, out JsonNode jsonNode) { throw null; } + + public static JsonNode Parse(string json) { throw null; } + public static JsonNode Parse(ReadOnlySequence utf8Json) { throw null; } + public static JsonNode Parse(Stream utf8Json) { throw null; } + public static JsonNode Parse(ReadOnlyMemory utf8Json) { throw null; } + public static JsonNode Parse(ReadOnlyMemory json) { throw null; } + + public static JsonNode DeepCopy(JsonNode jsonNode) { throw null; } + public static JsonNode DeepCopy(JsonElement jsonElement) { throw null; } + public static JsonNode DeepCopy(JsonDocument jsonDocument) { throw null; } } } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs index c9a083f3a2da..5955e1fd3eea 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs @@ -47,9 +47,9 @@ public void AddRange(IEnumerable> jsonProperties) public JsonNode GetProperty(string propertyName) { throw null; } public bool TryGetProperty(string propertyName, out JsonNode jsonNode) { throw null; } - public JsonObject GetObjectProperty(string propertyName) { throw null; } + public JsonObject GetJsonObjectProperty(string propertyName) { throw null; } public bool TryGetObjectProperty(string propertyName, out JsonObject jsonObject) { throw null; } - public JsonArray GetArrayProperty(string propertyName) { throw null; } + public JsonArray GetJsonArrayProperty(string propertyName) { throw null; } public bool TryGetArrayProperty(string propertyName, out JsonArray jsonArray) { throw null; } public IEnumerable GetAllProperties(string propertyName) { throw null; } diff --git a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj index 9f89307ce25d..527c88ff350a 100644 --- a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -101,7 +101,11 @@ + + + + diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs new file mode 100644 index 000000000000..cf5b586c7f52 --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs @@ -0,0 +1,146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static partial class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Accesing nested Json object - casting with as operator + /// + [Fact] + public static void TestAccesingNestedJsonObjectCastWithAs() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + // Should not throw any exceptions: + + var reportingEmployees = manager["reporting employees"] as JsonObject; + if (reportingEmployees == null) + throw new InvalidCastException(); + + var softwareDevelopers = reportingEmployees["software developers"] as JsonObject; + if (softwareDevelopers == null) + throw new InvalidCastException(); + + var internDevelopers = softwareDevelopers["intern employees"] as JsonObject; + if (internDevelopers == null) + throw new InvalidCastException(); + + internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - casting with is operator + /// + [Fact] + public static void TestAccesingNestedJsonObjectCastWithIs() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + static bool AddEmployee(JsonObject manager) + { + + if (manager["reporting employees"] is JsonObject reportingEmployees) + { + if (reportingEmployees["software developers"] is JsonObject softwareDevelopers) + { + if (softwareDevelopers["full time employees"] is JsonObject fullTimeEmployees) + { + fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); + return true; + } + } + } + return false; + } + + bool success = AddEmployee(manager); + Assert.True(success); + } + + /// + /// Accesing nested Json object - explicit casting + /// + [Fact] + public static void TestAccesingNestedJsonObjectExplicitCast() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + // Should not throw any exceptions: + ((JsonObject)((JsonObject)manager["reporting employees"])["HR"]).Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - GetObjectProperty method + /// + [Fact] + public static void TestAccesingNestedJsonObjectGetPropertyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + // Should not throw any exceptions: + + JsonObject internDevelopers = manager.GetJsonObjectProperty("reporting employees") + .GetJsonObjectProperty("software developers") + .GetJsonObjectProperty("intern employees"); + internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - TryGetObjectProperty method + /// + [Fact] + public static void TestAccesingNestedJsonObjectTryGetPropertyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + static bool AddEmployee(JsonObject manager) + { + if (manager.TryGetObjectProperty("reporting employees", out JsonObject reportingEmployees)) + { + if (reportingEmployees.TryGetObjectProperty("software developers", out JsonObject softwareDevelopers)) + { + if (softwareDevelopers.TryGetObjectProperty("full time employees", out JsonObject fullTimeEmployees)) + { + fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); + return true; + } + } + } + + return false; + } + + bool success = AddEmployee(manager); + Assert.True(success); + } + + /// + /// Accesing nested Json array - GetArrayProperty method + /// + [Fact] + public static void TestAccesingNestedJsonArrayGetPropertyMethod() + { + var issues = new JsonObject() + { + { "features", new JsonArray{ "new functionality 1", "new functionality 2" } }, + { "bugs", new JsonArray{ "bug 123", "bug 4566", "bug 821" } }, + { "tests", new JsonArray{ "code coverage" } }, + }; + + issues.GetJsonArrayProperty("bugs").Add("bug 12356"); + ((JsonString)issues.GetJsonArrayProperty("features")[0]).Value = "feature 1569"; + ((JsonString)issues.GetJsonArrayProperty("features")[1]).Value = "feature 56134"; + + Assert.True(((JsonArray)issues["bugs"]).Contains("bug 12356")); + Assert.Equal((JsonString)((JsonArray)issues["features"])[0], "feature 1569"); + Assert.Equal((JsonString)((JsonArray)issues["features"])[1], "feature 56134"); + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs new file mode 100644 index 000000000000..e53f85379232 --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs @@ -0,0 +1,136 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static partial class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Helper class simulating external library + /// + private static class EmployeesDatabase + { + private static int s_id = 0; + public static KeyValuePair GetNextEmployee() + { + var employee = new JsonObject() + { + { "name", "John" } , + { "surname", "Smith"}, + { "age", 45 } + }; + + return new KeyValuePair("employee" + s_id++, employee); + } + + public static IEnumerable> GetTenBestEmployees() + { + for (int i = 0; i < 10; i++) + yield return GetNextEmployee(); + } + + /// + /// Returns following JsonObject: + /// { + /// { "name" : "John" } + /// { "phone numbers" : { "work" : "123-456-7890", "home": "123-456-7890" } } + /// { + /// "reporting employees" : + /// { + /// "software developers" : + /// { + /// "full time employees" : /JsonObject of 3 employees fromk database/ + /// "intern employees" : /JsonObject of 2 employees fromk database/ + /// }, + /// "HR" : /JsonObject of 10 employees fromk database/ + /// } + /// + /// + public static JsonObject GetManager() + { + var manager = GetNextEmployee().Value as JsonObject; + + manager.Add + ( + "phone numbers", + new JsonObject() + { + { "work", "123-456-7890" }, { "home", "123-456-7890" } + } + ); + + manager.Add + ( + "reporting employees", new JsonObject() + { + { + "software developers", new JsonObject() + { + { + "full time employees", new JsonObject() + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + } + }, + { + "intern employees", new JsonObject() + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + } + } + } + }, + { + "HR", new JsonObject() + { + { + "full time employees", new JsonObject(EmployeesDatabase.GetTenBestEmployees()) + } + } + } + } + ); + + return manager; + } + + public static bool CheckSSN(string ssnNumber) => true; + public static void PerformHeavyOperations(JsonElement employee) { } + } + + /// + /// Helper class simulating sending Json files via network + /// + private static class Mailbox + { + public static void SendEmployeeData(JsonElement employeeData) { } + public static JsonElement RetrieveMutableEmployeeData() { return EmployeesDatabase.GetNextEmployee().Value.AsJsonElement(); } + public static JsonElement RetrieveImmutableEmployeeData() { return new JsonElement(); } + + public static void SendAllEmployeesData(JsonElement employeesData) { } + } + + private static class HealthCare + { + public static void CreateMedicalAppointment(string personName) { } + } + + /// + /// Helper class simulating enum + /// + private enum AvailableStateCodes + { + WA, + CA, + NY, + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs new file mode 100644 index 000000000000..e4885b5074b4 --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs @@ -0,0 +1,175 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Xunit; + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static partial class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Replacing Json object's primnary types + /// + [Fact] + public static void TestReplacingsonObjectPrimaryTypes() + { + var person1 = new JsonObject + { + { "name", "John" }, + { "age", 45 }, + { "is_married", true } + }; + + // Assign by creating a new instance of primary Json type + person1["name"] = new JsonString("Bob"); + + Assert.IsType(person1["name"]); + Assert.Equal(person1["name"] as JsonString, "Bob"); + + // Assign by using an implicit operator on primary Json type + JsonNumber newAge = 55; + person1["age"] = newAge; + + Assert.IsType(person1["age"]); + Assert.Equal(person1["age"] as JsonNumber, 55); + + // Assign by explicit cast from Json primary type + person1["is_married"] = (JsonBoolean)false; + + Assert.IsType(person1["is_married"]); + Assert.Equal(person1["is_married"] as JsonBoolean, false); + + // Not possible scenario (wold require implicit cast operators in JsonNode): + // person["name"] = "Bob"; + + var person2 = new JsonObject + { + { "name", new JsonString[]{ "Emily", "Rosalie" } }, + { "age", 33 }, + { "is_married", true } + }; + + // Copy property from another JsonObject + person1["age"] = person2["age"]; + + Assert.IsType(person1["age"]); + Assert.Equal(person1["age"] as JsonNumber, 33); + + // Copy property of different typoe + person1["name"] = person2["name"]; + + Assert.IsType(person1["name"]); + } + + /// + /// Modifying Json object's primnary types + /// + [Fact] + public static void TestModifyingJsonObjectPrimaryTypes() + { + JsonString name = "previous name"; + name.Value = "new name"; + + Assert.Equal("new name", name.Value); + + bool shouldBeEnabled = true; + var isEnabled = new JsonBoolean(false); + isEnabled.Value = shouldBeEnabled; + + Assert.True(isEnabled.Value); + + JsonNumber veryBigConstant = new JsonNumber(); + veryBigConstant.SetString("1e1000"); + string bigNumber = veryBigConstant.GetString(); + + Assert.Equal("1e1000", bigNumber); + + veryBigConstant.SetInt16(123); + short smallNumber = veryBigConstant.GetInt16(); + + Assert.Equal(123, smallNumber); + + // Incrementing age: + JsonObject employee = EmployeesDatabase.GetManager(); + int age = ((JsonNumber)employee["age"]).GetInt32(); + ((JsonNumber)employee["age"]).SetInt32(age + 1); + + Assert.Equal(46, ((JsonNumber)employee["age"]).GetInt32()); + } + + /// + /// Adding values to JsonArray + /// + [Fact] + public static void TestAddingToJsonArray() + { + var employeesIds = new JsonArray(); + + foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) + { + employeesIds.Add(employee.Key); + } + + JsonString prevId = new JsonString(); + foreach (JsonNode employeeId in employeesIds) + { + Assert.IsType(employeeId); + var employeeIdString = employeeId as JsonString; + Assert.NotEqual(prevId, employeeIdString); + prevId = employeeIdString; + } + } + + /// + /// Modifying Json object key - remove and add + /// + [Fact] + public static void TestModifyingJsonObjectKeyRemoveAdd() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject reportingEmployees = manager.GetJsonObjectProperty("reporting employees"); + + static void ModifyProperty(JsonObject jsonObject, string previousName, string newName) + { + JsonNode previousValue = jsonObject[previousName]; + jsonObject.Remove(previousName); + jsonObject.Add(newName, previousValue); + } + + string previousName = "software developers"; + string newName = "software engineers"; + + Assert.True(reportingEmployees.ContainsProperty(previousName)); + JsonNode previousValue = reportingEmployees[previousName]; + + ModifyProperty(reportingEmployees, previousName, newName); + + Assert.False(reportingEmployees.ContainsProperty(previousName)); + Assert.True(reportingEmployees.ContainsProperty(newName)); + Assert.Equal(previousValue, reportingEmployees[newName]); + } + + /// + /// Modifying Json object key - modify method + /// + [Fact] + public static void TestModifyingJsonObjectKeyModifyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject reportingEmployees = manager.GetJsonObjectProperty("reporting employees"); + + Assert.True(reportingEmployees.ContainsProperty("software developers")); + JsonNode previousValue = reportingEmployees["software engineers"]; + + reportingEmployees.ModifyPropertyName("software developers", "software engineers"); + + Assert.False(reportingEmployees.ContainsProperty("software developers")); + Assert.True(reportingEmployees.ContainsProperty("software engineers")); + Assert.Equal(previousValue, reportingEmployees["software engineers"]); + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs new file mode 100644 index 000000000000..0b6a5d96ecbc --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs @@ -0,0 +1,232 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static partial class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Transforming JsoneNode to JsonElement + /// + [Fact] + public static void TestTransformingJsonNodeToJsonElement() + { + // Send Json through network, should not throw any exceptions: + JsonNode employeeDataToSend = EmployeesDatabase.GetNextEmployee().Value; + Mailbox.SendEmployeeData(employeeDataToSend.AsJsonElement()); + } + + /// + /// Transforming JsonElement to JsonNode + /// + [Fact] + public static void TestTransformingJsonElementToJsonNode() + { + // Retrieve Json from network, should not throw any exceptions: + JsonNode receivedEmployeeData = JsonNode.DeepCopy(Mailbox.RetrieveMutableEmployeeData()); + if (receivedEmployeeData is JsonObject employee) + { + employee["name"] = new JsonString("Bob"); + Mailbox.SendEmployeeData(employee.AsJsonElement()); + } + } + + /// + /// Transforming JsonDocument to JsonNode and vice versa + /// + [Fact] + public static void TestTransformingToFromJsonDocument() + { + string jsonString = @" + { + ""employee1"" : + { + ""name"" : ""Ann"", + ""surname"" : ""Predictable"", + ""age"" : 30, + }, + ""employee2"" : + { + ""name"" : ""Zoe"", + ""surname"" : ""Coder"", + ""age"" : 24, + } + }"; + + using (JsonDocument employeesToSend = JsonDocument.Parse(jsonString)) + { + // regular send: + Mailbox.SendAllEmployeesData(employeesToSend.RootElement); + + // modified elements send: + JsonObject employees = JsonNode.DeepCopy(employeesToSend) as JsonObject; + Assert.Equal(2, employees.Count()); + + employees.Add(EmployeesDatabase.GetNextEmployee()); + Assert.Equal(3, employees.Count()); + + Mailbox.SendAllEmployeesData(employees.AsJsonElement()); + } + } + + /// + /// Parsing right to JsonNode if user knows data will be modified + /// + [Fact] + public static void TestParsingToJsonNode() + { + string jsonString = @" + { + ""employee1"" : + { + ""name"" : ""Ann"", + ""surname"" : ""Predictable"", + ""age"" : 30, + }, + ""employee2"" : + { + ""name"" : ""Zoe"", + ""surname"" : ""Coder"", + ""age"" : 24, + } + }"; + + JsonObject employees = JsonNode.Parse(jsonString) as JsonObject; + employees.Add(EmployeesDatabase.GetNextEmployee()); + Mailbox.SendAllEmployeesData(employees.AsJsonElement()); + + Assert.Equal(2, employees.Count()); + Assert.True(employees.ContainsProperty("employee1")); + Assert.True(employees.ContainsProperty("employee2")); + + JsonObject employee2 = employees.GetJsonObjectProperty("employee2"); + Assert.IsType(employee2["name"]); + Assert.Equal("Zoe", (JsonString)employee2["name"]); + Assert.IsType(employee2["surname"]); + Assert.Equal("Coder", (JsonString)employee2["surname"]); + Assert.IsType(employee2["age"]); + Assert.Equal(24, (JsonNumber)employee2["age"]); + } + + /// + /// Copying JsoneNode + /// + [Fact] + public static void TestCopyingJsonNode() + { + JsonObject employee = EmployeesDatabase.GetManager(); + JsonNode employeeCopy = JsonNode.DeepCopy(employee); + + static bool RecursiveEquals(JsonNode left, JsonNode right) + { + if (left == null && right == null) + { + return true; + } + + if (right.GetType() != left.GetType()) + { + return false; + } + + switch (left) + { + case JsonObject leftJsonObject: + var rightJsonObject = right as JsonObject; + if (leftJsonObject.Count() != rightJsonObject.Count()) + { + return false; + } + + for (int idx = 0; idx < leftJsonObject.Count(); idx++) + { + KeyValuePair leftElement = leftJsonObject.ElementAt(idx); + KeyValuePair rightElement = rightJsonObject.ElementAt(idx); + + if (leftElement.Key != rightElement.Key || !RecursiveEquals(leftElement.Value, rightElement.Value)) + { + return false; + } + } + + return true; + case JsonArray leftJsonArray: + var rightJsonArray = right as JsonArray; + if (leftJsonArray.Count() != rightJsonArray.Count()) + { + return false; + } + for (int idx = 0; idx < leftJsonArray.Count(); idx++) + { + JsonNode leftElement = leftJsonArray.ElementAt(idx); + JsonNode rightElement = rightJsonArray.ElementAt(idx); + + if (!RecursiveEquals(leftElement, rightElement)) + { + return false; + } + } + + return true; + case JsonString leftJsonString: + return leftJsonString.Equals(right as JsonString); + case JsonNumber leftJsonNumber: + return leftJsonNumber.Equals(right as JsonNumber); + case JsonBoolean leftJsonBoolean: + return leftJsonBoolean.Equals(right as JsonBoolean); + default: + return false; + } + } + + Assert.True(RecursiveEquals(employee, employeeCopy)); + } + + /// + /// Checking IsImmutable property + /// + [Fact] + public static void TestIsImmutable() + { + JsonElement employee = Mailbox.RetrieveMutableEmployeeData(); + Assert.False(employee.IsImmutable); + + if (!employee.IsImmutable) + { + JsonObject employeeNode = JsonNode.GetNode(employee) as JsonObject; + employeeNode["received as node"] = (JsonBoolean)true; + } + + employee = Mailbox.RetrieveImmutableEmployeeData(); + Assert.True(employee.IsImmutable); + } + + /// + /// Retrieving JsonNode from JsonElement + /// + [Fact] + public static void TestTryGetNode() + { + JsonElement employee = Mailbox.RetrieveMutableEmployeeData(); + + static bool CheckIfReceivedAsNode(JsonElement employee) + { + if (JsonNode.TryGetNode(employee, out JsonNode employeeNode)) + { + ((JsonObject)employeeNode)["received as node"] = (JsonBoolean)true; + return true; + } + return false; + } + + Assert.True(CheckIfReceivedAsNode(employee)); + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.cs b/src/System.Text.Json/tests/WritableJsonApiTests.cs index 2b66c6c8acab..e45bff09e714 100644 --- a/src/System.Text.Json/tests/WritableJsonApiTests.cs +++ b/src/System.Text.Json/tests/WritableJsonApiTests.cs @@ -6,107 +6,12 @@ using System.Linq; using Xunit; - namespace System.Text.Json { #pragma warning disable xUnit1000 - internal static class WritableJsonApiTests + internal static partial class WritableJsonApiTests #pragma warning enable xUnit1000 { - /// - /// Helper class simulating external library - /// - private static class EmployeesDatabase - { - private static int s_id = 0; - public static KeyValuePair GetNextEmployee() - { - return new KeyValuePair("employee" + s_id++, new JsonObject()); - } - - public static IEnumerable> GetTenBestEmployees() - { - for (int i = 0; i < 10; i++) - yield return GetNextEmployee(); - } - - /// - /// Returns following JsonObject: - /// { - /// { "name" : "John" } - /// { "phone numbers" : { "work" : "123-456-7890", "home": "123-456-7890" } } - /// { - /// "reporting employees" : - /// { - /// "software developers" : - /// { - /// "full time employees" : /JsonObject of 3 employees fromk database/ - /// "intern employees" : /JsonObject of 2 employees fromk database/ - /// }, - /// "HR" : /JsonObject of 10 employees fromk database/ - /// } - /// - /// - public static JsonObject GetManager() - { - return new JsonObject - { - { "name", "John" }, - { - "phone numbers", new JsonObject() - { - { "work", "123-456-7890" }, { "home", "123-456-7890" } - } - }, - { - "reporting employees", new JsonObject() - { - { - "software developers", new JsonObject() - { - { - "full time employees", new JsonObject() - { - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - } - }, - { - "intern employees", new JsonObject() - { - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - } - } - } - }, - { - "HR", new JsonObject() - { - { - "full time employees", new JsonObject(EmployeesDatabase.GetTenBestEmployees()) - } - } - } - } - } - }; - } - - public static bool CheckSSN(string ssnNumber) => true; - } - - /// - /// Helper class simulating enum - /// - private enum AvailableStateCodes - { - WA, - CA, - NY, - } - /// /// Creating simple Json object /// @@ -120,6 +25,20 @@ public static void TestCreatingJsonObject() { "is developer", true }, { "null property", (JsonNode) null } }; + + Assert.IsType(developer["name"]); + var developerNameCasted = developer["name"] as JsonString; + Assert.Equal("Kasia", developerNameCasted.Value); + + Assert.IsType(developer["age"]); + var developerAgeCasted = developer["age"] as JsonNumber; + Assert.Equal(22, developerAgeCasted.GetInt32()); + + Assert.IsType(developer["is developer"]); + var isDeveloperCasted = developer["is developer"] as JsonBoolean; + Assert.Equal(true, isDeveloperCasted.Value); + + Assert.Null(developer["null property"]); } /// @@ -134,6 +53,18 @@ public static void TestCreatingJsonObjectNewMethods() { "age", new JsonNumber(22) }, { "is developer", new JsonBoolean(true) } }; + + Assert.IsType(developer["name"]); + var developerNameCasted = developer["name"] as JsonString; + Assert.Equal("Kasia", developerNameCasted.Value); + + Assert.IsType(developer["age"]); + var developerAgeCasted = developer["age"] as JsonNumber; + Assert.Equal(22, developerAgeCasted.GetInt32()); + + Assert.IsType(developer["is developer"]); + var isDeveloperCasted = developer["is developer"] as JsonBoolean; + Assert.Equal(true, isDeveloperCasted.Value); } /// @@ -150,11 +81,27 @@ public static void TestNumerics() { "area", PI } }; - JsonNumber bigConstantBoxed = Int64.MaxValue; + Assert.IsType(circle["radius"]); + var radius = circle["radius"] as JsonNumber; + Assert.Equal(radius, 1); + + Assert.IsType(circle["length"]); + var length = circle["length"] as JsonNumber; + Assert.Equal(length, 2 * PI); + + Assert.IsType(circle["area"]); + var area = circle["area"] as JsonNumber; + Assert.Equal(area, PI); + + JsonNumber bigConstantBoxed = long.MaxValue; long bigConstant = bigConstantBoxed.GetInt64(); + Assert.Equal(long.MaxValue, bigConstant); + var smallValueBoxed = new JsonNumber(17); smallValueBoxed.TryGetInt16(out short smallValue); + + Assert.Equal(17, smallValue); } /// @@ -199,6 +146,16 @@ public static void TestCreatingNestedJsonObject() } } }; + + Assert.IsType(person["phone numbers"]); + var phoneNumbers = person["phone numbers"] as JsonObject; + Assert.IsType(phoneNumbers["work"]); + Assert.IsType(phoneNumbers["home"]); + + Assert.IsType(person["addresses"]); + var addresses = person["office"] as JsonObject; + Assert.IsType(addresses["office"]); + Assert.IsType(addresses["home"]); } /// @@ -208,6 +165,7 @@ public static void TestCreatingNestedJsonObject() public static void TestAssignmentDefinition() { JsonNode employee = EmployeesDatabase.GetNextEmployee().Value; + Assert.IsType(employee); } /// @@ -223,6 +181,15 @@ public static void TestAddingKeyValuePair() EmployeesDatabase.GetNextEmployee(), EmployeesDatabase.GetNextEmployee(), }; + + string prevId = ""; + foreach((string id, JsonNode employee) in employees) + { + Assert.NotEqual(prevId, id); + prevId = id; + + Assert.IsType(employee); + } } /// @@ -236,6 +203,15 @@ public static void TestAddingKeyValuePairAfterInitialization() { employees.Add(employee); } + + string prevId = ""; + foreach ((string id, JsonNode employee) in employees) + { + Assert.NotEqual(prevId, id); + prevId = id; + + Assert.IsType(employee); + } } /// @@ -245,6 +221,15 @@ public static void TestAddingKeyValuePairAfterInitialization() public static void TestAddingKeyValuePairsCollection() { var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); + + string prevId = ""; + foreach ((string id, JsonNode employee) in employees) + { + Assert.NotEqual(prevId, id); + prevId = id; + + Assert.IsType(employee); + } } /// @@ -255,16 +240,94 @@ public static void TestAddingKeyValuePairsCollectionAfterInitialization() { var employees = new JsonObject(); employees.AddRange(EmployeesDatabase.GetTenBestEmployees()); + + string prevId = ""; + foreach ((string id, JsonNode employee) in employees) + { + Assert.NotEqual(prevId, id); + prevId = id; + + Assert.IsType(employee); + } + } + + /// + /// Adding JsonArray to JsonObject by creating it in initializing collection + /// + [Fact] + public static void TestAddingJsonArray() + { + var preferences = new JsonObject() + { + { "colours", new JsonArray{ "red", "green", "purple" } } + }; + + Assert.IsType(preferences["colours"]); + var colours = preferences["colours"] as JsonArray; + Assert.Equal(3, colours.Count); + + string[] expected = { "red", "green", "blue" }; + + for (int i = 0; i < colours.Count; i++) + { + Assert.IsType(colours[i]); + Assert.Equal(expected[i], colours[i] as JsonString); + } } /// - /// Creating Json array + /// Adding JsonArray to JsonObject by creating it from string array /// [Fact] - public static void TestCreatingJsonArray() + public static void TestCretingJsonArrayFromStringArray() { - string[] dishes = { "sushi", "pasta", "cucumber soup" }; + string[] expected = { "sushi", "pasta", "cucumber soup" }; + var preferences = new JsonObject() + { + { "dishes", new JsonArray(expected) } + }; + Assert.IsType(preferences["dishes"]); + var dishesJson = preferences["dishes"] as JsonArray; + Assert.Equal(3, dishesJson.Count); + + for (int i = 0; i < dishesJson.Count; i++) + { + Assert.IsType(dishesJson[i]); + Assert.Equal(expected[i], dishesJson[i] as JsonString); + } + } + + /// + /// Adding JsonArray to JsonObject by passing JsonNumber array + /// + [Fact] + public static void TestAddingJsonArrayFromJsonNumberArray() + { + var preferences = new JsonObject() + { + { "prime numbers", new JsonNumber[] { 19, 37 } } + }; + + Assert.IsType(preferences["prime numbers"]); + var primeNumbers = preferences["prime numbers"] as JsonArray; + Assert.Equal(2, primeNumbers.Count); + + int[] expected = { 19, 37 }; + + for (int i = 0; i < primeNumbers.Count; i++) + { + Assert.IsType(primeNumbers[i]); + Assert.Equal(expected[i], primeNumbers[i] as JsonNumber); + } + } + + /// + /// Adding JsonArray to JsonObject by passing IEnumerable of strings + /// + [Fact] + public static void TestAddingJsonArrayFromIEnumerableOfStrings() + { var sportsExperienceYears = new JsonObject() { { "skiing", 5 }, @@ -277,6 +340,28 @@ public static void TestCreatingJsonArray() // choose only sports with > 2 experience years IEnumerable sports = sportsExperienceYears.Where(sport => ((JsonNumber)sport.Value).GetInt32() > 2).Select(sport => sport.Key); + var preferences = new JsonObject() + { + { "sports", new JsonArray(sports) } + }; + + Assert.IsType(preferences["sports"]); + var sportsJsonArray = preferences["sports"] as JsonArray; + Assert.Equal(3, sportsJsonArray.Count); + + for (int i = 0; i < sportsJsonArray.Count; i++) + { + Assert.IsType(sportsJsonArray[i]); + Assert.Equal(sports.ElementAt(i), sportsJsonArray[i] as JsonString); + } + } + + /// + /// Adding JsonArray to JsonObject by passing IEnumerable of JsonNodes + /// + [Fact] + public static void TestAddingJsonArrayFromIEnumerableOfJsonNodes() + { var strangeWords = new JsonArray() { "supercalifragilisticexpialidocious", @@ -287,14 +372,20 @@ public static void TestCreatingJsonArray() var preferences = new JsonObject() { - { "colours", new JsonArray { "red", "green", "purple" } }, - { "numbers", new JsonArray { 4, 123, 88 } }, - { "prime numbers", new JsonNumber[] { 19, 37 } }, - { "varia", new JsonArray { 17, "green", true } }, - { "dishes", new JsonArray(dishes) }, - { "sports", new JsonArray(sports) }, - { "strange words", strangeWords.Where(word => ((JsonString)word).Value.Length < 10) }, + { "strange words", strangeWords.Where(word => ((JsonString)word).Value.Length < 10) } }; + + Assert.IsType(preferences["strange words"]); + var strangeWordsJsonArray = preferences["strange words"] as JsonArray; + Assert.Equal(2, strangeWordsJsonArray.Count); + + string [] expected = { "gladiolus", "albumen" }; + + for (int i = 0; i < strangeWordsJsonArray.Count; i++) + { + Assert.IsType(strangeWordsJsonArray[i]); + Assert.Equal(expected[i], strangeWordsJsonArray[i] as JsonString); + } } /// @@ -332,22 +423,15 @@ public static void TestCreatingNestedJsonArray() } }, }; - } - - /// - /// Adding values to JsonArray - /// - [Fact] - public static void TestAddingToJsonArray() - { - var employeesIds = new JsonArray(); - foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) - { - employeesIds.Add(employee.Key); - } + Assert.IsType(vertices[0]); + var innerJsonArray = vertices[0] as JsonArray; + Assert.IsType(innerJsonArray[0]); + innerJsonArray = innerJsonArray[0] as JsonArray; + Assert.IsType(innerJsonArray[0]); } + /// /// Creating Json array from collection /// @@ -355,6 +439,15 @@ public static void TestAddingToJsonArray() public static void TestCreatingJsonArrayFromCollection() { var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => new JsonString(employee.Key))); + + JsonString prevId = new JsonString(); + foreach (JsonNode employeeId in employeesIds) + { + Assert.IsType(employeeId); + var employeeIdString = employeeId as JsonString; + Assert.NotEqual(prevId, employeeIdString); + prevId = employeeIdString; + } } /// @@ -364,6 +457,15 @@ public static void TestCreatingJsonArrayFromCollection() public static void TestCreatingJsonArrayFromCollectionOfString() { var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => employee.Key)); + + JsonString prevId = new JsonString(); + foreach (JsonNode employeeId in employeesIds) + { + Assert.IsType(employeeId); + var employeeIdString = employeeId as JsonString; + Assert.NotEqual(prevId, employeeIdString); + prevId = employeeIdString; + } } /// @@ -383,6 +485,11 @@ public static void TestContains() EmployeesDatabase.CheckSSN(((JsonString)person["ssn"]).Value); } + Assert.True(person.ContainsProperty("ssn")); + Assert.False(person.ContainsProperty("surname")); + + // Different scenario: + var enabledOptions = new JsonArray { "readonly", @@ -408,197 +515,6 @@ public static void TestContains() } } - /// - /// Replacing Json object's primnary types - /// - [Fact] - public static void TestReplacingsonObjectPrimaryTypes() - { - var person1 = new JsonObject - { - { "name", "John" }, - { "age", 45 }, - { "is_married", true } - }; - - // Assign by creating a new instance of primary Json type - person1["name"] = new JsonString("Bob"); - - // Assign by using an implicit operator on primary Json type - JsonNumber newAge = 55; - person1["age"] = newAge; - - // Assign by explicit cast from Json primary type - person1["is_married"] = (JsonBoolean)true; - - // Not possible scenario (wold require implicit cast operators in JsonNode): - // person["name"] = "Bob"; - - var person2 = new JsonObject - { - { "name", new JsonString[]{ "Emily", "Rosalie" } }, - { "age", 33 }, - { "is_married", true } - }; - - // Copy property from another JsonObject - person1["age"] = person2["age"]; - - // Copy property of different typoe - person1["name"] = person2["name"]; - } - - /// - /// Modifying Json object's primnary types - /// - [Fact] - public static void TestModifyingJsonObjectPrimaryTypes() - { - JsonString name = "previous name"; - name.Value = "new name"; - - bool shouldBeEnabled = true; - var isEnabled = new JsonBoolean(false); - isEnabled.Value = shouldBeEnabled; - - JsonNumber veryBigConstant = new JsonNumber(); - veryBigConstant.SetString("1e1000"); - string bigNumber = veryBigConstant.GetString(); - veryBigConstant.SetInt16(123); - short smallNumber = veryBigConstant.GetInt16(); - } - - /// - /// Accesing nested Json object - casting with as operator - /// - [Fact] - public static void TestAccesingNestedJsonObjectCastWithAs() - { - // Casting with as operator - JsonObject manager = EmployeesDatabase.GetManager(); - - var reportingEmployees = manager["reporting employees"] as JsonObject; - if (reportingEmployees == null) - throw new InvalidCastException(); - - var softwareDevelopers = reportingEmployees["software developers"] as JsonObject; - if (softwareDevelopers == null) - throw new InvalidCastException(); - - var internDevelopers = softwareDevelopers["intern employees"] as JsonObject; - if (internDevelopers == null) - throw new InvalidCastException(); - - internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - casting with is operator - /// - [Fact] - public static void TestAccesingNestedJsonObjectCastWithIs() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - if (manager["reporting employees"] is JsonObject reportingEmployees) - { - if (reportingEmployees["software developers"] is JsonObject softwareDevelopers) - { - if (softwareDevelopers["full time employees"] is JsonObject fullTimeEmployees) - { - fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); - } - } - } - } - - /// - /// Accesing nested Json object - explicit casting - /// - [Fact] - public static void TestAccesingNestedJsonObjectExplicitCast() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - ((JsonObject)((JsonObject)manager["reporting employees"])["HR"]).Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - GetObjectProperty method - /// - [Fact] - public static void TestAccesingNestedJsonObjectGetPropertyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - JsonObject internDevelopers = manager.GetObjectProperty("reporting employees") - .GetObjectProperty("software developers") - .GetObjectProperty("intern employees"); - internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - TryGetObjectProperty method - /// - [Fact] - public static void TestAccesingNestedJsonObjectTryGetPropertyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - if (manager.TryGetObjectProperty("reporting employees", out JsonObject reportingEmployees)) - { - if (reportingEmployees.TryGetObjectProperty("software developers", out JsonObject softwareDevelopers)) - { - if (softwareDevelopers.TryGetObjectProperty("full time employees", out JsonObject fullTimeEmployees)) - { - fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); - } - } - } - } - - /// - /// Accesing nested Json array - GetArrayProperty method - /// - [Fact] - public static void TestAccesingNestedJsonArrayGetPropertyMethod() - { - var issues = new JsonObject() - { - { "features", new JsonArray{ "new functionality 1", "new functionality 2" } }, - { "bugs", new JsonArray{ "bug 123", "bug 4566", "bug 821" } }, - { "tests", new JsonArray{ "code coverage" } }, - }; - - issues.GetArrayProperty("bugs").Add("bug 12356"); - ((JsonString)issues.GetArrayProperty("features")[0]).Value = "feature 1569"; - ((JsonString)issues.GetArrayProperty("features")[1]).Value = "feature 56134"; - } - - /// - /// Modifying Json object key - remove and add - /// - [Fact] - public static void TestModifyingJsonObjectKeyRemoveAdd() - { - JsonObject manager = EmployeesDatabase.GetManager(); - JsonObject reportingEmployees = manager.GetObjectProperty("reporting employees"); - - JsonNode softwareDevelopers = reportingEmployees["software developers"]; - reportingEmployees.Remove("software developers"); - reportingEmployees.Add("software engineers", softwareDevelopers); - } - - /// - /// Modifying Json object key - modify method - /// - [Fact] - public static void TestModifyingJsonObjectKeyModifyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - JsonObject reportingEmployees = manager.GetObjectProperty("reporting employees"); - - reportingEmployees.ModifyPropertyName("software developers", "software engineers"); - } - /// /// Aquiring all values /// @@ -607,6 +523,11 @@ public static void TestAquiringAllValues() { var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); ICollection employeesWithoutId = employees.Values; + + foreach(JsonNode employee in employeesWithoutId) + { + Assert.IsType(employee); + } } /// @@ -624,6 +545,11 @@ public static void TestAquiringAllProperties() }; IEnumerable fullTimeEmployees = employees.GetAllProperties("FTE"); + + Assert.Equal(3, fullTimeEmployees.Count()); + Assert.True(fullTimeEmployees.Contains((JsonString)"John Smith")); + Assert.True(fullTimeEmployees.Contains((JsonString)"Ann Predictable")); + Assert.True(fullTimeEmployees.Contains((JsonString)"Byron Shadow")); } } } From 6cd2efbdf4997c811b593b466a94edffaba19d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katarzyna=20Bu=C5=82at?= Date: Wed, 17 Jul 2019 13:19:54 -0700 Subject: [PATCH 03/30] Json prototype (#1) Basic API for Json writable DOM with scenarios including collection initialization, accessing and modifying Json nodes. --- src/System.Text.Json/ref/System.Text.Json.cs | 224 +++++++ .../src/System.Text.Json.csproj | 6 + .../src/System/Text/Json/Node/JsonArray.cs | 104 +++ .../src/System/Text/Json/Node/JsonBoolean.cs | 24 + .../src/System/Text/Json/Node/JsonNode.cs | 16 + .../src/System/Text/Json/Node/JsonNumber.cs | 96 +++ .../src/System/Text/Json/Node/JsonObject.cs | 64 ++ .../src/System/Text/Json/Node/JsonString.cs | 24 + .../tests/System.Text.Json.Tests.csproj | 3 +- .../tests/WritableJsonApiTests.cs | 629 ++++++++++++++++++ 10 files changed, 1188 insertions(+), 2 deletions(-) create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs create mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.cs diff --git a/src/System.Text.Json/ref/System.Text.Json.cs b/src/System.Text.Json/ref/System.Text.Json.cs index c9560f4e005e..a1db0fc81651 100644 --- a/src/System.Text.Json/ref/System.Text.Json.cs +++ b/src/System.Text.Json/ref/System.Text.Json.cs @@ -7,6 +7,97 @@ namespace System.Text.Json { + public partial class JsonArray : System.Text.Json.JsonNode, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable + { + public JsonArray() { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + [System.CLSCompliantAttribute(false)] + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } + [System.CLSCompliantAttribute(false)] + public JsonArray(System.Collections.Generic.IEnumerable values) { } + [System.CLSCompliantAttribute(false)] + public JsonArray(System.Collections.Generic.IEnumerable values) { } + [System.CLSCompliantAttribute(false)] + public JsonArray(System.Collections.Generic.IEnumerable values) { } + public int Count { get { throw null; } } + public bool IsReadOnly { get { throw null; } } + public System.Text.Json.JsonNode this[int idx] { get { throw null; } set { } } + public void Add(bool value) { } + public void Add(byte value) { } + public void Add(double value) { } + public void Add(short value) { } + public void Add(int value) { } + public void Add(long value) { } + [System.CLSCompliantAttribute(false)] + public void Add(sbyte value) { } + public void Add(float value) { } + public void Add(string value) { } + public void Add(System.Text.Json.JsonNode value) { } + [System.CLSCompliantAttribute(false)] + public void Add(ushort value) { } + [System.CLSCompliantAttribute(false)] + public void Add(uint value) { } + [System.CLSCompliantAttribute(false)] + public void Add(ulong value) { } + public void Clear() { } + public bool Contains(bool value) { throw null; } + public bool Contains(byte value) { throw null; } + public bool Contains(double value) { throw null; } + public bool Contains(short value) { throw null; } + public bool Contains(int value) { throw null; } + public bool Contains(long value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool Contains(sbyte value) { throw null; } + public bool Contains(float value) { throw null; } + public bool Contains(string value) { throw null; } + public bool Contains(System.Text.Json.JsonNode value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool Contains(ushort value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool Contains(uint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool Contains(ulong value) { throw null; } + public System.Collections.Generic.IEnumerator GetEnumerator() { throw null; } + public int IndexOf(System.Text.Json.JsonNode item) { throw null; } + public void Insert(int index, bool item) { } + public void Insert(int index, byte item) { } + public void Insert(int index, double item) { } + public void Insert(int index, short item) { } + public void Insert(int index, int item) { } + public void Insert(int index, long item) { } + [System.CLSCompliantAttribute(false)] + public void Insert(int index, sbyte item) { } + public void Insert(int index, float item) { } + public void Insert(int index, string item) { } + public void Insert(int index, System.Text.Json.JsonNode item) { } + [System.CLSCompliantAttribute(false)] + public void Insert(int index, ushort item) { } + [System.CLSCompliantAttribute(false)] + public void Insert(int index, uint item) { } + [System.CLSCompliantAttribute(false)] + public void Insert(int index, ulong item) { } + public bool Remove(System.Text.Json.JsonNode item) { throw null; } + public void RemoveAt(int index) { } + void System.Collections.Generic.ICollection.CopyTo(System.Text.Json.JsonNode[] array, int arrayIndex) { } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } + } + public partial class JsonBoolean : System.Text.Json.JsonNode + { + public JsonBoolean() { } + public JsonBoolean(bool value) { } + public bool Value { get { throw null; } set { } } + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + public static implicit operator System.Text.Json.JsonBoolean (bool value) { throw null; } + } public enum JsonCommentHandling : byte { Disallow = (byte)0, @@ -156,6 +247,130 @@ protected JsonNamingPolicy() { } public static System.Text.Json.JsonNamingPolicy CamelCase { get { throw null; } } public abstract string ConvertName(string name); } + public partial class JsonNode + { + public JsonNode() { } + } + public partial class JsonNumber : System.Text.Json.JsonNode + { + public JsonNumber() { } + public JsonNumber(byte value) { } + public JsonNumber(double value) { } + public JsonNumber(short value) { } + public JsonNumber(int value) { } + public JsonNumber(long value) { } + [System.CLSCompliantAttribute(false)] + public JsonNumber(sbyte value) { } + public JsonNumber(float value) { } + public JsonNumber(string value) { } + [System.CLSCompliantAttribute(false)] + public JsonNumber(ushort value) { } + [System.CLSCompliantAttribute(false)] + public JsonNumber(uint value) { } + [System.CLSCompliantAttribute(false)] + public JsonNumber(ulong value) { } + public override bool Equals(object obj) { throw null; } + public byte GetByte() { throw null; } + public double GetDouble() { throw null; } + public override int GetHashCode() { throw null; } + public short GetInt16() { throw null; } + public int GetInt32() { throw null; } + public long GetInt64() { throw null; } + [System.CLSCompliantAttribute(false)] + public sbyte GetSByte() { throw null; } + public float GetSingle() { throw null; } + public string GetString() { throw null; } + [System.CLSCompliantAttribute(false)] + public ushort GetUInt16() { throw null; } + [System.CLSCompliantAttribute(false)] + public uint GetUInt32() { throw null; } + [System.CLSCompliantAttribute(false)] + public ulong GetUInt64() { throw null; } + public static implicit operator System.Text.Json.JsonNumber (byte value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (double value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (short value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (int value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (long value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Text.Json.JsonNumber (sbyte value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (float value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Text.Json.JsonNumber (ushort value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Text.Json.JsonNumber (uint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Text.Json.JsonNumber (ulong value) { throw null; } + public void SetByte(byte value) { } + public void SetDouble(double value) { } + public void SetInt16(short value) { } + public void SetInt32(int value) { } + public void SetInt64(long value) { } + [System.CLSCompliantAttribute(false)] + public void SetSByte(sbyte value) { } + public void SetSingle(float value) { } + public void SetString(string value) { } + [System.CLSCompliantAttribute(false)] + public void SetUInt16(ushort value) { } + [System.CLSCompliantAttribute(false)] + public void SetUInt32(uint value) { } + [System.CLSCompliantAttribute(false)] + public void SetUInt64(ulong value) { } + public bool TryGetByte(out byte value) { throw null; } + public bool TryGetDouble(out double value) { throw null; } + public bool TryGetInt16(out short value) { throw null; } + public bool TryGetInt32(out int value) { throw null; } + public bool TryGetInt64(out long value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool TryGetSByte(out sbyte value) { throw null; } + public bool TryGetSingle(out float value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool TryGetUInt16(out ushort value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool TryGetUInt32(out uint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public bool TryGetUInt64(out ulong value) { throw null; } + } + public partial class JsonObject : System.Text.Json.JsonNode, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable + { + public JsonObject() { } + public JsonObject(System.Collections.Generic.IEnumerable> jsonProperties) { } + public System.Text.Json.JsonNode this[string key] { get { throw null; } set { } } + public System.Collections.Generic.ICollection PropertyNames { get { throw null; } } + public System.Collections.Generic.ICollection Values { get { throw null; } } + public void Add(System.Collections.Generic.KeyValuePair jsonProperty) { } + public void Add(string propertyName, bool propertyValue) { } + public void Add(string propertyName, byte propertyValue) { } + public void Add(string propertyName, System.Collections.Generic.IEnumerable propertyValue) { } + public void Add(string propertyName, double propertyValue) { } + public void Add(string propertyName, short propertyValue) { } + public void Add(string propertyName, int propertyValue) { } + public void Add(string propertyName, long propertyValue) { } + [System.CLSCompliantAttribute(false)] + public void Add(string propertyName, sbyte propertyValue) { } + public void Add(string propertyName, float propertyValue) { } + public void Add(string propertyName, string propertyValue) { } + public void Add(string propertyName, System.Text.Json.JsonArray propertyValue) { } + public void Add(string propertyName, System.Text.Json.JsonNode propertyValue) { } + [System.CLSCompliantAttribute(false)] + public void Add(string propertyName, ushort propertyValue) { } + [System.CLSCompliantAttribute(false)] + public void Add(string propertyName, uint propertyValue) { } + [System.CLSCompliantAttribute(false)] + public void Add(string propertyName, ulong propertyValue) { } + public void AddRange(System.Collections.Generic.IEnumerable> jsonProperties) { } + public bool ContainsProperty(string propertyName) { throw null; } + public System.Collections.Generic.IEnumerable GetAllProperties(string propertyName) { throw null; } + public System.Text.Json.JsonArray GetArrayProperty(string propertyName) { throw null; } + public System.Collections.Generic.IEnumerator> GetEnumerator() { throw null; } + public System.Text.Json.JsonObject GetObjectProperty(string propertyName) { throw null; } + public System.Text.Json.JsonNode GetProperty(string propertyName) { throw null; } + public bool ModifyPropertyName(string oldName, string newName) { throw null; } + public bool Remove(string propertyName) { throw null; } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } + public bool TryGetArrayProperty(string propertyName, out System.Text.Json.JsonArray jsonArray) { throw null; } + public bool TryGetObjectProperty(string propertyName, out System.Text.Json.JsonObject jsonObject) { throw null; } + public bool TryGetProperty(string propertyName, out System.Text.Json.JsonNode jsonNode) { throw null; } + } public readonly partial struct JsonProperty { private readonly object _dummy; @@ -217,6 +432,15 @@ public JsonSerializerOptions() { } public bool WriteIndented { get { throw null; } set { } } public System.Text.Json.Serialization.JsonConverter GetConverter(System.Type typeToConvert) { throw null; } } + public partial class JsonString : System.Text.Json.JsonNode + { + public JsonString() { } + public JsonString(string value) { } + public string Value { get { throw null; } set { } } + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + public static implicit operator System.Text.Json.JsonString (string value) { throw null; } + } public enum JsonTokenType : byte { None = (byte)0, diff --git a/src/System.Text.Json/src/System.Text.Json.csproj b/src/System.Text.Json/src/System.Text.Json.csproj index 8d2f4ddc7fb4..c7a1c9fceba6 100644 --- a/src/System.Text.Json/src/System.Text.Json.csproj +++ b/src/System.Text.Json/src/System.Text.Json.csproj @@ -22,7 +22,13 @@ + + + + + + diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs new file mode 100644 index 000000000000..5f5f14cb1789 --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs @@ -0,0 +1,104 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonArray : JsonNode, IList, IReadOnlyList + { + public JsonArray() { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } + [CLSCompliant(false)] + public JsonArray(IEnumerable values) { } + [CLSCompliant(false)] + public JsonArray(IEnumerable values) { } + [CLSCompliant(false)] + public JsonArray(IEnumerable values) { } + [CLSCompliant(false)] + public JsonArray(IEnumerable values) { } + + public JsonNode this[int idx] { get => throw null; set => throw null; } + + public void Add(JsonNode value) { } + public void Add(string value) { } + public void Add(bool value) { } + public void Add(byte value) { } + public void Add(short value) { } + public void Add(int value) { } + public void Add(long value) { } + public void Add(float value) { } + public void Add(double value) { } + [CLSCompliant(false)] + public void Add(sbyte value) { } + [CLSCompliant(false)] + public void Add(ushort value) { } + [CLSCompliant(false)] + public void Add(uint value) { } + [CLSCompliant(false)] + public void Add(ulong value) { } + + public void Insert(int index, JsonNode item) { throw null; } + public void Insert(int index, string item) { throw null; } + public void Insert(int index, bool item) { throw null; } + public void Insert(int index, byte item) { throw null; } + public void Insert(int index, short item) { throw null; } + public void Insert(int index, int item) { throw null; } + public void Insert(int index, long item) { throw null; } + public void Insert(int index, float item) { throw null; } + public void Insert(int index, double item) { throw null; } + [CLSCompliant(false)] + public void Insert(int index, sbyte item) { throw null; } + [CLSCompliant(false)] + public void Insert(int index, ushort item) { throw null; } + [CLSCompliant(false)] + public void Insert(int index, uint item) { throw null; } + [CLSCompliant(false)] + public void Insert(int index, ulong item) { throw null; } + + public bool Contains(JsonNode value) { throw null; } + public bool Contains(string value) { throw null; } + public bool Contains(bool value) { throw null; } + public bool Contains(byte value) { throw null; } + public bool Contains(short value) { throw null; } + public bool Contains(int value) { throw null; } + public bool Contains(long value) { throw null; } + public bool Contains(float value) { throw null; } + public bool Contains(double value) { throw null; } + [CLSCompliant(false)] + public bool Contains(sbyte value) { throw null; } + [CLSCompliant(false)] + public bool Contains(ushort value) { throw null; } + [CLSCompliant(false)] + public bool Contains(uint value) { throw null; } + [CLSCompliant(false)] + public bool Contains(ulong value) { throw null; } + + public int Count => throw new NotImplementedException(); + public bool IsReadOnly => throw new NotImplementedException(); + + public int IndexOf(JsonNode item) { throw null; } + public void RemoveAt(int index) { throw null; } + public void Clear() { throw null; } + public bool Remove(JsonNode item) { throw null; } + + void ICollection.CopyTo(JsonNode[] array, int arrayIndex) { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public IEnumerator GetEnumerator() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs new file mode 100644 index 000000000000..c18f85b01b32 --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonBoolean : JsonNode + { + public JsonBoolean() { } + public JsonBoolean(bool value) { } + + public bool Value { get; set; } + + public static implicit operator JsonBoolean(bool value) { throw null; } + + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs new file mode 100644 index 000000000000..7dd0d7206f19 --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonNode + { + + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs new file mode 100644 index 000000000000..7a9fd6337015 --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -0,0 +1,96 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonNumber : JsonNode + { + public JsonNumber() { } + public JsonNumber(string value) { } + public JsonNumber(byte value) { } + public JsonNumber(short value) { } + public JsonNumber(int value) { } + public JsonNumber(long value) { } + public JsonNumber(float value) { } + public JsonNumber(double value) { } + [CLSCompliant(false)] + public JsonNumber(sbyte value) { } + [CLSCompliant(false)] + public JsonNumber(ushort value) { } + [CLSCompliant(false)] + public JsonNumber(uint value) { } + [CLSCompliant(false)] + public JsonNumber(ulong value) { } + + public string GetString() { throw null; } + public byte GetByte() { throw null; } + public int GetInt32() { throw null; } + public short GetInt16() { throw null; } + public long GetInt64() { throw null; } + public float GetSingle() { throw null; } + public double GetDouble() { throw null; } + [CLSCompliant(false)] + public sbyte GetSByte() { throw null; } + [CLSCompliant(false)] + public ushort GetUInt16() { throw null; } + [CLSCompliant(false)] + public uint GetUInt32() { throw null; } + [CLSCompliant(false)] + public ulong GetUInt64() { throw null; } + + public bool TryGetByte(out byte value) { throw null; } + public bool TryGetInt32(out int value) { throw null; } + public bool TryGetInt16(out short value) { throw null; } + public bool TryGetInt64(out long value) { throw null; } + public bool TryGetSingle(out float value) { throw null; } + public bool TryGetDouble(out double value) { throw null; } + [CLSCompliant(false)] + public bool TryGetSByte(out sbyte value) { throw null; } + [CLSCompliant(false)] + public bool TryGetUInt16(out ushort value) { throw null; } + [CLSCompliant(false)] + public bool TryGetUInt32(out uint value) { throw null; } + [CLSCompliant(false)] + public bool TryGetUInt64(out ulong value) { throw null; } + + public void SetString(string value) { } + public void SetByte(byte value) { } + public void SetInt32(int value) { } + public void SetInt16(short value) { } + public void SetInt64(long value) { } + public void SetSingle(float value) { } + public void SetDouble(double value) { } + [CLSCompliant(false)] + public void SetSByte(sbyte value) { } + [CLSCompliant(false)] + public void SetUInt16(ushort value) { } + [CLSCompliant(false)] + public void SetUInt32(uint value) { } + [CLSCompliant(false)] + public void SetUInt64(ulong value) { } + + public static implicit operator JsonNumber(byte value) { throw null; } + public static implicit operator JsonNumber(int value) { throw null; } + public static implicit operator JsonNumber(short value) { throw null; } + public static implicit operator JsonNumber(long value) { throw null; } + public static implicit operator JsonNumber(float value) { throw null; } + public static implicit operator JsonNumber(double value) { throw null; } + [CLSCompliant(false)] + public static implicit operator JsonNumber(sbyte value) { throw null; } + [CLSCompliant(false)] + public static implicit operator JsonNumber(ushort value) { throw null; } + [CLSCompliant(false)] + public static implicit operator JsonNumber(uint value) { throw null; } + [CLSCompliant(false)] + public static implicit operator JsonNumber(ulong value) { throw null; } + + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs new file mode 100644 index 000000000000..c9a083f3a2da --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonObject : JsonNode, IEnumerable> + { + public JsonObject() { } + public JsonObject(IEnumerable> jsonProperties) { } + + public JsonNode this[string key] { get => throw null; set => throw null; } + public IEnumerator> GetEnumerator() { throw null; } + + public void Add(KeyValuePair jsonProperty) { } + public void Add(string propertyName, JsonArray propertyValue) { } + public void Add(string propertyName, JsonNode propertyValue) { } + public void Add(string propertyName, string propertyValue) { } + public void Add(string propertyName, bool propertyValue) { } + public void Add(string propertyName, byte propertyValue) { } + public void Add(string propertyName, short propertyValue) { } + public void Add(string propertyName, int propertyValue) { } + public void Add(string propertyName, long propertyValue) { } + public void Add(string propertyName, float propertyValue) { } + public void Add(string propertyName, double propertyValue) { } + [CLSCompliant(false)] + public void Add(string propertyName, sbyte propertyValue) { } + [CLSCompliant(false)] + public void Add(string propertyName, ushort propertyValue) { } + [CLSCompliant(false)] + public void Add(string propertyName, uint propertyValue) { } + [CLSCompliant(false)] + public void Add(string propertyName, ulong propertyValue) { } + public void Add(string propertyName, IEnumerable propertyValue) { } + public void AddRange(IEnumerable> jsonProperties) { } + + public bool Remove(string propertyName) { throw null; } + public bool ContainsProperty(string propertyName) { throw null; } + + public bool ModifyPropertyName(string oldName, string newName) { throw null; } + + public JsonNode GetProperty(string propertyName) { throw null; } + public bool TryGetProperty(string propertyName, out JsonNode jsonNode) { throw null; } + public JsonObject GetObjectProperty(string propertyName) { throw null; } + public bool TryGetObjectProperty(string propertyName, out JsonObject jsonObject) { throw null; } + public JsonArray GetArrayProperty(string propertyName) { throw null; } + public bool TryGetArrayProperty(string propertyName, out JsonArray jsonArray) { throw null; } + public IEnumerable GetAllProperties(string propertyName) { throw null; } + + + public ICollection PropertyNames => throw null; + public ICollection Values => throw null; + + IEnumerator IEnumerable.GetEnumerator() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs new file mode 100644 index 000000000000..9c993375209c --- /dev/null +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + +namespace System.Text.Json +{ + public partial class JsonString : JsonNode + { + public JsonString() { } + public JsonString(string value) { } + + public string Value { get; set; } + + public static implicit operator JsonString(string value) { throw null; } + + public override bool Equals(object obj) { throw null; } + public override int GetHashCode() { throw null; } + } +} + +#pragma warning restore CS1591 diff --git a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj index c60ca78db8fe..fabe09e30d71 100644 --- a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -101,9 +101,8 @@ - - + diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.cs b/src/System.Text.Json/tests/WritableJsonApiTests.cs new file mode 100644 index 000000000000..2b66c6c8acab --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.cs @@ -0,0 +1,629 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Helper class simulating external library + /// + private static class EmployeesDatabase + { + private static int s_id = 0; + public static KeyValuePair GetNextEmployee() + { + return new KeyValuePair("employee" + s_id++, new JsonObject()); + } + + public static IEnumerable> GetTenBestEmployees() + { + for (int i = 0; i < 10; i++) + yield return GetNextEmployee(); + } + + /// + /// Returns following JsonObject: + /// { + /// { "name" : "John" } + /// { "phone numbers" : { "work" : "123-456-7890", "home": "123-456-7890" } } + /// { + /// "reporting employees" : + /// { + /// "software developers" : + /// { + /// "full time employees" : /JsonObject of 3 employees fromk database/ + /// "intern employees" : /JsonObject of 2 employees fromk database/ + /// }, + /// "HR" : /JsonObject of 10 employees fromk database/ + /// } + /// + /// + public static JsonObject GetManager() + { + return new JsonObject + { + { "name", "John" }, + { + "phone numbers", new JsonObject() + { + { "work", "123-456-7890" }, { "home", "123-456-7890" } + } + }, + { + "reporting employees", new JsonObject() + { + { + "software developers", new JsonObject() + { + { + "full time employees", new JsonObject() + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + } + }, + { + "intern employees", new JsonObject() + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + } + } + } + }, + { + "HR", new JsonObject() + { + { + "full time employees", new JsonObject(EmployeesDatabase.GetTenBestEmployees()) + } + } + } + } + } + }; + } + + public static bool CheckSSN(string ssnNumber) => true; + } + + /// + /// Helper class simulating enum + /// + private enum AvailableStateCodes + { + WA, + CA, + NY, + } + + /// + /// Creating simple Json object + /// + [Fact] + public static void TestCreatingJsonObject() + { + var developer = new JsonObject + { + { "name", "Kasia" }, + { "age", 22 }, + { "is developer", true }, + { "null property", (JsonNode) null } + }; + } + + /// + /// Creating simple Json object by new methods on primary types + /// + [Fact] + public static void TestCreatingJsonObjectNewMethods() + { + var developer = new JsonObject + { + { "name", new JsonString("Kasia") }, + { "age", new JsonNumber(22) }, + { "is developer", new JsonBoolean(true) } + }; + } + + /// + /// Creating and retriving different numeric values + /// + [Fact] + public static void TestNumerics() + { + double PI = 3.14159265359; + var circle = new JsonObject + { + { "radius", 1 }, + { "length", 2*PI }, + { "area", PI } + }; + + JsonNumber bigConstantBoxed = Int64.MaxValue; + long bigConstant = bigConstantBoxed.GetInt64(); + + var smallValueBoxed = new JsonNumber(17); + smallValueBoxed.TryGetInt16(out short smallValue); + } + + /// + /// Creating nested Json object + /// + [Fact] + public static void TestCreatingNestedJsonObject() + { + var person = new JsonObject + { + { "name", "John" }, + { "surname", "Smith" }, + { + "phone numbers", new JsonObject() + { + { "work", "123-456-7890" }, + { "home", "123-456-7890" } + } + }, + { + "addresses", new JsonObject() + { + { + "office", new JsonObject() + { + { "address line 1", "One Microsoft Way" }, + { "city" , "Redmond" } , + { "zip code" , 98052 } , + { "state" , (int) AvailableStateCodes.WA } + } + }, + { + "home", new JsonObject() + { + { "address line 1", "Pear Ave" }, + { "address line 2", "1288" }, + { "city" , "Mountain View" } , + { "zip code" , 94043 } , + { "state" , (int) AvailableStateCodes.CA } + } + } + } + } + }; + } + + /// + /// Defining as KeyValuePair value + /// + [Fact] + public static void TestAssignmentDefinition() + { + JsonNode employee = EmployeesDatabase.GetNextEmployee().Value; + } + + /// + /// Adding KeyValuePair from external library + /// + [Fact] + public static void TestAddingKeyValuePair() + { + var employees = new JsonObject + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + }; + } + + /// + /// Adding KeyValuePair from external library after initialization + /// + [Fact] + public static void TestAddingKeyValuePairAfterInitialization() + { + var employees = new JsonObject(); + foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) + { + employees.Add(employee); + } + } + + /// + /// Adding KeyValuePairs collection from external library + /// + [Fact] + public static void TestAddingKeyValuePairsCollection() + { + var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); + } + + /// + /// Adding KeyValuePairs collection from external library after initialization + /// + [Fact] + public static void TestAddingKeyValuePairsCollectionAfterInitialization() + { + var employees = new JsonObject(); + employees.AddRange(EmployeesDatabase.GetTenBestEmployees()); + } + + /// + /// Creating Json array + /// + [Fact] + public static void TestCreatingJsonArray() + { + string[] dishes = { "sushi", "pasta", "cucumber soup" }; + + var sportsExperienceYears = new JsonObject() + { + { "skiing", 5 }, + { "cycling", 8 }, + { "hiking", 6 }, + { "chess", 2 }, + { "skating", 1 }, + }; + + // choose only sports with > 2 experience years + IEnumerable sports = sportsExperienceYears.Where(sport => ((JsonNumber)sport.Value).GetInt32() > 2).Select(sport => sport.Key); + + var strangeWords = new JsonArray() + { + "supercalifragilisticexpialidocious", + "gladiolus", + "albumen", + "smaragdine" + }; + + var preferences = new JsonObject() + { + { "colours", new JsonArray { "red", "green", "purple" } }, + { "numbers", new JsonArray { 4, 123, 88 } }, + { "prime numbers", new JsonNumber[] { 19, 37 } }, + { "varia", new JsonArray { 17, "green", true } }, + { "dishes", new JsonArray(dishes) }, + { "sports", new JsonArray(sports) }, + { "strange words", strangeWords.Where(word => ((JsonString)word).Value.Length < 10) }, + }; + } + + /// + /// Creating nested Json array + /// + [Fact] + public static void TestCreatingNestedJsonArray() + { + var vertices = new JsonArray() + { + new JsonArray + { + new JsonArray + { + new JsonArray { 0, 0, 0 }, + new JsonArray { 0, 0, 1 } + }, + new JsonArray + { + new JsonArray { 0, 1, 0 }, + new JsonArray { 0, 1, 1 } + } + }, + new JsonArray + { + new JsonArray + { + new JsonArray { 1, 0, 0 }, + new JsonArray { 1, 0, 1 } + }, + new JsonArray + { + new JsonArray { 1, 1, 0 }, + new JsonArray { 1, 1, 1 } + } + }, + }; + } + + /// + /// Adding values to JsonArray + /// + [Fact] + public static void TestAddingToJsonArray() + { + var employeesIds = new JsonArray(); + + foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) + { + employeesIds.Add(employee.Key); + } + } + + /// + /// Creating Json array from collection + /// + [Fact] + public static void TestCreatingJsonArrayFromCollection() + { + var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => new JsonString(employee.Key))); + } + + /// + /// Creating Json array from collection of strings + /// + [Fact] + public static void TestCreatingJsonArrayFromCollectionOfString() + { + var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => employee.Key)); + } + + /// + /// Contains checks + /// + [Fact] + public static void TestContains() + { + var person = new JsonObject + { + { "name", "John" }, + { "ssn", "123456789" }, + }; + + if (person.ContainsProperty("ssn")) + { + EmployeesDatabase.CheckSSN(((JsonString)person["ssn"]).Value); + } + + var enabledOptions = new JsonArray + { + "readonly", + "no cache", + "continue on failure" + }; + + if (enabledOptions.Contains("no cache")) + { + // do sth without using caching + } + + var requiredOptions = new JsonArray + { + "readonly", + "continue on failure" + }; + + // if all required options are enabled + if (!requiredOptions.Select(option => !enabledOptions.Contains(option)).Any()) + { + // do sth without using caching + } + } + + /// + /// Replacing Json object's primnary types + /// + [Fact] + public static void TestReplacingsonObjectPrimaryTypes() + { + var person1 = new JsonObject + { + { "name", "John" }, + { "age", 45 }, + { "is_married", true } + }; + + // Assign by creating a new instance of primary Json type + person1["name"] = new JsonString("Bob"); + + // Assign by using an implicit operator on primary Json type + JsonNumber newAge = 55; + person1["age"] = newAge; + + // Assign by explicit cast from Json primary type + person1["is_married"] = (JsonBoolean)true; + + // Not possible scenario (wold require implicit cast operators in JsonNode): + // person["name"] = "Bob"; + + var person2 = new JsonObject + { + { "name", new JsonString[]{ "Emily", "Rosalie" } }, + { "age", 33 }, + { "is_married", true } + }; + + // Copy property from another JsonObject + person1["age"] = person2["age"]; + + // Copy property of different typoe + person1["name"] = person2["name"]; + } + + /// + /// Modifying Json object's primnary types + /// + [Fact] + public static void TestModifyingJsonObjectPrimaryTypes() + { + JsonString name = "previous name"; + name.Value = "new name"; + + bool shouldBeEnabled = true; + var isEnabled = new JsonBoolean(false); + isEnabled.Value = shouldBeEnabled; + + JsonNumber veryBigConstant = new JsonNumber(); + veryBigConstant.SetString("1e1000"); + string bigNumber = veryBigConstant.GetString(); + veryBigConstant.SetInt16(123); + short smallNumber = veryBigConstant.GetInt16(); + } + + /// + /// Accesing nested Json object - casting with as operator + /// + [Fact] + public static void TestAccesingNestedJsonObjectCastWithAs() + { + // Casting with as operator + JsonObject manager = EmployeesDatabase.GetManager(); + + var reportingEmployees = manager["reporting employees"] as JsonObject; + if (reportingEmployees == null) + throw new InvalidCastException(); + + var softwareDevelopers = reportingEmployees["software developers"] as JsonObject; + if (softwareDevelopers == null) + throw new InvalidCastException(); + + var internDevelopers = softwareDevelopers["intern employees"] as JsonObject; + if (internDevelopers == null) + throw new InvalidCastException(); + + internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - casting with is operator + /// + [Fact] + public static void TestAccesingNestedJsonObjectCastWithIs() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + if (manager["reporting employees"] is JsonObject reportingEmployees) + { + if (reportingEmployees["software developers"] is JsonObject softwareDevelopers) + { + if (softwareDevelopers["full time employees"] is JsonObject fullTimeEmployees) + { + fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); + } + } + } + } + + /// + /// Accesing nested Json object - explicit casting + /// + [Fact] + public static void TestAccesingNestedJsonObjectExplicitCast() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + ((JsonObject)((JsonObject)manager["reporting employees"])["HR"]).Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - GetObjectProperty method + /// + [Fact] + public static void TestAccesingNestedJsonObjectGetPropertyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject internDevelopers = manager.GetObjectProperty("reporting employees") + .GetObjectProperty("software developers") + .GetObjectProperty("intern employees"); + internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - TryGetObjectProperty method + /// + [Fact] + public static void TestAccesingNestedJsonObjectTryGetPropertyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + if (manager.TryGetObjectProperty("reporting employees", out JsonObject reportingEmployees)) + { + if (reportingEmployees.TryGetObjectProperty("software developers", out JsonObject softwareDevelopers)) + { + if (softwareDevelopers.TryGetObjectProperty("full time employees", out JsonObject fullTimeEmployees)) + { + fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); + } + } + } + } + + /// + /// Accesing nested Json array - GetArrayProperty method + /// + [Fact] + public static void TestAccesingNestedJsonArrayGetPropertyMethod() + { + var issues = new JsonObject() + { + { "features", new JsonArray{ "new functionality 1", "new functionality 2" } }, + { "bugs", new JsonArray{ "bug 123", "bug 4566", "bug 821" } }, + { "tests", new JsonArray{ "code coverage" } }, + }; + + issues.GetArrayProperty("bugs").Add("bug 12356"); + ((JsonString)issues.GetArrayProperty("features")[0]).Value = "feature 1569"; + ((JsonString)issues.GetArrayProperty("features")[1]).Value = "feature 56134"; + } + + /// + /// Modifying Json object key - remove and add + /// + [Fact] + public static void TestModifyingJsonObjectKeyRemoveAdd() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject reportingEmployees = manager.GetObjectProperty("reporting employees"); + + JsonNode softwareDevelopers = reportingEmployees["software developers"]; + reportingEmployees.Remove("software developers"); + reportingEmployees.Add("software engineers", softwareDevelopers); + } + + /// + /// Modifying Json object key - modify method + /// + [Fact] + public static void TestModifyingJsonObjectKeyModifyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject reportingEmployees = manager.GetObjectProperty("reporting employees"); + + reportingEmployees.ModifyPropertyName("software developers", "software engineers"); + } + + /// + /// Aquiring all values + /// + [Fact] + public static void TestAquiringAllValues() + { + var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); + ICollection employeesWithoutId = employees.Values; + } + + /// + /// Aquiring all properties + /// + [Fact] + public static void TestAquiringAllProperties() + { + var employees = new JsonObject() + { + { "FTE", "John Smith" }, + { "FTE", "Ann Predictable" }, + { "Intern", "Zoe Coder" }, + { "FTE", "Byron Shadow" }, + }; + + IEnumerable fullTimeEmployees = employees.GetAllProperties("FTE"); + } + } +} From 409e57503c60f1fee88f17db510088903749cdd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katarzyna=20Bu=C5=82at?= Date: Fri, 19 Jul 2019 15:21:28 -0700 Subject: [PATCH 04/30] Json prototype - transformation API (#2) * transformation API added * assertions to existing scenarios added --- src/System.Text.Json/ref/System.Text.Json.cs | 23 +- .../System/Text/Json/Document/JsonElement.cs | 5 + .../src/System/Text/Json/Node/JsonArray.cs | 5 +- .../src/System/Text/Json/Node/JsonNode.cs | 20 +- .../src/System/Text/Json/Node/JsonObject.cs | 4 +- .../tests/System.Text.Json.Tests.csproj | 4 + ...JsonApiTests.TestAccessingNestedMembers.cs | 146 +++++ .../tests/WritableJsonApiTests.TestData.cs | 136 +++++ .../WritableJsonApiTests.TestModifying.cs | 175 ++++++ ...ritableJsonApiTests.TestTransformations.cs | 232 ++++++++ .../tests/WritableJsonApiTests.cs | 548 ++++++++---------- 11 files changed, 977 insertions(+), 321 deletions(-) create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs diff --git a/src/System.Text.Json/ref/System.Text.Json.cs b/src/System.Text.Json/ref/System.Text.Json.cs index a1db0fc81651..1cd6b06e9056 100644 --- a/src/System.Text.Json/ref/System.Text.Json.cs +++ b/src/System.Text.Json/ref/System.Text.Json.cs @@ -84,6 +84,7 @@ public void Insert(int index, ushort item) { } public void Insert(int index, uint item) { } [System.CLSCompliantAttribute(false)] public void Insert(int index, ulong item) { } + public int LastIndexOf(System.Text.Json.JsonNode item) { throw null; } public bool Remove(System.Text.Json.JsonNode item) { throw null; } public void RemoveAt(int index) { } void System.Collections.Generic.ICollection.CopyTo(System.Text.Json.JsonNode[] array, int arrayIndex) { } @@ -130,6 +131,7 @@ public readonly partial struct JsonElement { private readonly object _dummy; private readonly int _dummyPrimitive; + public bool IsImmutable { get { throw null; } } public System.Text.Json.JsonElement this[int index] { get { throw null; } } public System.Text.Json.JsonValueKind ValueKind { get { throw null; } } public System.Text.Json.JsonElement Clone() { throw null; } @@ -247,9 +249,20 @@ protected JsonNamingPolicy() { } public static System.Text.Json.JsonNamingPolicy CamelCase { get { throw null; } } public abstract string ConvertName(string name); } - public partial class JsonNode - { - public JsonNode() { } + public abstract partial class JsonNode + { + internal JsonNode() { } + public System.Text.Json.JsonElement AsJsonElement() { throw null; } + public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonDocument jsonDocument) { throw null; } + public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonElement jsonElement) { throw null; } + public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonNode jsonNode) { throw null; } + public static System.Text.Json.JsonNode GetNode(System.Text.Json.JsonElement jsonElement) { throw null; } + public static System.Text.Json.JsonNode Parse(System.Buffers.ReadOnlySequence utf8Json) { throw null; } + public static System.Text.Json.JsonNode Parse(System.IO.Stream utf8Json) { throw null; } + public static System.Text.Json.JsonNode Parse(System.ReadOnlyMemory utf8Json) { throw null; } + public static System.Text.Json.JsonNode Parse(System.ReadOnlyMemory json) { throw null; } + public static System.Text.Json.JsonNode Parse(string json) { throw null; } + public static bool TryGetNode(System.Text.Json.JsonElement jsonElement, out System.Text.Json.JsonNode jsonNode) { throw null; } } public partial class JsonNumber : System.Text.Json.JsonNode { @@ -360,9 +373,9 @@ public void Add(string propertyName, ulong propertyValue) { } public void AddRange(System.Collections.Generic.IEnumerable> jsonProperties) { } public bool ContainsProperty(string propertyName) { throw null; } public System.Collections.Generic.IEnumerable GetAllProperties(string propertyName) { throw null; } - public System.Text.Json.JsonArray GetArrayProperty(string propertyName) { throw null; } public System.Collections.Generic.IEnumerator> GetEnumerator() { throw null; } - public System.Text.Json.JsonObject GetObjectProperty(string propertyName) { throw null; } + public System.Text.Json.JsonArray GetJsonArrayProperty(string propertyName) { throw null; } + public System.Text.Json.JsonObject GetJsonObjectProperty(string propertyName) { throw null; } public System.Text.Json.JsonNode GetProperty(string propertyName) { throw null; } public bool ModifyPropertyName(string oldName, string newName) { throw null; } public bool Remove(string propertyName) { throw null; } diff --git a/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs b/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs index 1b142fd5f6a8..39369b3828fd 100644 --- a/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs +++ b/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs @@ -1440,5 +1440,10 @@ private void CheckValidInstance() [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay => $"ValueKind = {ValueKind} : \"{ToString()}\""; + +// for now disabling error caused by not adding documentation to methods +#pragma warning disable CS1591 + public bool IsImmutable => throw null; +#pragma warning restore CS1591 } } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs index 5f5f14cb1789..c2abffde5a74 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs @@ -87,10 +87,11 @@ public void Add(ulong value) { } [CLSCompliant(false)] public bool Contains(ulong value) { throw null; } - public int Count => throw new NotImplementedException(); - public bool IsReadOnly => throw new NotImplementedException(); + public int Count => throw null; + public bool IsReadOnly => throw null; public int IndexOf(JsonNode item) { throw null; } + public int LastIndexOf(JsonNode item) { throw null; } public void RemoveAt(int index) { throw null; } public void Clear() { throw null; } public bool Remove(JsonNode item) { throw null; } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs index 7dd0d7206f19..fc907402a258 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs @@ -5,11 +5,29 @@ // for now disabling error caused by not adding documentation to methods #pragma warning disable CS1591 +using System.Buffers; +using System.IO; + namespace System.Text.Json { - public partial class JsonNode + public abstract partial class JsonNode { + private protected JsonNode() { } + public JsonElement AsJsonElement() { throw null; } + + public static JsonNode GetNode(JsonElement jsonElement) { throw null; } + public static bool TryGetNode(JsonElement jsonElement, out JsonNode jsonNode) { throw null; } + + public static JsonNode Parse(string json) { throw null; } + public static JsonNode Parse(ReadOnlySequence utf8Json) { throw null; } + public static JsonNode Parse(Stream utf8Json) { throw null; } + public static JsonNode Parse(ReadOnlyMemory utf8Json) { throw null; } + public static JsonNode Parse(ReadOnlyMemory json) { throw null; } + + public static JsonNode DeepCopy(JsonNode jsonNode) { throw null; } + public static JsonNode DeepCopy(JsonElement jsonElement) { throw null; } + public static JsonNode DeepCopy(JsonDocument jsonDocument) { throw null; } } } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs index c9a083f3a2da..5955e1fd3eea 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs @@ -47,9 +47,9 @@ public void AddRange(IEnumerable> jsonProperties) public JsonNode GetProperty(string propertyName) { throw null; } public bool TryGetProperty(string propertyName, out JsonNode jsonNode) { throw null; } - public JsonObject GetObjectProperty(string propertyName) { throw null; } + public JsonObject GetJsonObjectProperty(string propertyName) { throw null; } public bool TryGetObjectProperty(string propertyName, out JsonObject jsonObject) { throw null; } - public JsonArray GetArrayProperty(string propertyName) { throw null; } + public JsonArray GetJsonArrayProperty(string propertyName) { throw null; } public bool TryGetArrayProperty(string propertyName, out JsonArray jsonArray) { throw null; } public IEnumerable GetAllProperties(string propertyName) { throw null; } diff --git a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj index fabe09e30d71..14b23aa2f3ac 100644 --- a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -102,7 +102,11 @@ + + + + diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs new file mode 100644 index 000000000000..cf5b586c7f52 --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs @@ -0,0 +1,146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static partial class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Accesing nested Json object - casting with as operator + /// + [Fact] + public static void TestAccesingNestedJsonObjectCastWithAs() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + // Should not throw any exceptions: + + var reportingEmployees = manager["reporting employees"] as JsonObject; + if (reportingEmployees == null) + throw new InvalidCastException(); + + var softwareDevelopers = reportingEmployees["software developers"] as JsonObject; + if (softwareDevelopers == null) + throw new InvalidCastException(); + + var internDevelopers = softwareDevelopers["intern employees"] as JsonObject; + if (internDevelopers == null) + throw new InvalidCastException(); + + internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - casting with is operator + /// + [Fact] + public static void TestAccesingNestedJsonObjectCastWithIs() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + static bool AddEmployee(JsonObject manager) + { + + if (manager["reporting employees"] is JsonObject reportingEmployees) + { + if (reportingEmployees["software developers"] is JsonObject softwareDevelopers) + { + if (softwareDevelopers["full time employees"] is JsonObject fullTimeEmployees) + { + fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); + return true; + } + } + } + return false; + } + + bool success = AddEmployee(manager); + Assert.True(success); + } + + /// + /// Accesing nested Json object - explicit casting + /// + [Fact] + public static void TestAccesingNestedJsonObjectExplicitCast() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + // Should not throw any exceptions: + ((JsonObject)((JsonObject)manager["reporting employees"])["HR"]).Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - GetObjectProperty method + /// + [Fact] + public static void TestAccesingNestedJsonObjectGetPropertyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + // Should not throw any exceptions: + + JsonObject internDevelopers = manager.GetJsonObjectProperty("reporting employees") + .GetJsonObjectProperty("software developers") + .GetJsonObjectProperty("intern employees"); + internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); + } + + /// + /// Accesing nested Json object - TryGetObjectProperty method + /// + [Fact] + public static void TestAccesingNestedJsonObjectTryGetPropertyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + + static bool AddEmployee(JsonObject manager) + { + if (manager.TryGetObjectProperty("reporting employees", out JsonObject reportingEmployees)) + { + if (reportingEmployees.TryGetObjectProperty("software developers", out JsonObject softwareDevelopers)) + { + if (softwareDevelopers.TryGetObjectProperty("full time employees", out JsonObject fullTimeEmployees)) + { + fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); + return true; + } + } + } + + return false; + } + + bool success = AddEmployee(manager); + Assert.True(success); + } + + /// + /// Accesing nested Json array - GetArrayProperty method + /// + [Fact] + public static void TestAccesingNestedJsonArrayGetPropertyMethod() + { + var issues = new JsonObject() + { + { "features", new JsonArray{ "new functionality 1", "new functionality 2" } }, + { "bugs", new JsonArray{ "bug 123", "bug 4566", "bug 821" } }, + { "tests", new JsonArray{ "code coverage" } }, + }; + + issues.GetJsonArrayProperty("bugs").Add("bug 12356"); + ((JsonString)issues.GetJsonArrayProperty("features")[0]).Value = "feature 1569"; + ((JsonString)issues.GetJsonArrayProperty("features")[1]).Value = "feature 56134"; + + Assert.True(((JsonArray)issues["bugs"]).Contains("bug 12356")); + Assert.Equal((JsonString)((JsonArray)issues["features"])[0], "feature 1569"); + Assert.Equal((JsonString)((JsonArray)issues["features"])[1], "feature 56134"); + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs new file mode 100644 index 000000000000..e53f85379232 --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs @@ -0,0 +1,136 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static partial class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Helper class simulating external library + /// + private static class EmployeesDatabase + { + private static int s_id = 0; + public static KeyValuePair GetNextEmployee() + { + var employee = new JsonObject() + { + { "name", "John" } , + { "surname", "Smith"}, + { "age", 45 } + }; + + return new KeyValuePair("employee" + s_id++, employee); + } + + public static IEnumerable> GetTenBestEmployees() + { + for (int i = 0; i < 10; i++) + yield return GetNextEmployee(); + } + + /// + /// Returns following JsonObject: + /// { + /// { "name" : "John" } + /// { "phone numbers" : { "work" : "123-456-7890", "home": "123-456-7890" } } + /// { + /// "reporting employees" : + /// { + /// "software developers" : + /// { + /// "full time employees" : /JsonObject of 3 employees fromk database/ + /// "intern employees" : /JsonObject of 2 employees fromk database/ + /// }, + /// "HR" : /JsonObject of 10 employees fromk database/ + /// } + /// + /// + public static JsonObject GetManager() + { + var manager = GetNextEmployee().Value as JsonObject; + + manager.Add + ( + "phone numbers", + new JsonObject() + { + { "work", "123-456-7890" }, { "home", "123-456-7890" } + } + ); + + manager.Add + ( + "reporting employees", new JsonObject() + { + { + "software developers", new JsonObject() + { + { + "full time employees", new JsonObject() + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + } + }, + { + "intern employees", new JsonObject() + { + EmployeesDatabase.GetNextEmployee(), + EmployeesDatabase.GetNextEmployee(), + } + } + } + }, + { + "HR", new JsonObject() + { + { + "full time employees", new JsonObject(EmployeesDatabase.GetTenBestEmployees()) + } + } + } + } + ); + + return manager; + } + + public static bool CheckSSN(string ssnNumber) => true; + public static void PerformHeavyOperations(JsonElement employee) { } + } + + /// + /// Helper class simulating sending Json files via network + /// + private static class Mailbox + { + public static void SendEmployeeData(JsonElement employeeData) { } + public static JsonElement RetrieveMutableEmployeeData() { return EmployeesDatabase.GetNextEmployee().Value.AsJsonElement(); } + public static JsonElement RetrieveImmutableEmployeeData() { return new JsonElement(); } + + public static void SendAllEmployeesData(JsonElement employeesData) { } + } + + private static class HealthCare + { + public static void CreateMedicalAppointment(string personName) { } + } + + /// + /// Helper class simulating enum + /// + private enum AvailableStateCodes + { + WA, + CA, + NY, + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs new file mode 100644 index 000000000000..e4885b5074b4 --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs @@ -0,0 +1,175 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Xunit; + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static partial class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Replacing Json object's primnary types + /// + [Fact] + public static void TestReplacingsonObjectPrimaryTypes() + { + var person1 = new JsonObject + { + { "name", "John" }, + { "age", 45 }, + { "is_married", true } + }; + + // Assign by creating a new instance of primary Json type + person1["name"] = new JsonString("Bob"); + + Assert.IsType(person1["name"]); + Assert.Equal(person1["name"] as JsonString, "Bob"); + + // Assign by using an implicit operator on primary Json type + JsonNumber newAge = 55; + person1["age"] = newAge; + + Assert.IsType(person1["age"]); + Assert.Equal(person1["age"] as JsonNumber, 55); + + // Assign by explicit cast from Json primary type + person1["is_married"] = (JsonBoolean)false; + + Assert.IsType(person1["is_married"]); + Assert.Equal(person1["is_married"] as JsonBoolean, false); + + // Not possible scenario (wold require implicit cast operators in JsonNode): + // person["name"] = "Bob"; + + var person2 = new JsonObject + { + { "name", new JsonString[]{ "Emily", "Rosalie" } }, + { "age", 33 }, + { "is_married", true } + }; + + // Copy property from another JsonObject + person1["age"] = person2["age"]; + + Assert.IsType(person1["age"]); + Assert.Equal(person1["age"] as JsonNumber, 33); + + // Copy property of different typoe + person1["name"] = person2["name"]; + + Assert.IsType(person1["name"]); + } + + /// + /// Modifying Json object's primnary types + /// + [Fact] + public static void TestModifyingJsonObjectPrimaryTypes() + { + JsonString name = "previous name"; + name.Value = "new name"; + + Assert.Equal("new name", name.Value); + + bool shouldBeEnabled = true; + var isEnabled = new JsonBoolean(false); + isEnabled.Value = shouldBeEnabled; + + Assert.True(isEnabled.Value); + + JsonNumber veryBigConstant = new JsonNumber(); + veryBigConstant.SetString("1e1000"); + string bigNumber = veryBigConstant.GetString(); + + Assert.Equal("1e1000", bigNumber); + + veryBigConstant.SetInt16(123); + short smallNumber = veryBigConstant.GetInt16(); + + Assert.Equal(123, smallNumber); + + // Incrementing age: + JsonObject employee = EmployeesDatabase.GetManager(); + int age = ((JsonNumber)employee["age"]).GetInt32(); + ((JsonNumber)employee["age"]).SetInt32(age + 1); + + Assert.Equal(46, ((JsonNumber)employee["age"]).GetInt32()); + } + + /// + /// Adding values to JsonArray + /// + [Fact] + public static void TestAddingToJsonArray() + { + var employeesIds = new JsonArray(); + + foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) + { + employeesIds.Add(employee.Key); + } + + JsonString prevId = new JsonString(); + foreach (JsonNode employeeId in employeesIds) + { + Assert.IsType(employeeId); + var employeeIdString = employeeId as JsonString; + Assert.NotEqual(prevId, employeeIdString); + prevId = employeeIdString; + } + } + + /// + /// Modifying Json object key - remove and add + /// + [Fact] + public static void TestModifyingJsonObjectKeyRemoveAdd() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject reportingEmployees = manager.GetJsonObjectProperty("reporting employees"); + + static void ModifyProperty(JsonObject jsonObject, string previousName, string newName) + { + JsonNode previousValue = jsonObject[previousName]; + jsonObject.Remove(previousName); + jsonObject.Add(newName, previousValue); + } + + string previousName = "software developers"; + string newName = "software engineers"; + + Assert.True(reportingEmployees.ContainsProperty(previousName)); + JsonNode previousValue = reportingEmployees[previousName]; + + ModifyProperty(reportingEmployees, previousName, newName); + + Assert.False(reportingEmployees.ContainsProperty(previousName)); + Assert.True(reportingEmployees.ContainsProperty(newName)); + Assert.Equal(previousValue, reportingEmployees[newName]); + } + + /// + /// Modifying Json object key - modify method + /// + [Fact] + public static void TestModifyingJsonObjectKeyModifyMethod() + { + JsonObject manager = EmployeesDatabase.GetManager(); + JsonObject reportingEmployees = manager.GetJsonObjectProperty("reporting employees"); + + Assert.True(reportingEmployees.ContainsProperty("software developers")); + JsonNode previousValue = reportingEmployees["software engineers"]; + + reportingEmployees.ModifyPropertyName("software developers", "software engineers"); + + Assert.False(reportingEmployees.ContainsProperty("software developers")); + Assert.True(reportingEmployees.ContainsProperty("software engineers")); + Assert.Equal(previousValue, reportingEmployees["software engineers"]); + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs new file mode 100644 index 000000000000..0b6a5d96ecbc --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs @@ -0,0 +1,232 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace System.Text.Json +{ +#pragma warning disable xUnit1000 + internal static partial class WritableJsonApiTests +#pragma warning enable xUnit1000 + { + /// + /// Transforming JsoneNode to JsonElement + /// + [Fact] + public static void TestTransformingJsonNodeToJsonElement() + { + // Send Json through network, should not throw any exceptions: + JsonNode employeeDataToSend = EmployeesDatabase.GetNextEmployee().Value; + Mailbox.SendEmployeeData(employeeDataToSend.AsJsonElement()); + } + + /// + /// Transforming JsonElement to JsonNode + /// + [Fact] + public static void TestTransformingJsonElementToJsonNode() + { + // Retrieve Json from network, should not throw any exceptions: + JsonNode receivedEmployeeData = JsonNode.DeepCopy(Mailbox.RetrieveMutableEmployeeData()); + if (receivedEmployeeData is JsonObject employee) + { + employee["name"] = new JsonString("Bob"); + Mailbox.SendEmployeeData(employee.AsJsonElement()); + } + } + + /// + /// Transforming JsonDocument to JsonNode and vice versa + /// + [Fact] + public static void TestTransformingToFromJsonDocument() + { + string jsonString = @" + { + ""employee1"" : + { + ""name"" : ""Ann"", + ""surname"" : ""Predictable"", + ""age"" : 30, + }, + ""employee2"" : + { + ""name"" : ""Zoe"", + ""surname"" : ""Coder"", + ""age"" : 24, + } + }"; + + using (JsonDocument employeesToSend = JsonDocument.Parse(jsonString)) + { + // regular send: + Mailbox.SendAllEmployeesData(employeesToSend.RootElement); + + // modified elements send: + JsonObject employees = JsonNode.DeepCopy(employeesToSend) as JsonObject; + Assert.Equal(2, employees.Count()); + + employees.Add(EmployeesDatabase.GetNextEmployee()); + Assert.Equal(3, employees.Count()); + + Mailbox.SendAllEmployeesData(employees.AsJsonElement()); + } + } + + /// + /// Parsing right to JsonNode if user knows data will be modified + /// + [Fact] + public static void TestParsingToJsonNode() + { + string jsonString = @" + { + ""employee1"" : + { + ""name"" : ""Ann"", + ""surname"" : ""Predictable"", + ""age"" : 30, + }, + ""employee2"" : + { + ""name"" : ""Zoe"", + ""surname"" : ""Coder"", + ""age"" : 24, + } + }"; + + JsonObject employees = JsonNode.Parse(jsonString) as JsonObject; + employees.Add(EmployeesDatabase.GetNextEmployee()); + Mailbox.SendAllEmployeesData(employees.AsJsonElement()); + + Assert.Equal(2, employees.Count()); + Assert.True(employees.ContainsProperty("employee1")); + Assert.True(employees.ContainsProperty("employee2")); + + JsonObject employee2 = employees.GetJsonObjectProperty("employee2"); + Assert.IsType(employee2["name"]); + Assert.Equal("Zoe", (JsonString)employee2["name"]); + Assert.IsType(employee2["surname"]); + Assert.Equal("Coder", (JsonString)employee2["surname"]); + Assert.IsType(employee2["age"]); + Assert.Equal(24, (JsonNumber)employee2["age"]); + } + + /// + /// Copying JsoneNode + /// + [Fact] + public static void TestCopyingJsonNode() + { + JsonObject employee = EmployeesDatabase.GetManager(); + JsonNode employeeCopy = JsonNode.DeepCopy(employee); + + static bool RecursiveEquals(JsonNode left, JsonNode right) + { + if (left == null && right == null) + { + return true; + } + + if (right.GetType() != left.GetType()) + { + return false; + } + + switch (left) + { + case JsonObject leftJsonObject: + var rightJsonObject = right as JsonObject; + if (leftJsonObject.Count() != rightJsonObject.Count()) + { + return false; + } + + for (int idx = 0; idx < leftJsonObject.Count(); idx++) + { + KeyValuePair leftElement = leftJsonObject.ElementAt(idx); + KeyValuePair rightElement = rightJsonObject.ElementAt(idx); + + if (leftElement.Key != rightElement.Key || !RecursiveEquals(leftElement.Value, rightElement.Value)) + { + return false; + } + } + + return true; + case JsonArray leftJsonArray: + var rightJsonArray = right as JsonArray; + if (leftJsonArray.Count() != rightJsonArray.Count()) + { + return false; + } + for (int idx = 0; idx < leftJsonArray.Count(); idx++) + { + JsonNode leftElement = leftJsonArray.ElementAt(idx); + JsonNode rightElement = rightJsonArray.ElementAt(idx); + + if (!RecursiveEquals(leftElement, rightElement)) + { + return false; + } + } + + return true; + case JsonString leftJsonString: + return leftJsonString.Equals(right as JsonString); + case JsonNumber leftJsonNumber: + return leftJsonNumber.Equals(right as JsonNumber); + case JsonBoolean leftJsonBoolean: + return leftJsonBoolean.Equals(right as JsonBoolean); + default: + return false; + } + } + + Assert.True(RecursiveEquals(employee, employeeCopy)); + } + + /// + /// Checking IsImmutable property + /// + [Fact] + public static void TestIsImmutable() + { + JsonElement employee = Mailbox.RetrieveMutableEmployeeData(); + Assert.False(employee.IsImmutable); + + if (!employee.IsImmutable) + { + JsonObject employeeNode = JsonNode.GetNode(employee) as JsonObject; + employeeNode["received as node"] = (JsonBoolean)true; + } + + employee = Mailbox.RetrieveImmutableEmployeeData(); + Assert.True(employee.IsImmutable); + } + + /// + /// Retrieving JsonNode from JsonElement + /// + [Fact] + public static void TestTryGetNode() + { + JsonElement employee = Mailbox.RetrieveMutableEmployeeData(); + + static bool CheckIfReceivedAsNode(JsonElement employee) + { + if (JsonNode.TryGetNode(employee, out JsonNode employeeNode)) + { + ((JsonObject)employeeNode)["received as node"] = (JsonBoolean)true; + return true; + } + return false; + } + + Assert.True(CheckIfReceivedAsNode(employee)); + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.cs b/src/System.Text.Json/tests/WritableJsonApiTests.cs index 2b66c6c8acab..e45bff09e714 100644 --- a/src/System.Text.Json/tests/WritableJsonApiTests.cs +++ b/src/System.Text.Json/tests/WritableJsonApiTests.cs @@ -6,107 +6,12 @@ using System.Linq; using Xunit; - namespace System.Text.Json { #pragma warning disable xUnit1000 - internal static class WritableJsonApiTests + internal static partial class WritableJsonApiTests #pragma warning enable xUnit1000 { - /// - /// Helper class simulating external library - /// - private static class EmployeesDatabase - { - private static int s_id = 0; - public static KeyValuePair GetNextEmployee() - { - return new KeyValuePair("employee" + s_id++, new JsonObject()); - } - - public static IEnumerable> GetTenBestEmployees() - { - for (int i = 0; i < 10; i++) - yield return GetNextEmployee(); - } - - /// - /// Returns following JsonObject: - /// { - /// { "name" : "John" } - /// { "phone numbers" : { "work" : "123-456-7890", "home": "123-456-7890" } } - /// { - /// "reporting employees" : - /// { - /// "software developers" : - /// { - /// "full time employees" : /JsonObject of 3 employees fromk database/ - /// "intern employees" : /JsonObject of 2 employees fromk database/ - /// }, - /// "HR" : /JsonObject of 10 employees fromk database/ - /// } - /// - /// - public static JsonObject GetManager() - { - return new JsonObject - { - { "name", "John" }, - { - "phone numbers", new JsonObject() - { - { "work", "123-456-7890" }, { "home", "123-456-7890" } - } - }, - { - "reporting employees", new JsonObject() - { - { - "software developers", new JsonObject() - { - { - "full time employees", new JsonObject() - { - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - } - }, - { - "intern employees", new JsonObject() - { - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - } - } - } - }, - { - "HR", new JsonObject() - { - { - "full time employees", new JsonObject(EmployeesDatabase.GetTenBestEmployees()) - } - } - } - } - } - }; - } - - public static bool CheckSSN(string ssnNumber) => true; - } - - /// - /// Helper class simulating enum - /// - private enum AvailableStateCodes - { - WA, - CA, - NY, - } - /// /// Creating simple Json object /// @@ -120,6 +25,20 @@ public static void TestCreatingJsonObject() { "is developer", true }, { "null property", (JsonNode) null } }; + + Assert.IsType(developer["name"]); + var developerNameCasted = developer["name"] as JsonString; + Assert.Equal("Kasia", developerNameCasted.Value); + + Assert.IsType(developer["age"]); + var developerAgeCasted = developer["age"] as JsonNumber; + Assert.Equal(22, developerAgeCasted.GetInt32()); + + Assert.IsType(developer["is developer"]); + var isDeveloperCasted = developer["is developer"] as JsonBoolean; + Assert.Equal(true, isDeveloperCasted.Value); + + Assert.Null(developer["null property"]); } /// @@ -134,6 +53,18 @@ public static void TestCreatingJsonObjectNewMethods() { "age", new JsonNumber(22) }, { "is developer", new JsonBoolean(true) } }; + + Assert.IsType(developer["name"]); + var developerNameCasted = developer["name"] as JsonString; + Assert.Equal("Kasia", developerNameCasted.Value); + + Assert.IsType(developer["age"]); + var developerAgeCasted = developer["age"] as JsonNumber; + Assert.Equal(22, developerAgeCasted.GetInt32()); + + Assert.IsType(developer["is developer"]); + var isDeveloperCasted = developer["is developer"] as JsonBoolean; + Assert.Equal(true, isDeveloperCasted.Value); } /// @@ -150,11 +81,27 @@ public static void TestNumerics() { "area", PI } }; - JsonNumber bigConstantBoxed = Int64.MaxValue; + Assert.IsType(circle["radius"]); + var radius = circle["radius"] as JsonNumber; + Assert.Equal(radius, 1); + + Assert.IsType(circle["length"]); + var length = circle["length"] as JsonNumber; + Assert.Equal(length, 2 * PI); + + Assert.IsType(circle["area"]); + var area = circle["area"] as JsonNumber; + Assert.Equal(area, PI); + + JsonNumber bigConstantBoxed = long.MaxValue; long bigConstant = bigConstantBoxed.GetInt64(); + Assert.Equal(long.MaxValue, bigConstant); + var smallValueBoxed = new JsonNumber(17); smallValueBoxed.TryGetInt16(out short smallValue); + + Assert.Equal(17, smallValue); } /// @@ -199,6 +146,16 @@ public static void TestCreatingNestedJsonObject() } } }; + + Assert.IsType(person["phone numbers"]); + var phoneNumbers = person["phone numbers"] as JsonObject; + Assert.IsType(phoneNumbers["work"]); + Assert.IsType(phoneNumbers["home"]); + + Assert.IsType(person["addresses"]); + var addresses = person["office"] as JsonObject; + Assert.IsType(addresses["office"]); + Assert.IsType(addresses["home"]); } /// @@ -208,6 +165,7 @@ public static void TestCreatingNestedJsonObject() public static void TestAssignmentDefinition() { JsonNode employee = EmployeesDatabase.GetNextEmployee().Value; + Assert.IsType(employee); } /// @@ -223,6 +181,15 @@ public static void TestAddingKeyValuePair() EmployeesDatabase.GetNextEmployee(), EmployeesDatabase.GetNextEmployee(), }; + + string prevId = ""; + foreach((string id, JsonNode employee) in employees) + { + Assert.NotEqual(prevId, id); + prevId = id; + + Assert.IsType(employee); + } } /// @@ -236,6 +203,15 @@ public static void TestAddingKeyValuePairAfterInitialization() { employees.Add(employee); } + + string prevId = ""; + foreach ((string id, JsonNode employee) in employees) + { + Assert.NotEqual(prevId, id); + prevId = id; + + Assert.IsType(employee); + } } /// @@ -245,6 +221,15 @@ public static void TestAddingKeyValuePairAfterInitialization() public static void TestAddingKeyValuePairsCollection() { var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); + + string prevId = ""; + foreach ((string id, JsonNode employee) in employees) + { + Assert.NotEqual(prevId, id); + prevId = id; + + Assert.IsType(employee); + } } /// @@ -255,16 +240,94 @@ public static void TestAddingKeyValuePairsCollectionAfterInitialization() { var employees = new JsonObject(); employees.AddRange(EmployeesDatabase.GetTenBestEmployees()); + + string prevId = ""; + foreach ((string id, JsonNode employee) in employees) + { + Assert.NotEqual(prevId, id); + prevId = id; + + Assert.IsType(employee); + } + } + + /// + /// Adding JsonArray to JsonObject by creating it in initializing collection + /// + [Fact] + public static void TestAddingJsonArray() + { + var preferences = new JsonObject() + { + { "colours", new JsonArray{ "red", "green", "purple" } } + }; + + Assert.IsType(preferences["colours"]); + var colours = preferences["colours"] as JsonArray; + Assert.Equal(3, colours.Count); + + string[] expected = { "red", "green", "blue" }; + + for (int i = 0; i < colours.Count; i++) + { + Assert.IsType(colours[i]); + Assert.Equal(expected[i], colours[i] as JsonString); + } } /// - /// Creating Json array + /// Adding JsonArray to JsonObject by creating it from string array /// [Fact] - public static void TestCreatingJsonArray() + public static void TestCretingJsonArrayFromStringArray() { - string[] dishes = { "sushi", "pasta", "cucumber soup" }; + string[] expected = { "sushi", "pasta", "cucumber soup" }; + var preferences = new JsonObject() + { + { "dishes", new JsonArray(expected) } + }; + Assert.IsType(preferences["dishes"]); + var dishesJson = preferences["dishes"] as JsonArray; + Assert.Equal(3, dishesJson.Count); + + for (int i = 0; i < dishesJson.Count; i++) + { + Assert.IsType(dishesJson[i]); + Assert.Equal(expected[i], dishesJson[i] as JsonString); + } + } + + /// + /// Adding JsonArray to JsonObject by passing JsonNumber array + /// + [Fact] + public static void TestAddingJsonArrayFromJsonNumberArray() + { + var preferences = new JsonObject() + { + { "prime numbers", new JsonNumber[] { 19, 37 } } + }; + + Assert.IsType(preferences["prime numbers"]); + var primeNumbers = preferences["prime numbers"] as JsonArray; + Assert.Equal(2, primeNumbers.Count); + + int[] expected = { 19, 37 }; + + for (int i = 0; i < primeNumbers.Count; i++) + { + Assert.IsType(primeNumbers[i]); + Assert.Equal(expected[i], primeNumbers[i] as JsonNumber); + } + } + + /// + /// Adding JsonArray to JsonObject by passing IEnumerable of strings + /// + [Fact] + public static void TestAddingJsonArrayFromIEnumerableOfStrings() + { var sportsExperienceYears = new JsonObject() { { "skiing", 5 }, @@ -277,6 +340,28 @@ public static void TestCreatingJsonArray() // choose only sports with > 2 experience years IEnumerable sports = sportsExperienceYears.Where(sport => ((JsonNumber)sport.Value).GetInt32() > 2).Select(sport => sport.Key); + var preferences = new JsonObject() + { + { "sports", new JsonArray(sports) } + }; + + Assert.IsType(preferences["sports"]); + var sportsJsonArray = preferences["sports"] as JsonArray; + Assert.Equal(3, sportsJsonArray.Count); + + for (int i = 0; i < sportsJsonArray.Count; i++) + { + Assert.IsType(sportsJsonArray[i]); + Assert.Equal(sports.ElementAt(i), sportsJsonArray[i] as JsonString); + } + } + + /// + /// Adding JsonArray to JsonObject by passing IEnumerable of JsonNodes + /// + [Fact] + public static void TestAddingJsonArrayFromIEnumerableOfJsonNodes() + { var strangeWords = new JsonArray() { "supercalifragilisticexpialidocious", @@ -287,14 +372,20 @@ public static void TestCreatingJsonArray() var preferences = new JsonObject() { - { "colours", new JsonArray { "red", "green", "purple" } }, - { "numbers", new JsonArray { 4, 123, 88 } }, - { "prime numbers", new JsonNumber[] { 19, 37 } }, - { "varia", new JsonArray { 17, "green", true } }, - { "dishes", new JsonArray(dishes) }, - { "sports", new JsonArray(sports) }, - { "strange words", strangeWords.Where(word => ((JsonString)word).Value.Length < 10) }, + { "strange words", strangeWords.Where(word => ((JsonString)word).Value.Length < 10) } }; + + Assert.IsType(preferences["strange words"]); + var strangeWordsJsonArray = preferences["strange words"] as JsonArray; + Assert.Equal(2, strangeWordsJsonArray.Count); + + string [] expected = { "gladiolus", "albumen" }; + + for (int i = 0; i < strangeWordsJsonArray.Count; i++) + { + Assert.IsType(strangeWordsJsonArray[i]); + Assert.Equal(expected[i], strangeWordsJsonArray[i] as JsonString); + } } /// @@ -332,22 +423,15 @@ public static void TestCreatingNestedJsonArray() } }, }; - } - - /// - /// Adding values to JsonArray - /// - [Fact] - public static void TestAddingToJsonArray() - { - var employeesIds = new JsonArray(); - foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) - { - employeesIds.Add(employee.Key); - } + Assert.IsType(vertices[0]); + var innerJsonArray = vertices[0] as JsonArray; + Assert.IsType(innerJsonArray[0]); + innerJsonArray = innerJsonArray[0] as JsonArray; + Assert.IsType(innerJsonArray[0]); } + /// /// Creating Json array from collection /// @@ -355,6 +439,15 @@ public static void TestAddingToJsonArray() public static void TestCreatingJsonArrayFromCollection() { var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => new JsonString(employee.Key))); + + JsonString prevId = new JsonString(); + foreach (JsonNode employeeId in employeesIds) + { + Assert.IsType(employeeId); + var employeeIdString = employeeId as JsonString; + Assert.NotEqual(prevId, employeeIdString); + prevId = employeeIdString; + } } /// @@ -364,6 +457,15 @@ public static void TestCreatingJsonArrayFromCollection() public static void TestCreatingJsonArrayFromCollectionOfString() { var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => employee.Key)); + + JsonString prevId = new JsonString(); + foreach (JsonNode employeeId in employeesIds) + { + Assert.IsType(employeeId); + var employeeIdString = employeeId as JsonString; + Assert.NotEqual(prevId, employeeIdString); + prevId = employeeIdString; + } } /// @@ -383,6 +485,11 @@ public static void TestContains() EmployeesDatabase.CheckSSN(((JsonString)person["ssn"]).Value); } + Assert.True(person.ContainsProperty("ssn")); + Assert.False(person.ContainsProperty("surname")); + + // Different scenario: + var enabledOptions = new JsonArray { "readonly", @@ -408,197 +515,6 @@ public static void TestContains() } } - /// - /// Replacing Json object's primnary types - /// - [Fact] - public static void TestReplacingsonObjectPrimaryTypes() - { - var person1 = new JsonObject - { - { "name", "John" }, - { "age", 45 }, - { "is_married", true } - }; - - // Assign by creating a new instance of primary Json type - person1["name"] = new JsonString("Bob"); - - // Assign by using an implicit operator on primary Json type - JsonNumber newAge = 55; - person1["age"] = newAge; - - // Assign by explicit cast from Json primary type - person1["is_married"] = (JsonBoolean)true; - - // Not possible scenario (wold require implicit cast operators in JsonNode): - // person["name"] = "Bob"; - - var person2 = new JsonObject - { - { "name", new JsonString[]{ "Emily", "Rosalie" } }, - { "age", 33 }, - { "is_married", true } - }; - - // Copy property from another JsonObject - person1["age"] = person2["age"]; - - // Copy property of different typoe - person1["name"] = person2["name"]; - } - - /// - /// Modifying Json object's primnary types - /// - [Fact] - public static void TestModifyingJsonObjectPrimaryTypes() - { - JsonString name = "previous name"; - name.Value = "new name"; - - bool shouldBeEnabled = true; - var isEnabled = new JsonBoolean(false); - isEnabled.Value = shouldBeEnabled; - - JsonNumber veryBigConstant = new JsonNumber(); - veryBigConstant.SetString("1e1000"); - string bigNumber = veryBigConstant.GetString(); - veryBigConstant.SetInt16(123); - short smallNumber = veryBigConstant.GetInt16(); - } - - /// - /// Accesing nested Json object - casting with as operator - /// - [Fact] - public static void TestAccesingNestedJsonObjectCastWithAs() - { - // Casting with as operator - JsonObject manager = EmployeesDatabase.GetManager(); - - var reportingEmployees = manager["reporting employees"] as JsonObject; - if (reportingEmployees == null) - throw new InvalidCastException(); - - var softwareDevelopers = reportingEmployees["software developers"] as JsonObject; - if (softwareDevelopers == null) - throw new InvalidCastException(); - - var internDevelopers = softwareDevelopers["intern employees"] as JsonObject; - if (internDevelopers == null) - throw new InvalidCastException(); - - internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - casting with is operator - /// - [Fact] - public static void TestAccesingNestedJsonObjectCastWithIs() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - if (manager["reporting employees"] is JsonObject reportingEmployees) - { - if (reportingEmployees["software developers"] is JsonObject softwareDevelopers) - { - if (softwareDevelopers["full time employees"] is JsonObject fullTimeEmployees) - { - fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); - } - } - } - } - - /// - /// Accesing nested Json object - explicit casting - /// - [Fact] - public static void TestAccesingNestedJsonObjectExplicitCast() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - ((JsonObject)((JsonObject)manager["reporting employees"])["HR"]).Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - GetObjectProperty method - /// - [Fact] - public static void TestAccesingNestedJsonObjectGetPropertyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - JsonObject internDevelopers = manager.GetObjectProperty("reporting employees") - .GetObjectProperty("software developers") - .GetObjectProperty("intern employees"); - internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - TryGetObjectProperty method - /// - [Fact] - public static void TestAccesingNestedJsonObjectTryGetPropertyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - if (manager.TryGetObjectProperty("reporting employees", out JsonObject reportingEmployees)) - { - if (reportingEmployees.TryGetObjectProperty("software developers", out JsonObject softwareDevelopers)) - { - if (softwareDevelopers.TryGetObjectProperty("full time employees", out JsonObject fullTimeEmployees)) - { - fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); - } - } - } - } - - /// - /// Accesing nested Json array - GetArrayProperty method - /// - [Fact] - public static void TestAccesingNestedJsonArrayGetPropertyMethod() - { - var issues = new JsonObject() - { - { "features", new JsonArray{ "new functionality 1", "new functionality 2" } }, - { "bugs", new JsonArray{ "bug 123", "bug 4566", "bug 821" } }, - { "tests", new JsonArray{ "code coverage" } }, - }; - - issues.GetArrayProperty("bugs").Add("bug 12356"); - ((JsonString)issues.GetArrayProperty("features")[0]).Value = "feature 1569"; - ((JsonString)issues.GetArrayProperty("features")[1]).Value = "feature 56134"; - } - - /// - /// Modifying Json object key - remove and add - /// - [Fact] - public static void TestModifyingJsonObjectKeyRemoveAdd() - { - JsonObject manager = EmployeesDatabase.GetManager(); - JsonObject reportingEmployees = manager.GetObjectProperty("reporting employees"); - - JsonNode softwareDevelopers = reportingEmployees["software developers"]; - reportingEmployees.Remove("software developers"); - reportingEmployees.Add("software engineers", softwareDevelopers); - } - - /// - /// Modifying Json object key - modify method - /// - [Fact] - public static void TestModifyingJsonObjectKeyModifyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - JsonObject reportingEmployees = manager.GetObjectProperty("reporting employees"); - - reportingEmployees.ModifyPropertyName("software developers", "software engineers"); - } - /// /// Aquiring all values /// @@ -607,6 +523,11 @@ public static void TestAquiringAllValues() { var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); ICollection employeesWithoutId = employees.Values; + + foreach(JsonNode employee in employeesWithoutId) + { + Assert.IsType(employee); + } } /// @@ -624,6 +545,11 @@ public static void TestAquiringAllProperties() }; IEnumerable fullTimeEmployees = employees.GetAllProperties("FTE"); + + Assert.Equal(3, fullTimeEmployees.Count()); + Assert.True(fullTimeEmployees.Contains((JsonString)"John Smith")); + Assert.True(fullTimeEmployees.Contains((JsonString)"Ann Predictable")); + Assert.True(fullTimeEmployees.Contains((JsonString)"Byron Shadow")); } } } From 9dcfc4bb7a977268f12642729724a08c5c06d918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katarzyna=20Bu=C5=82at?= Date: Tue, 30 Jul 2019 13:58:50 -0700 Subject: [PATCH 05/30] 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 --- src/System.Text.Json/ref/System.Text.Json.cs | 29 +- .../src/System/Text/Json/Node/JsonArray.cs | 4 + .../src/System/Text/Json/Node/JsonBoolean.cs | 8 +- .../src/System/Text/Json/Node/JsonNumber.cs | 226 ++++++--- .../src/System/Text/Json/Node/JsonObject.cs | 1 + .../src/System/Text/Json/Node/JsonString.cs | 7 +- .../tests/System.Text.Json.Tests.csproj | 1 + ...ritableJsonApiTests.JsonNumberUnitTests.cs | 473 ++++++++++++++++++ ...JsonApiTests.TestAccessingNestedMembers.cs | 8 +- .../tests/WritableJsonApiTests.TestData.cs | 4 +- .../WritableJsonApiTests.TestModifying.cs | 16 +- ...ritableJsonApiTests.TestTransformations.cs | 4 +- .../tests/WritableJsonApiTests.cs | 10 +- 13 files changed, 684 insertions(+), 107 deletions(-) create mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.JsonNumberUnitTests.cs diff --git a/src/System.Text.Json/ref/System.Text.Json.cs b/src/System.Text.Json/ref/System.Text.Json.cs index 1cd6b06e9056..6164b2372c0c 100644 --- a/src/System.Text.Json/ref/System.Text.Json.cs +++ b/src/System.Text.Json/ref/System.Text.Json.cs @@ -12,6 +12,7 @@ public partial class JsonArray : System.Text.Json.JsonNode, System.Collections.G public JsonArray() { } public JsonArray(System.Collections.Generic.IEnumerable values) { } public JsonArray(System.Collections.Generic.IEnumerable values) { } + public JsonArray(System.Collections.Generic.IEnumerable values) { } public JsonArray(System.Collections.Generic.IEnumerable values) { } public JsonArray(System.Collections.Generic.IEnumerable values) { } public JsonArray(System.Collections.Generic.IEnumerable values) { } @@ -32,6 +33,7 @@ public JsonArray(System.Collections.Generic.IEnumerable values) { } public System.Text.Json.JsonNode this[int idx] { get { throw null; } set { } } public void Add(bool value) { } public void Add(byte value) { } + public void Add(decimal value) { } public void Add(double value) { } public void Add(short value) { } public void Add(int value) { } @@ -50,6 +52,7 @@ public void Add(ulong value) { } public void Clear() { } public bool Contains(bool value) { throw null; } public bool Contains(byte value) { throw null; } + public bool Contains(decimal value) { throw null; } public bool Contains(double value) { throw null; } public bool Contains(short value) { throw null; } public bool Contains(int value) { throw null; } @@ -69,6 +72,7 @@ public void Clear() { } public int IndexOf(System.Text.Json.JsonNode item) { throw null; } public void Insert(int index, bool item) { } public void Insert(int index, byte item) { } + public void Insert(int index, decimal item) { } public void Insert(int index, double item) { } public void Insert(int index, short item) { } public void Insert(int index, int item) { } @@ -90,14 +94,17 @@ public void RemoveAt(int index) { } void System.Collections.Generic.ICollection.CopyTo(System.Text.Json.JsonNode[] array, int arrayIndex) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } - public partial class JsonBoolean : System.Text.Json.JsonNode + public partial class JsonBoolean : System.Text.Json.JsonNode, System.IEquatable { public JsonBoolean() { } public JsonBoolean(bool value) { } public bool Value { get { throw null; } set { } } public override bool Equals(object obj) { throw null; } + public bool Equals(System.Text.Json.JsonBoolean other) { throw null; } public override int GetHashCode() { throw null; } + public static bool operator ==(System.Text.Json.JsonBoolean left, System.Text.Json.JsonBoolean right) { throw null; } public static implicit operator System.Text.Json.JsonBoolean (bool value) { throw null; } + public static bool operator !=(System.Text.Json.JsonBoolean left, System.Text.Json.JsonBoolean right) { throw null; } } public enum JsonCommentHandling : byte { @@ -264,10 +271,11 @@ internal JsonNode() { } public static System.Text.Json.JsonNode Parse(string json) { throw null; } public static bool TryGetNode(System.Text.Json.JsonElement jsonElement, out System.Text.Json.JsonNode jsonNode) { throw null; } } - public partial class JsonNumber : System.Text.Json.JsonNode + public partial class JsonNumber : System.Text.Json.JsonNode, System.IEquatable { public JsonNumber() { } public JsonNumber(byte value) { } + public JsonNumber(decimal value) { } public JsonNumber(double value) { } public JsonNumber(short value) { } public JsonNumber(int value) { } @@ -283,7 +291,9 @@ public JsonNumber(uint value) { } [System.CLSCompliantAttribute(false)] public JsonNumber(ulong value) { } public override bool Equals(object obj) { throw null; } + public bool Equals(System.Text.Json.JsonNumber other) { throw null; } public byte GetByte() { throw null; } + public decimal GetDecimal() { throw null; } public double GetDouble() { throw null; } public override int GetHashCode() { throw null; } public short GetInt16() { throw null; } @@ -292,14 +302,15 @@ public JsonNumber(ulong value) { } [System.CLSCompliantAttribute(false)] public sbyte GetSByte() { throw null; } public float GetSingle() { throw null; } - public string GetString() { throw null; } [System.CLSCompliantAttribute(false)] public ushort GetUInt16() { throw null; } [System.CLSCompliantAttribute(false)] public uint GetUInt32() { throw null; } [System.CLSCompliantAttribute(false)] public ulong GetUInt64() { throw null; } + public static bool operator ==(System.Text.Json.JsonNumber left, System.Text.Json.JsonNumber right) { throw null; } public static implicit operator System.Text.Json.JsonNumber (byte value) { throw null; } + public static implicit operator System.Text.Json.JsonNumber (decimal value) { throw null; } public static implicit operator System.Text.Json.JsonNumber (double value) { throw null; } public static implicit operator System.Text.Json.JsonNumber (short value) { throw null; } public static implicit operator System.Text.Json.JsonNumber (int value) { throw null; } @@ -313,22 +324,26 @@ public JsonNumber(ulong value) { } public static implicit operator System.Text.Json.JsonNumber (uint value) { throw null; } [System.CLSCompliantAttribute(false)] public static implicit operator System.Text.Json.JsonNumber (ulong value) { throw null; } + public static bool operator !=(System.Text.Json.JsonNumber left, System.Text.Json.JsonNumber right) { throw null; } public void SetByte(byte value) { } + public void SetDecimal(decimal value) { } public void SetDouble(double value) { } + public void SetFormattedValue(string value) { } public void SetInt16(short value) { } public void SetInt32(int value) { } public void SetInt64(long value) { } [System.CLSCompliantAttribute(false)] public void SetSByte(sbyte value) { } public void SetSingle(float value) { } - public void SetString(string value) { } [System.CLSCompliantAttribute(false)] public void SetUInt16(ushort value) { } [System.CLSCompliantAttribute(false)] public void SetUInt32(uint value) { } [System.CLSCompliantAttribute(false)] public void SetUInt64(ulong value) { } + public override string ToString() { throw null; } public bool TryGetByte(out byte value) { throw null; } + public bool TryGetDecimal(out decimal value) { throw null; } public bool TryGetDouble(out double value) { throw null; } public bool TryGetInt16(out short value) { throw null; } public bool TryGetInt32(out int value) { throw null; } @@ -354,6 +369,7 @@ public void Add(System.Collections.Generic.KeyValuePair propertyValue) { } + public void Add(string propertyName, decimal propertyValue) { } public void Add(string propertyName, double propertyValue) { } public void Add(string propertyName, short propertyValue) { } public void Add(string propertyName, int propertyValue) { } @@ -445,14 +461,17 @@ public JsonSerializerOptions() { } public bool WriteIndented { get { throw null; } set { } } public System.Text.Json.Serialization.JsonConverter GetConverter(System.Type typeToConvert) { throw null; } } - public partial class JsonString : System.Text.Json.JsonNode + public partial class JsonString : System.Text.Json.JsonNode, System.IEquatable { public JsonString() { } public JsonString(string value) { } public string Value { get { throw null; } set { } } public override bool Equals(object obj) { throw null; } + public bool Equals(System.Text.Json.JsonString other) { throw null; } public override int GetHashCode() { throw null; } + public static bool operator ==(System.Text.Json.JsonString left, System.Text.Json.JsonString right) { throw null; } public static implicit operator System.Text.Json.JsonString (string value) { throw null; } + public static bool operator !=(System.Text.Json.JsonString left, System.Text.Json.JsonString right) { throw null; } } public enum JsonTokenType : byte { diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs index c2abffde5a74..d3cd46ca3873 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs @@ -30,6 +30,7 @@ public JsonArray(IEnumerable values) { } public JsonArray(IEnumerable values) { } [CLSCompliant(false)] public JsonArray(IEnumerable values) { } + public JsonArray(IEnumerable values) { } public JsonNode this[int idx] { get => throw null; set => throw null; } @@ -50,6 +51,7 @@ public void Add(ushort value) { } public void Add(uint value) { } [CLSCompliant(false)] public void Add(ulong value) { } + public void Add(decimal value) { } public void Insert(int index, JsonNode item) { throw null; } public void Insert(int index, string item) { throw null; } @@ -68,6 +70,7 @@ public void Add(ulong value) { } public void Insert(int index, uint item) { throw null; } [CLSCompliant(false)] public void Insert(int index, ulong item) { throw null; } + public void Insert(int index, decimal item) { throw null; } public bool Contains(JsonNode value) { throw null; } public bool Contains(string value) { throw null; } @@ -86,6 +89,7 @@ public void Add(ulong value) { } public bool Contains(uint value) { throw null; } [CLSCompliant(false)] public bool Contains(ulong value) { throw null; } + public bool Contains(decimal value) { throw null; } public int Count => throw null; public bool IsReadOnly => throw null; diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs index c18f85b01b32..c0768d810fdb 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs @@ -7,7 +7,7 @@ namespace System.Text.Json { - public partial class JsonBoolean : JsonNode + public partial class JsonBoolean : JsonNode, IEquatable { public JsonBoolean() { } public JsonBoolean(bool value) { } @@ -18,7 +18,11 @@ public JsonBoolean(bool value) { } public override bool Equals(object obj) { throw null; } public override int GetHashCode() { throw null; } + + public bool Equals(JsonBoolean other) { throw null; } + + public static bool operator ==(JsonBoolean left, JsonBoolean right) => throw null; + public static bool operator !=(JsonBoolean left, JsonBoolean right) => throw null; } } - #pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 7a9fd6337015..adae60a4f28c 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -5,91 +5,171 @@ // for now disabling error caused by not adding documentation to methods #pragma warning disable CS1591 +using System.Buffers; + namespace System.Text.Json { - public partial class JsonNumber : JsonNode + public partial class JsonNumber : JsonNode, IEquatable { - public JsonNumber() { } - public JsonNumber(string value) { } - public JsonNumber(byte value) { } - public JsonNumber(short value) { } - public JsonNumber(int value) { } - public JsonNumber(long value) { } - public JsonNumber(float value) { } - public JsonNumber(double value) { } - [CLSCompliant(false)] - public JsonNumber(sbyte value) { } - [CLSCompliant(false)] - public JsonNumber(ushort value) { } - [CLSCompliant(false)] - public JsonNumber(uint value) { } - [CLSCompliant(false)] - public JsonNumber(ulong value) { } + private string _value; - public string GetString() { throw null; } - public byte GetByte() { throw null; } - public int GetInt32() { throw null; } - public short GetInt16() { throw null; } - public long GetInt64() { throw null; } - public float GetSingle() { throw null; } - public double GetDouble() { throw null; } - [CLSCompliant(false)] - public sbyte GetSByte() { throw null; } - [CLSCompliant(false)] - public ushort GetUInt16() { throw null; } - [CLSCompliant(false)] - public uint GetUInt32() { throw null; } - [CLSCompliant(false)] - public ulong GetUInt64() { throw null; } + public JsonNumber() => _value = "0"; - public bool TryGetByte(out byte value) { throw null; } - public bool TryGetInt32(out int value) { throw null; } - public bool TryGetInt16(out short value) { throw null; } - public bool TryGetInt64(out long value) { throw null; } - public bool TryGetSingle(out float value) { throw null; } - public bool TryGetDouble(out double value) { throw null; } - [CLSCompliant(false)] - public bool TryGetSByte(out sbyte value) { throw null; } - [CLSCompliant(false)] - public bool TryGetUInt16(out ushort value) { throw null; } - [CLSCompliant(false)] - public bool TryGetUInt32(out uint value) { throw null; } - [CLSCompliant(false)] - public bool TryGetUInt64(out ulong value) { throw null; } + public JsonNumber(string value) => SetFormattedValue(value); + + public JsonNumber(byte value) => SetByte(value); + + public JsonNumber(short value) => SetInt16(value); + + public JsonNumber(int value) => SetInt32(value); + + public JsonNumber(long value) => SetInt64(value); + + public JsonNumber(float value) => SetSingle(value); + + public JsonNumber(double value) => SetDouble(value); + + [CLSCompliant(false)] + public JsonNumber(sbyte value) => SetSByte(value); + + [CLSCompliant(false)] + public JsonNumber(ushort value) => SetUInt16(value); + + [CLSCompliant(false)] + public JsonNumber(uint value) => SetUInt32(value); + + [CLSCompliant(false)] + public JsonNumber(ulong value) => SetUInt64(value); - public void SetString(string value) { } - public void SetByte(byte value) { } - public void SetInt32(int value) { } - public void SetInt16(short value) { } - public void SetInt64(long value) { } - public void SetSingle(float value) { } - public void SetDouble(double value) { } - [CLSCompliant(false)] - public void SetSByte(sbyte value) { } - [CLSCompliant(false)] - public void SetUInt16(ushort value) { } - [CLSCompliant(false)] - public void SetUInt32(uint value) { } - [CLSCompliant(false)] - public void SetUInt64(ulong value) { } + public JsonNumber(decimal value) => SetDecimal(value); + + public override string ToString() => _value; + + public byte GetByte() => byte.Parse(_value); + + public short GetInt16() => short.Parse(_value); + + public int GetInt32() => int.Parse(_value); + + public long GetInt64() => long.Parse(_value); + + public float GetSingle() => float.Parse(_value); + + public double GetDouble() => double.Parse(_value); + + [CLSCompliant(false)] + public sbyte GetSByte() => sbyte.Parse(_value); + + [CLSCompliant(false)] + public ushort GetUInt16() => ushort.Parse(_value); + + [CLSCompliant(false)] + public uint GetUInt32() => uint.Parse(_value); + + [CLSCompliant(false)] + public ulong GetUInt64() => ulong.Parse(_value); + + public decimal GetDecimal() => decimal.Parse(_value); + + public bool TryGetByte(out byte value) => byte.TryParse(_value, out value); + + public bool TryGetInt16(out short value) => short.TryParse(_value, out value); + + public bool TryGetInt32(out int value) => int.TryParse(_value, out value); + + public bool TryGetInt64(out long value) => long.TryParse(_value, out value); + + public bool TryGetSingle(out float value) => float.TryParse(_value, out value); + + public bool TryGetDouble(out double value) => double.TryParse(_value, out value); - public static implicit operator JsonNumber(byte value) { throw null; } - public static implicit operator JsonNumber(int value) { throw null; } - public static implicit operator JsonNumber(short value) { throw null; } - public static implicit operator JsonNumber(long value) { throw null; } - public static implicit operator JsonNumber(float value) { throw null; } - public static implicit operator JsonNumber(double value) { throw null; } [CLSCompliant(false)] - public static implicit operator JsonNumber(sbyte value) { throw null; } + public bool TryGetSByte(out sbyte value) => sbyte.TryParse(_value, out value); + [CLSCompliant(false)] - public static implicit operator JsonNumber(ushort value) { throw null; } + public bool TryGetUInt16(out ushort value) => ushort.TryParse(_value, out value); + [CLSCompliant(false)] - public static implicit operator JsonNumber(uint value) { throw null; } + public bool TryGetUInt32(out uint value) => uint.TryParse(_value, out value); + [CLSCompliant(false)] - public static implicit operator JsonNumber(ulong value) { throw null; } + public bool TryGetUInt64(out ulong value) => ulong.TryParse(_value, out value); + + public bool TryGetDecimal(out decimal value) => decimal.TryParse(_value, out value); + + + public void SetFormattedValue(string value) + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + if (value.Length == 0) + throw new ArgumentException("Expected number, but instead got empty string.", nameof(value)); + + JsonWriterHelper.ValidateNumber(Encoding.UTF8.GetBytes(value).AsSpan()); + _value = value; + } + + public void SetByte(byte value) => _value = value.ToString(); + + public void SetInt16(short value) => _value = value.ToString(); + + public void SetInt32(int value) => _value = value.ToString(); + + public void SetInt64(long value) => _value = value.ToString(); + + public void SetSingle(float value) => _value = value.ToString(); + + public void SetDouble(double value) => _value = value.ToString(); + + [CLSCompliant(false)] + public void SetSByte(sbyte value) => _value = value.ToString(); + + [CLSCompliant(false)] + public void SetUInt16(ushort value) => _value = value.ToString(); + + [CLSCompliant(false)] + public void SetUInt32(uint value) => _value = value.ToString(); + + [CLSCompliant(false)] + public void SetUInt64(ulong value) => _value = value.ToString(); + + public void SetDecimal(decimal value) => _value = value.ToString(); + + public static implicit operator JsonNumber(byte value) => new JsonNumber(value); + + public static implicit operator JsonNumber(int value) => new JsonNumber(value); + + public static implicit operator JsonNumber(short value) => new JsonNumber(value); + + public static implicit operator JsonNumber(long value) => new JsonNumber(value); + + public static implicit operator JsonNumber(float value) => new JsonNumber(value); + + public static implicit operator JsonNumber(double value) => new JsonNumber(value); + + [CLSCompliant(false)] + public static implicit operator JsonNumber(sbyte value) => new JsonNumber(value); + + [CLSCompliant(false)] + public static implicit operator JsonNumber(ushort value) => new JsonNumber(value); + + [CLSCompliant(false)] + public static implicit operator JsonNumber(uint value) => new JsonNumber(value); + + [CLSCompliant(false)] + public static implicit operator JsonNumber(ulong value) => new JsonNumber(value); + + public static implicit operator JsonNumber(decimal value) => new JsonNumber(value); + + public override bool Equals(object obj) => obj is JsonNumber number && _value == number._value; + + public override int GetHashCode() => _value.GetHashCode(); + + public bool Equals(JsonNumber other) => _value == other._value; - public override bool Equals(object obj) { throw null; } - public override int GetHashCode() { throw null; } + public static bool operator ==(JsonNumber left, JsonNumber right) => left._value == right._value; + + public static bool operator !=(JsonNumber left, JsonNumber right) => left._value != right._value; } } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs index 5955e1fd3eea..0c285632c84d 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs @@ -37,6 +37,7 @@ public void Add(string propertyName, ushort propertyValue) { } public void Add(string propertyName, uint propertyValue) { } [CLSCompliant(false)] public void Add(string propertyName, ulong propertyValue) { } + public void Add(string propertyName, decimal propertyValue) { } public void Add(string propertyName, IEnumerable propertyValue) { } public void AddRange(IEnumerable> jsonProperties) { } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs index 9c993375209c..99c701c50ece 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs @@ -7,7 +7,7 @@ namespace System.Text.Json { - public partial class JsonString : JsonNode + public partial class JsonString : JsonNode, IEquatable { public JsonString() { } public JsonString(string value) { } @@ -18,6 +18,11 @@ public JsonString(string value) { } public override bool Equals(object obj) { throw null; } public override int GetHashCode() { throw null; } + + public bool Equals(JsonString other) { throw null; } + + public static bool operator ==(JsonString left, JsonString right) => throw null; + public static bool operator !=(JsonString left, JsonString right) => throw null; } } diff --git a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj index 14b23aa2f3ac..7a9dcd5ce226 100644 --- a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -107,6 +107,7 @@ + diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.JsonNumberUnitTests.cs b/src/System.Text.Json/tests/WritableJsonApiTests.JsonNumberUnitTests.cs new file mode 100644 index 000000000000..2f32a32588da --- /dev/null +++ b/src/System.Text.Json/tests/WritableJsonApiTests.JsonNumberUnitTests.cs @@ -0,0 +1,473 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Text.Json +{ + public static partial class WritableJsonApiTests + { + [Theory] + [InlineData(-456)] + [InlineData(0)] + [InlineData(17)] + [InlineData(long.MaxValue)] + [InlineData(2.3)] + [InlineData(-17.009)] + [InlineData(3.14f)] + [InlineData(0x2A)] + [InlineData(0b_0110_1010)] + [InlineData("1e400")] + [InlineData("1e+100000002")] + [InlineData("184467440737095516150.184467440737095516150")] + public static void TestJsonNumberConstructor(object value) + { + // should not throw any exceptions: + _ = new JsonNumber(value as dynamic); + } + + [Fact] + public static void TestDefaultCtor() + { + var jsonNumber = new JsonNumber(); + Assert.Equal(0, jsonNumber.GetInt32()); + } + + [Theory] + [InlineData(0)] + [InlineData(17)] + [InlineData(255)] + public static void TestByte(byte value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetByte(value); + Assert.Equal(value, jsonNumber.GetByte()); + Assert.True(jsonNumber.TryGetByte(out byte result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(-17)] + [InlineData(17)] + [InlineData(short.MinValue)] + [InlineData(short.MaxValue)] + public static void TestShort(short value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetInt16(value); + Assert.Equal(value, jsonNumber.GetInt16()); + Assert.True(jsonNumber.TryGetInt16(out short result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(-17)] + [InlineData(17)] + [InlineData(int.MinValue)] + [InlineData(int.MaxValue)] + public static void TestInt(int value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetInt32(value); + Assert.Equal(value, jsonNumber.GetInt32()); + Assert.True(jsonNumber.TryGetInt32(out int result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(-17)] + [InlineData(17)] + [InlineData(long.MinValue)] + [InlineData(long.MaxValue)] + public static void TestLong(long value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetInt64(value); + Assert.Equal(value, jsonNumber.GetInt64()); + Assert.True(jsonNumber.TryGetInt64(out long result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(17)] + [InlineData(-17)] + [InlineData(3.14)] + [InlineData(-15.5)] + [InlineData(float.MinValue)] + [InlineData(float.MaxValue)] + public static void TestFloat(float value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetSingle(value); + Assert.Equal(value, jsonNumber.GetSingle()); + Assert.True(jsonNumber.TryGetSingle(out float result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(17)] + [InlineData(-17)] + [InlineData(3.14)] + [InlineData(-15.5)] + [InlineData(double.MinValue)] + [InlineData(double.MaxValue)] + public static void TestDouble(double value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetDouble(value); + Assert.Equal(value, jsonNumber.GetDouble()); + Assert.True(jsonNumber.TryGetDouble(out double result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(17)] + [InlineData(-17)] + [InlineData(sbyte.MinValue)] + [InlineData(sbyte.MaxValue)] + public static void TestSbyte(sbyte value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetSByte(value); + Assert.Equal(value, jsonNumber.GetSByte()); + Assert.True(jsonNumber.TryGetSByte(out sbyte result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(17)] + [InlineData(ushort.MaxValue)] + public static void TestUInt16(ushort value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetUInt16(value); + Assert.Equal(value, jsonNumber.GetUInt16()); + Assert.True(jsonNumber.TryGetUInt16(out ushort result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(17)] + [InlineData(uint.MaxValue)] + public static void TestUInt32(uint value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetUInt32(value); + Assert.Equal(value, jsonNumber.GetUInt32()); + Assert.True(jsonNumber.TryGetUInt32(out uint result)); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(0)] + [InlineData(17)] + [InlineData(ulong.MaxValue)] + public static void TestUInt64(ulong value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetUInt64(value); + Assert.Equal(value, jsonNumber.GetUInt64()); + Assert.True(jsonNumber.TryGetUInt64(out ulong result)); + Assert.Equal(value, result); + } + + [Fact] + public static void TestDecimal() + { + var decimalValue = decimal.MaxValue; + var jsonNumber = new JsonNumber(); + jsonNumber.SetDecimal(decimalValue); + Assert.Equal(decimalValue, jsonNumber.GetDecimal()); + Assert.True(jsonNumber.TryGetDecimal(out decimal result)); + Assert.Equal(decimalValue, result); + } + + [Theory] + [InlineData("3.14")] + [InlineData("-17")] + [InlineData("0")] + [InlineData("189")] + [InlineData("1e400")] + [InlineData("1e+100000002")] + [InlineData("184467440737095516150.184467440737095516150")] + public static void TestString(string value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetFormattedValue(value); + Assert.Equal(value, jsonNumber.ToString()); + } + + [Theory] + [InlineData("")] + [InlineData("3,14")] + [InlineData("this is not a number")] + [InlineData("NAN")] + [InlineData("0.")] + [InlineData("008")] + [InlineData("0e")] + [InlineData("5e")] + [InlineData("5a")] + [InlineData("0.1e")] + [InlineData("-01")] + [InlineData("10.5e")] + [InlineData("10.5e-")] + [InlineData("10.5e+")] + [InlineData("10.5e-0.2")] + [InlineData(" 6")] + [InlineData("6 ")] + [InlineData(" 6 ")] + [InlineData("+0")] + [InlineData("+1")] + public static void TestInvalidString(string value) + { + Assert.Throws(() => new JsonNumber(value)); + } + + [Fact] + public static void TestNullString() + { + Assert.Throws(() => new JsonNumber(null)); + } + + [Fact] + public static void TestIntFromString() + { + var jsonNumber = new JsonNumber("145"); + Assert.Equal(145, jsonNumber.GetInt32()); + } + + [Fact] + public static void TestUpcasts() + { + byte value = 17; + var jsonNumber = new JsonNumber(value); + + // Getting other types should also succeed: + Assert.Equal(value, jsonNumber.GetInt16()); + Assert.True(jsonNumber.TryGetInt16(out short shortResult)); + Assert.Equal(value, shortResult); + + Assert.Equal(value, jsonNumber.GetInt32()); + Assert.True(jsonNumber.TryGetInt32(out int intResult)); + Assert.Equal(value, intResult); + + Assert.Equal(value, jsonNumber.GetInt64()); + Assert.True(jsonNumber.TryGetInt64(out long longResult)); + Assert.Equal(value, longResult); + + Assert.Equal(value, jsonNumber.GetSingle()); + Assert.True(jsonNumber.TryGetSingle(out float floatResult)); + Assert.Equal(value, floatResult); + + Assert.Equal(value, jsonNumber.GetDouble()); + Assert.True(jsonNumber.TryGetDouble(out double doubleResult)); + Assert.Equal(value, doubleResult); + + Assert.Equal(value, (byte)jsonNumber.GetSByte()); + Assert.True(jsonNumber.TryGetSByte(out sbyte sbyteResult)); + Assert.Equal(value, (byte)sbyteResult); + + Assert.Equal(value, jsonNumber.GetUInt16()); + Assert.True(jsonNumber.TryGetUInt16(out ushort ushortResult)); + Assert.Equal(value, ushortResult); + + Assert.Equal(value, jsonNumber.GetUInt32()); + Assert.True(jsonNumber.TryGetUInt32(out uint uintResult)); + Assert.Equal(value, uintResult); + + Assert.Equal(value, jsonNumber.GetUInt64()); + Assert.True(jsonNumber.TryGetUInt64(out ulong ulongResult)); + Assert.Equal(value, ulongResult); + + Assert.Equal(value, jsonNumber.GetDecimal()); + Assert.True(jsonNumber.TryGetDecimal(out decimal decimalResult)); + Assert.Equal(value, decimalResult); + } + + [Fact] + public static void TestIntegerGetMismatches() + { + var jsonNumber = new JsonNumber(long.MaxValue); + + // Getting smaller types should fail: + Assert.False(jsonNumber.TryGetByte(out byte byteResult)); + Assert.Throws(() => jsonNumber.GetByte()); + + Assert.False(jsonNumber.TryGetInt16(out short shortResult)); + Assert.Throws(() => jsonNumber.GetInt16()); + + Assert.False(jsonNumber.TryGetInt32(out int intResult)); + Assert.Throws(() => jsonNumber.GetInt32()); + + Assert.False(jsonNumber.TryGetSByte(out sbyte sbyteResult)); + Assert.Throws(() => jsonNumber.GetSByte()); + + Assert.False(jsonNumber.TryGetUInt16(out ushort ushortResult)); + Assert.Throws(() => jsonNumber.GetUInt16()); + + Assert.False(jsonNumber.TryGetUInt32(out uint uintResult)); + Assert.Throws(() => jsonNumber.GetUInt32()); + } + + [Fact] + public static void TestUnsignedGetMismatches() + { + var jsonNumber = new JsonNumber("-1"); + + // Getting unsigned types should fail: + Assert.False(jsonNumber.TryGetByte(out byte byteResult)); + Assert.Throws(() => jsonNumber.GetByte()); + + Assert.False(jsonNumber.TryGetUInt16(out ushort ushortResult)); + Assert.Throws(() => jsonNumber.GetUInt16()); + + Assert.False(jsonNumber.TryGetUInt32(out uint uintResult)); + Assert.Throws(() => jsonNumber.GetUInt32()); + + Assert.False(jsonNumber.TryGetUInt64(out ulong ulongResult)); + Assert.Throws(() => jsonNumber.GetUInt64()); + } + + [Fact] + public static void TestRationalGetMismatches() + { + var jsonNumber = new JsonNumber("3.14"); + + // Getting integer types should fail: + Assert.False(jsonNumber.TryGetByte(out byte byteResult)); + Assert.Throws(() => jsonNumber.GetByte()); + + Assert.False(jsonNumber.TryGetInt16(out short shortResult)); + Assert.Throws(() => jsonNumber.GetInt16()); + + Assert.False(jsonNumber.TryGetInt32(out int intResult)); + Assert.Throws(() => jsonNumber.GetInt32()); + + Assert.False(jsonNumber.TryGetInt64(out long longResult)); + Assert.Throws(() => jsonNumber.GetInt64()); + + Assert.False(jsonNumber.TryGetSByte(out sbyte sbyteResult)); + Assert.Throws(() => jsonNumber.GetSByte()); + + Assert.False(jsonNumber.TryGetUInt16(out ushort ushortResult)); + Assert.Throws(() => jsonNumber.GetUInt16()); + + Assert.False(jsonNumber.TryGetUInt32(out uint uintResult)); + Assert.Throws(() => jsonNumber.GetUInt32()); + + Assert.False(jsonNumber.TryGetUInt64(out ulong ulongResult)); + Assert.Throws(() => jsonNumber.GetUInt64()); + } + + [Theory] + [InlineData("0")] + [InlineData("-17")] + [InlineData("17")] + [InlineData("3.14")] + [InlineData("-3.1415")] + [InlineData("1234567890")] + [InlineData("1e400")] + [InlineData("1e+100000002")] + [InlineData("184467440737095516150.184467440737095516150")] + public static void TestToString(string value) + { + var jsonNumber = new JsonNumber(); + jsonNumber.SetFormattedValue(value); + Assert.Equal(value, jsonNumber.ToString()); + } + + [Fact] + public static void TestChangingTypes() + { + var jsonNumber = new JsonNumber(5); + Assert.Equal(5, jsonNumber.GetInt32()); + + jsonNumber.SetDouble(3.14); + Assert.Equal(3.14, jsonNumber.GetDouble()); + + jsonNumber.SetByte(17); + Assert.Equal(17, jsonNumber.GetByte()); + + jsonNumber.SetInt64(long.MaxValue); + Assert.Equal(long.MaxValue, jsonNumber.GetInt64()); + + jsonNumber.SetUInt16(ushort.MaxValue); + Assert.Equal(ushort.MaxValue, jsonNumber.GetUInt16()); + + jsonNumber.SetSingle(-1.1f); + Assert.Equal(-1.1f, jsonNumber.GetSingle()); + + jsonNumber.SetSByte(4); + Assert.Equal(4, jsonNumber.GetSByte()); + + jsonNumber.SetUInt32(127); + Assert.Equal((uint)127, jsonNumber.GetUInt32()); + + jsonNumber.SetFormattedValue("1e400"); + Assert.Equal("1e400", jsonNumber.ToString()); + + jsonNumber.SetUInt64(ulong.MaxValue); + Assert.Equal(ulong.MaxValue, jsonNumber.GetUInt64()); + + jsonNumber.SetDecimal(decimal.MaxValue); + Assert.Equal(decimal.MaxValue, jsonNumber.GetDecimal()); + } + + [Fact] + public static void TestImplicitOperators() + { + byte byteValue = byte.MaxValue; + JsonNumber jsonNumber = byteValue; + Assert.Equal(byteValue, jsonNumber.GetByte()); + + short shortValue = short.MaxValue; + jsonNumber = shortValue; + Assert.Equal(shortValue, jsonNumber.GetInt16()); + + int intValue = int.MaxValue; + jsonNumber = intValue; + Assert.Equal(intValue, jsonNumber.GetInt32()); + + long longValue = long.MaxValue; + jsonNumber = longValue; + Assert.Equal(longValue, jsonNumber.GetInt64()); + + float floatValue = float.MaxValue; + jsonNumber = floatValue; + Assert.Equal(floatValue, jsonNumber.GetSingle()); + + double doubleValue = double.MaxValue; + jsonNumber = doubleValue; + Assert.Equal(doubleValue, jsonNumber.GetDouble()); + + sbyte sbyteValue = sbyte.MaxValue; + jsonNumber = sbyteValue; + Assert.Equal(sbyteValue, jsonNumber.GetSByte()); + + ushort ushortValue = ushort.MaxValue; + jsonNumber = ushortValue; + Assert.Equal(ushortValue, jsonNumber.GetUInt16()); + + uint uintValue = uint.MaxValue; + jsonNumber = uintValue; + Assert.Equal(uintValue, jsonNumber.GetUInt32()); + + ulong ulongValue = ulong.MaxValue; + jsonNumber = ulongValue; + Assert.Equal(ulongValue, jsonNumber.GetUInt64()); + + decimal decimalValue = decimal.MaxValue; + jsonNumber = decimalValue; + Assert.Equal(decimalValue, jsonNumber.GetDecimal()); + } + } +} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs index cf5b586c7f52..7f3c19d05520 100644 --- a/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs @@ -6,9 +6,7 @@ namespace System.Text.Json { -#pragma warning disable xUnit1000 - internal static partial class WritableJsonApiTests -#pragma warning enable xUnit1000 + public static partial class WritableJsonApiTests { /// /// Accesing nested Json object - casting with as operator @@ -139,8 +137,8 @@ public static void TestAccesingNestedJsonArrayGetPropertyMethod() ((JsonString)issues.GetJsonArrayProperty("features")[1]).Value = "feature 56134"; Assert.True(((JsonArray)issues["bugs"]).Contains("bug 12356")); - Assert.Equal((JsonString)((JsonArray)issues["features"])[0], "feature 1569"); - Assert.Equal((JsonString)((JsonArray)issues["features"])[1], "feature 56134"); + Assert.Equal("feature 1569", (JsonString)((JsonArray)issues["features"])[0]); + Assert.Equal("feature 56134", (JsonString)((JsonArray)issues["features"])[1]); } } } diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs index e53f85379232..be61a4821844 100644 --- a/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs @@ -6,9 +6,7 @@ namespace System.Text.Json { -#pragma warning disable xUnit1000 - internal static partial class WritableJsonApiTests -#pragma warning enable xUnit1000 + public static partial class WritableJsonApiTests { /// /// Helper class simulating external library diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs index e4885b5074b4..6ef4d2659d6c 100644 --- a/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs @@ -7,9 +7,7 @@ namespace System.Text.Json { -#pragma warning disable xUnit1000 - internal static partial class WritableJsonApiTests -#pragma warning enable xUnit1000 + public static partial class WritableJsonApiTests { /// /// Replacing Json object's primnary types @@ -28,20 +26,20 @@ public static void TestReplacingsonObjectPrimaryTypes() person1["name"] = new JsonString("Bob"); Assert.IsType(person1["name"]); - Assert.Equal(person1["name"] as JsonString, "Bob"); + Assert.Equal("Bob", person1["name"] as JsonString); // Assign by using an implicit operator on primary Json type JsonNumber newAge = 55; person1["age"] = newAge; Assert.IsType(person1["age"]); - Assert.Equal(person1["age"] as JsonNumber, 55); + Assert.Equal(55, person1["age"] as JsonNumber); // Assign by explicit cast from Json primary type person1["is_married"] = (JsonBoolean)false; Assert.IsType(person1["is_married"]); - Assert.Equal(person1["is_married"] as JsonBoolean, false); + Assert.Equal(false, person1["is_married"] as JsonBoolean); // Not possible scenario (wold require implicit cast operators in JsonNode): // person["name"] = "Bob"; @@ -57,7 +55,7 @@ public static void TestReplacingsonObjectPrimaryTypes() person1["age"] = person2["age"]; Assert.IsType(person1["age"]); - Assert.Equal(person1["age"] as JsonNumber, 33); + Assert.Equal(33, person1["age"] as JsonNumber); // Copy property of different typoe person1["name"] = person2["name"]; @@ -83,8 +81,8 @@ public static void TestModifyingJsonObjectPrimaryTypes() Assert.True(isEnabled.Value); JsonNumber veryBigConstant = new JsonNumber(); - veryBigConstant.SetString("1e1000"); - string bigNumber = veryBigConstant.GetString(); + veryBigConstant.SetFormattedValue("1e1000"); + string bigNumber = veryBigConstant.ToString(); Assert.Equal("1e1000", bigNumber); diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs index 0b6a5d96ecbc..1707757dcd42 100644 --- a/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs +++ b/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs @@ -8,9 +8,7 @@ namespace System.Text.Json { -#pragma warning disable xUnit1000 - internal static partial class WritableJsonApiTests -#pragma warning enable xUnit1000 + public static partial class WritableJsonApiTests { /// /// Transforming JsoneNode to JsonElement diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.cs b/src/System.Text.Json/tests/WritableJsonApiTests.cs index e45bff09e714..18856a103cb6 100644 --- a/src/System.Text.Json/tests/WritableJsonApiTests.cs +++ b/src/System.Text.Json/tests/WritableJsonApiTests.cs @@ -8,9 +8,7 @@ namespace System.Text.Json { -#pragma warning disable xUnit1000 - internal static partial class WritableJsonApiTests -#pragma warning enable xUnit1000 + public static partial class WritableJsonApiTests { /// /// Creating simple Json object @@ -36,7 +34,7 @@ public static void TestCreatingJsonObject() Assert.IsType(developer["is developer"]); var isDeveloperCasted = developer["is developer"] as JsonBoolean; - Assert.Equal(true, isDeveloperCasted.Value); + Assert.True(isDeveloperCasted.Value); Assert.Null(developer["null property"]); } @@ -64,7 +62,7 @@ public static void TestCreatingJsonObjectNewMethods() Assert.IsType(developer["is developer"]); var isDeveloperCasted = developer["is developer"] as JsonBoolean; - Assert.Equal(true, isDeveloperCasted.Value); + Assert.True(isDeveloperCasted.Value); } /// @@ -83,7 +81,7 @@ public static void TestNumerics() Assert.IsType(circle["radius"]); var radius = circle["radius"] as JsonNumber; - Assert.Equal(radius, 1); + Assert.Equal(1, radius); Assert.IsType(circle["length"]); var length = circle["length"] as JsonNumber; From 08f4734bfbe4c8c5209821f74c839bf942cc1d87 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Tue, 30 Jul 2019 14:10:39 -0700 Subject: [PATCH 06/30] all unimplemented classes and methods with accompanying tests removed --- src/System.Text.Json/ref/System.Text.Json.cs | 164 ------ .../src/System.Text.Json.csproj | 4 - .../src/System/Text/Json/Node/JsonArray.cs | 109 ---- .../src/System/Text/Json/Node/JsonBoolean.cs | 28 - .../src/System/Text/Json/Node/JsonNode.cs | 23 +- .../src/System/Text/Json/Node/JsonNumber.cs | 2 - .../src/System/Text/Json/Node/JsonObject.cs | 65 -- .../src/System/Text/Json/Node/JsonString.cs | 29 - .../tests/System.Text.Json.Tests.csproj | 5 - ...JsonApiTests.TestAccessingNestedMembers.cs | 144 ----- .../tests/WritableJsonApiTests.TestData.cs | 134 ----- .../WritableJsonApiTests.TestModifying.cs | 173 ------ ...ritableJsonApiTests.TestTransformations.cs | 230 -------- .../tests/WritableJsonApiTests.cs | 553 ------------------ 14 files changed, 3 insertions(+), 1660 deletions(-) delete mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs delete mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs delete mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs delete mode 100644 src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs delete mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs delete mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs delete mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs delete mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs delete mode 100644 src/System.Text.Json/tests/WritableJsonApiTests.cs diff --git a/src/System.Text.Json/ref/System.Text.Json.cs b/src/System.Text.Json/ref/System.Text.Json.cs index 6164b2372c0c..0e1aa80d4932 100644 --- a/src/System.Text.Json/ref/System.Text.Json.cs +++ b/src/System.Text.Json/ref/System.Text.Json.cs @@ -7,105 +7,6 @@ namespace System.Text.Json { - public partial class JsonArray : System.Text.Json.JsonNode, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable - { - public JsonArray() { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - [System.CLSCompliantAttribute(false)] - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public JsonArray(System.Collections.Generic.IEnumerable values) { } - [System.CLSCompliantAttribute(false)] - public JsonArray(System.Collections.Generic.IEnumerable values) { } - [System.CLSCompliantAttribute(false)] - public JsonArray(System.Collections.Generic.IEnumerable values) { } - [System.CLSCompliantAttribute(false)] - public JsonArray(System.Collections.Generic.IEnumerable values) { } - public int Count { get { throw null; } } - public bool IsReadOnly { get { throw null; } } - public System.Text.Json.JsonNode this[int idx] { get { throw null; } set { } } - public void Add(bool value) { } - public void Add(byte value) { } - public void Add(decimal value) { } - public void Add(double value) { } - public void Add(short value) { } - public void Add(int value) { } - public void Add(long value) { } - [System.CLSCompliantAttribute(false)] - public void Add(sbyte value) { } - public void Add(float value) { } - public void Add(string value) { } - public void Add(System.Text.Json.JsonNode value) { } - [System.CLSCompliantAttribute(false)] - public void Add(ushort value) { } - [System.CLSCompliantAttribute(false)] - public void Add(uint value) { } - [System.CLSCompliantAttribute(false)] - public void Add(ulong value) { } - public void Clear() { } - public bool Contains(bool value) { throw null; } - public bool Contains(byte value) { throw null; } - public bool Contains(decimal value) { throw null; } - public bool Contains(double value) { throw null; } - public bool Contains(short value) { throw null; } - public bool Contains(int value) { throw null; } - public bool Contains(long value) { throw null; } - [System.CLSCompliantAttribute(false)] - public bool Contains(sbyte value) { throw null; } - public bool Contains(float value) { throw null; } - public bool Contains(string value) { throw null; } - public bool Contains(System.Text.Json.JsonNode value) { throw null; } - [System.CLSCompliantAttribute(false)] - public bool Contains(ushort value) { throw null; } - [System.CLSCompliantAttribute(false)] - public bool Contains(uint value) { throw null; } - [System.CLSCompliantAttribute(false)] - public bool Contains(ulong value) { throw null; } - public System.Collections.Generic.IEnumerator GetEnumerator() { throw null; } - public int IndexOf(System.Text.Json.JsonNode item) { throw null; } - public void Insert(int index, bool item) { } - public void Insert(int index, byte item) { } - public void Insert(int index, decimal item) { } - public void Insert(int index, double item) { } - public void Insert(int index, short item) { } - public void Insert(int index, int item) { } - public void Insert(int index, long item) { } - [System.CLSCompliantAttribute(false)] - public void Insert(int index, sbyte item) { } - public void Insert(int index, float item) { } - public void Insert(int index, string item) { } - public void Insert(int index, System.Text.Json.JsonNode item) { } - [System.CLSCompliantAttribute(false)] - public void Insert(int index, ushort item) { } - [System.CLSCompliantAttribute(false)] - public void Insert(int index, uint item) { } - [System.CLSCompliantAttribute(false)] - public void Insert(int index, ulong item) { } - public int LastIndexOf(System.Text.Json.JsonNode item) { throw null; } - public bool Remove(System.Text.Json.JsonNode item) { throw null; } - public void RemoveAt(int index) { } - void System.Collections.Generic.ICollection.CopyTo(System.Text.Json.JsonNode[] array, int arrayIndex) { } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - } - public partial class JsonBoolean : System.Text.Json.JsonNode, System.IEquatable - { - public JsonBoolean() { } - public JsonBoolean(bool value) { } - public bool Value { get { throw null; } set { } } - public override bool Equals(object obj) { throw null; } - public bool Equals(System.Text.Json.JsonBoolean other) { throw null; } - public override int GetHashCode() { throw null; } - public static bool operator ==(System.Text.Json.JsonBoolean left, System.Text.Json.JsonBoolean right) { throw null; } - public static implicit operator System.Text.Json.JsonBoolean (bool value) { throw null; } - public static bool operator !=(System.Text.Json.JsonBoolean left, System.Text.Json.JsonBoolean right) { throw null; } - } public enum JsonCommentHandling : byte { Disallow = (byte)0, @@ -259,17 +160,6 @@ protected JsonNamingPolicy() { } public abstract partial class JsonNode { internal JsonNode() { } - public System.Text.Json.JsonElement AsJsonElement() { throw null; } - public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonDocument jsonDocument) { throw null; } - public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonElement jsonElement) { throw null; } - public static System.Text.Json.JsonNode DeepCopy(System.Text.Json.JsonNode jsonNode) { throw null; } - public static System.Text.Json.JsonNode GetNode(System.Text.Json.JsonElement jsonElement) { throw null; } - public static System.Text.Json.JsonNode Parse(System.Buffers.ReadOnlySequence utf8Json) { throw null; } - public static System.Text.Json.JsonNode Parse(System.IO.Stream utf8Json) { throw null; } - public static System.Text.Json.JsonNode Parse(System.ReadOnlyMemory utf8Json) { throw null; } - public static System.Text.Json.JsonNode Parse(System.ReadOnlyMemory json) { throw null; } - public static System.Text.Json.JsonNode Parse(string json) { throw null; } - public static bool TryGetNode(System.Text.Json.JsonElement jsonElement, out System.Text.Json.JsonNode jsonNode) { throw null; } } public partial class JsonNumber : System.Text.Json.JsonNode, System.IEquatable { @@ -358,48 +248,6 @@ public void SetUInt64(ulong value) { } [System.CLSCompliantAttribute(false)] public bool TryGetUInt64(out ulong value) { throw null; } } - public partial class JsonObject : System.Text.Json.JsonNode, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable - { - public JsonObject() { } - public JsonObject(System.Collections.Generic.IEnumerable> jsonProperties) { } - public System.Text.Json.JsonNode this[string key] { get { throw null; } set { } } - public System.Collections.Generic.ICollection PropertyNames { get { throw null; } } - public System.Collections.Generic.ICollection Values { get { throw null; } } - public void Add(System.Collections.Generic.KeyValuePair jsonProperty) { } - public void Add(string propertyName, bool propertyValue) { } - public void Add(string propertyName, byte propertyValue) { } - public void Add(string propertyName, System.Collections.Generic.IEnumerable propertyValue) { } - public void Add(string propertyName, decimal propertyValue) { } - public void Add(string propertyName, double propertyValue) { } - public void Add(string propertyName, short propertyValue) { } - public void Add(string propertyName, int propertyValue) { } - public void Add(string propertyName, long propertyValue) { } - [System.CLSCompliantAttribute(false)] - public void Add(string propertyName, sbyte propertyValue) { } - public void Add(string propertyName, float propertyValue) { } - public void Add(string propertyName, string propertyValue) { } - public void Add(string propertyName, System.Text.Json.JsonArray propertyValue) { } - public void Add(string propertyName, System.Text.Json.JsonNode propertyValue) { } - [System.CLSCompliantAttribute(false)] - public void Add(string propertyName, ushort propertyValue) { } - [System.CLSCompliantAttribute(false)] - public void Add(string propertyName, uint propertyValue) { } - [System.CLSCompliantAttribute(false)] - public void Add(string propertyName, ulong propertyValue) { } - public void AddRange(System.Collections.Generic.IEnumerable> jsonProperties) { } - public bool ContainsProperty(string propertyName) { throw null; } - public System.Collections.Generic.IEnumerable GetAllProperties(string propertyName) { throw null; } - public System.Collections.Generic.IEnumerator> GetEnumerator() { throw null; } - public System.Text.Json.JsonArray GetJsonArrayProperty(string propertyName) { throw null; } - public System.Text.Json.JsonObject GetJsonObjectProperty(string propertyName) { throw null; } - public System.Text.Json.JsonNode GetProperty(string propertyName) { throw null; } - public bool ModifyPropertyName(string oldName, string newName) { throw null; } - public bool Remove(string propertyName) { throw null; } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - public bool TryGetArrayProperty(string propertyName, out System.Text.Json.JsonArray jsonArray) { throw null; } - public bool TryGetObjectProperty(string propertyName, out System.Text.Json.JsonObject jsonObject) { throw null; } - public bool TryGetProperty(string propertyName, out System.Text.Json.JsonNode jsonNode) { throw null; } - } public readonly partial struct JsonProperty { private readonly object _dummy; @@ -461,18 +309,6 @@ public JsonSerializerOptions() { } public bool WriteIndented { get { throw null; } set { } } public System.Text.Json.Serialization.JsonConverter GetConverter(System.Type typeToConvert) { throw null; } } - public partial class JsonString : System.Text.Json.JsonNode, System.IEquatable - { - public JsonString() { } - public JsonString(string value) { } - public string Value { get { throw null; } set { } } - public override bool Equals(object obj) { throw null; } - public bool Equals(System.Text.Json.JsonString other) { throw null; } - public override int GetHashCode() { throw null; } - public static bool operator ==(System.Text.Json.JsonString left, System.Text.Json.JsonString right) { throw null; } - public static implicit operator System.Text.Json.JsonString (string value) { throw null; } - public static bool operator !=(System.Text.Json.JsonString left, System.Text.Json.JsonString right) { throw null; } - } public enum JsonTokenType : byte { None = (byte)0, diff --git a/src/System.Text.Json/src/System.Text.Json.csproj b/src/System.Text.Json/src/System.Text.Json.csproj index c7a1c9fceba6..ad6319b02c15 100644 --- a/src/System.Text.Json/src/System.Text.Json.csproj +++ b/src/System.Text.Json/src/System.Text.Json.csproj @@ -22,13 +22,9 @@ - - - - diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs deleted file mode 100644 index d3cd46ca3873..000000000000 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections; -using System.Collections.Generic; - -// for now disabling error caused by not adding documentation to methods -#pragma warning disable CS1591 - -namespace System.Text.Json -{ - public partial class JsonArray : JsonNode, IList, IReadOnlyList - { - public JsonArray() { } - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - [CLSCompliant(false)] - public JsonArray(IEnumerable values) { } - [CLSCompliant(false)] - public JsonArray(IEnumerable values) { } - [CLSCompliant(false)] - public JsonArray(IEnumerable values) { } - [CLSCompliant(false)] - public JsonArray(IEnumerable values) { } - public JsonArray(IEnumerable values) { } - - public JsonNode this[int idx] { get => throw null; set => throw null; } - - public void Add(JsonNode value) { } - public void Add(string value) { } - public void Add(bool value) { } - public void Add(byte value) { } - public void Add(short value) { } - public void Add(int value) { } - public void Add(long value) { } - public void Add(float value) { } - public void Add(double value) { } - [CLSCompliant(false)] - public void Add(sbyte value) { } - [CLSCompliant(false)] - public void Add(ushort value) { } - [CLSCompliant(false)] - public void Add(uint value) { } - [CLSCompliant(false)] - public void Add(ulong value) { } - public void Add(decimal value) { } - - public void Insert(int index, JsonNode item) { throw null; } - public void Insert(int index, string item) { throw null; } - public void Insert(int index, bool item) { throw null; } - public void Insert(int index, byte item) { throw null; } - public void Insert(int index, short item) { throw null; } - public void Insert(int index, int item) { throw null; } - public void Insert(int index, long item) { throw null; } - public void Insert(int index, float item) { throw null; } - public void Insert(int index, double item) { throw null; } - [CLSCompliant(false)] - public void Insert(int index, sbyte item) { throw null; } - [CLSCompliant(false)] - public void Insert(int index, ushort item) { throw null; } - [CLSCompliant(false)] - public void Insert(int index, uint item) { throw null; } - [CLSCompliant(false)] - public void Insert(int index, ulong item) { throw null; } - public void Insert(int index, decimal item) { throw null; } - - public bool Contains(JsonNode value) { throw null; } - public bool Contains(string value) { throw null; } - public bool Contains(bool value) { throw null; } - public bool Contains(byte value) { throw null; } - public bool Contains(short value) { throw null; } - public bool Contains(int value) { throw null; } - public bool Contains(long value) { throw null; } - public bool Contains(float value) { throw null; } - public bool Contains(double value) { throw null; } - [CLSCompliant(false)] - public bool Contains(sbyte value) { throw null; } - [CLSCompliant(false)] - public bool Contains(ushort value) { throw null; } - [CLSCompliant(false)] - public bool Contains(uint value) { throw null; } - [CLSCompliant(false)] - public bool Contains(ulong value) { throw null; } - public bool Contains(decimal value) { throw null; } - - public int Count => throw null; - public bool IsReadOnly => throw null; - - public int IndexOf(JsonNode item) { throw null; } - public int LastIndexOf(JsonNode item) { throw null; } - public void RemoveAt(int index) { throw null; } - public void Clear() { throw null; } - public bool Remove(JsonNode item) { throw null; } - - void ICollection.CopyTo(JsonNode[] array, int arrayIndex) { throw null; } - IEnumerator IEnumerable.GetEnumerator() { throw null; } - public IEnumerator GetEnumerator() { throw null; } - } -} - -#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs deleted file mode 100644 index c0768d810fdb..000000000000 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// for now disabling error caused by not adding documentation to methods -#pragma warning disable CS1591 - -namespace System.Text.Json -{ - public partial class JsonBoolean : JsonNode, IEquatable - { - public JsonBoolean() { } - public JsonBoolean(bool value) { } - - public bool Value { get; set; } - - public static implicit operator JsonBoolean(bool value) { throw null; } - - public override bool Equals(object obj) { throw null; } - public override int GetHashCode() { throw null; } - - public bool Equals(JsonBoolean other) { throw null; } - - public static bool operator ==(JsonBoolean left, JsonBoolean right) => throw null; - public static bool operator !=(JsonBoolean left, JsonBoolean right) => throw null; - } -} -#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs index fc907402a258..9e0420f0cfd6 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs @@ -2,33 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// for now disabling error caused by not adding documentation to methods -#pragma warning disable CS1591 - using System.Buffers; using System.IO; namespace System.Text.Json { + /// + /// Represents a specific JSON node. + /// public abstract partial class JsonNode { private protected JsonNode() { } - public JsonElement AsJsonElement() { throw null; } - - public static JsonNode GetNode(JsonElement jsonElement) { throw null; } - public static bool TryGetNode(JsonElement jsonElement, out JsonNode jsonNode) { throw null; } - - public static JsonNode Parse(string json) { throw null; } - public static JsonNode Parse(ReadOnlySequence utf8Json) { throw null; } - public static JsonNode Parse(Stream utf8Json) { throw null; } - public static JsonNode Parse(ReadOnlyMemory utf8Json) { throw null; } - public static JsonNode Parse(ReadOnlyMemory json) { throw null; } - - - public static JsonNode DeepCopy(JsonNode jsonNode) { throw null; } - public static JsonNode DeepCopy(JsonElement jsonElement) { throw null; } - public static JsonNode DeepCopy(JsonDocument jsonDocument) { throw null; } } } - -#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index adae60a4f28c..d9ce86c8435c 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -5,8 +5,6 @@ // for now disabling error caused by not adding documentation to methods #pragma warning disable CS1591 -using System.Buffers; - namespace System.Text.Json { public partial class JsonNumber : JsonNode, IEquatable diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs deleted file mode 100644 index 0c285632c84d..000000000000 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections; -using System.Collections.Generic; - -// for now disabling error caused by not adding documentation to methods -#pragma warning disable CS1591 - -namespace System.Text.Json -{ - public partial class JsonObject : JsonNode, IEnumerable> - { - public JsonObject() { } - public JsonObject(IEnumerable> jsonProperties) { } - - public JsonNode this[string key] { get => throw null; set => throw null; } - public IEnumerator> GetEnumerator() { throw null; } - - public void Add(KeyValuePair jsonProperty) { } - public void Add(string propertyName, JsonArray propertyValue) { } - public void Add(string propertyName, JsonNode propertyValue) { } - public void Add(string propertyName, string propertyValue) { } - public void Add(string propertyName, bool propertyValue) { } - public void Add(string propertyName, byte propertyValue) { } - public void Add(string propertyName, short propertyValue) { } - public void Add(string propertyName, int propertyValue) { } - public void Add(string propertyName, long propertyValue) { } - public void Add(string propertyName, float propertyValue) { } - public void Add(string propertyName, double propertyValue) { } - [CLSCompliant(false)] - public void Add(string propertyName, sbyte propertyValue) { } - [CLSCompliant(false)] - public void Add(string propertyName, ushort propertyValue) { } - [CLSCompliant(false)] - public void Add(string propertyName, uint propertyValue) { } - [CLSCompliant(false)] - public void Add(string propertyName, ulong propertyValue) { } - public void Add(string propertyName, decimal propertyValue) { } - public void Add(string propertyName, IEnumerable propertyValue) { } - public void AddRange(IEnumerable> jsonProperties) { } - - public bool Remove(string propertyName) { throw null; } - public bool ContainsProperty(string propertyName) { throw null; } - - public bool ModifyPropertyName(string oldName, string newName) { throw null; } - - public JsonNode GetProperty(string propertyName) { throw null; } - public bool TryGetProperty(string propertyName, out JsonNode jsonNode) { throw null; } - public JsonObject GetJsonObjectProperty(string propertyName) { throw null; } - public bool TryGetObjectProperty(string propertyName, out JsonObject jsonObject) { throw null; } - public JsonArray GetJsonArrayProperty(string propertyName) { throw null; } - public bool TryGetArrayProperty(string propertyName, out JsonArray jsonArray) { throw null; } - public IEnumerable GetAllProperties(string propertyName) { throw null; } - - - public ICollection PropertyNames => throw null; - public ICollection Values => throw null; - - IEnumerator IEnumerable.GetEnumerator() { throw null; } - } -} - -#pragma warning restore CS1591 diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs deleted file mode 100644 index 99c701c50ece..000000000000 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonString.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// for now disabling error caused by not adding documentation to methods -#pragma warning disable CS1591 - -namespace System.Text.Json -{ - public partial class JsonString : JsonNode, IEquatable - { - public JsonString() { } - public JsonString(string value) { } - - public string Value { get; set; } - - public static implicit operator JsonString(string value) { throw null; } - - public override bool Equals(object obj) { throw null; } - public override int GetHashCode() { throw null; } - - public bool Equals(JsonString other) { throw null; } - - public static bool operator ==(JsonString left, JsonString right) => throw null; - public static bool operator !=(JsonString left, JsonString right) => throw null; - } -} - -#pragma warning restore CS1591 diff --git a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj index 7a9dcd5ce226..395d91349eed 100644 --- a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -102,11 +102,6 @@ - - - - - diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs deleted file mode 100644 index 7f3c19d05520..000000000000 --- a/src/System.Text.Json/tests/WritableJsonApiTests.TestAccessingNestedMembers.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Xunit; - -namespace System.Text.Json -{ - public static partial class WritableJsonApiTests - { - /// - /// Accesing nested Json object - casting with as operator - /// - [Fact] - public static void TestAccesingNestedJsonObjectCastWithAs() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - // Should not throw any exceptions: - - var reportingEmployees = manager["reporting employees"] as JsonObject; - if (reportingEmployees == null) - throw new InvalidCastException(); - - var softwareDevelopers = reportingEmployees["software developers"] as JsonObject; - if (softwareDevelopers == null) - throw new InvalidCastException(); - - var internDevelopers = softwareDevelopers["intern employees"] as JsonObject; - if (internDevelopers == null) - throw new InvalidCastException(); - - internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - casting with is operator - /// - [Fact] - public static void TestAccesingNestedJsonObjectCastWithIs() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - static bool AddEmployee(JsonObject manager) - { - - if (manager["reporting employees"] is JsonObject reportingEmployees) - { - if (reportingEmployees["software developers"] is JsonObject softwareDevelopers) - { - if (softwareDevelopers["full time employees"] is JsonObject fullTimeEmployees) - { - fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); - return true; - } - } - } - return false; - } - - bool success = AddEmployee(manager); - Assert.True(success); - } - - /// - /// Accesing nested Json object - explicit casting - /// - [Fact] - public static void TestAccesingNestedJsonObjectExplicitCast() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - // Should not throw any exceptions: - ((JsonObject)((JsonObject)manager["reporting employees"])["HR"]).Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - GetObjectProperty method - /// - [Fact] - public static void TestAccesingNestedJsonObjectGetPropertyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - // Should not throw any exceptions: - - JsonObject internDevelopers = manager.GetJsonObjectProperty("reporting employees") - .GetJsonObjectProperty("software developers") - .GetJsonObjectProperty("intern employees"); - internDevelopers.Add(EmployeesDatabase.GetNextEmployee()); - } - - /// - /// Accesing nested Json object - TryGetObjectProperty method - /// - [Fact] - public static void TestAccesingNestedJsonObjectTryGetPropertyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - - static bool AddEmployee(JsonObject manager) - { - if (manager.TryGetObjectProperty("reporting employees", out JsonObject reportingEmployees)) - { - if (reportingEmployees.TryGetObjectProperty("software developers", out JsonObject softwareDevelopers)) - { - if (softwareDevelopers.TryGetObjectProperty("full time employees", out JsonObject fullTimeEmployees)) - { - fullTimeEmployees.Add(EmployeesDatabase.GetNextEmployee()); - return true; - } - } - } - - return false; - } - - bool success = AddEmployee(manager); - Assert.True(success); - } - - /// - /// Accesing nested Json array - GetArrayProperty method - /// - [Fact] - public static void TestAccesingNestedJsonArrayGetPropertyMethod() - { - var issues = new JsonObject() - { - { "features", new JsonArray{ "new functionality 1", "new functionality 2" } }, - { "bugs", new JsonArray{ "bug 123", "bug 4566", "bug 821" } }, - { "tests", new JsonArray{ "code coverage" } }, - }; - - issues.GetJsonArrayProperty("bugs").Add("bug 12356"); - ((JsonString)issues.GetJsonArrayProperty("features")[0]).Value = "feature 1569"; - ((JsonString)issues.GetJsonArrayProperty("features")[1]).Value = "feature 56134"; - - Assert.True(((JsonArray)issues["bugs"]).Contains("bug 12356")); - Assert.Equal("feature 1569", (JsonString)((JsonArray)issues["features"])[0]); - Assert.Equal("feature 56134", (JsonString)((JsonArray)issues["features"])[1]); - } - } -} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs deleted file mode 100644 index be61a4821844..000000000000 --- a/src/System.Text.Json/tests/WritableJsonApiTests.TestData.cs +++ /dev/null @@ -1,134 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; - -namespace System.Text.Json -{ - public static partial class WritableJsonApiTests - { - /// - /// Helper class simulating external library - /// - private static class EmployeesDatabase - { - private static int s_id = 0; - public static KeyValuePair GetNextEmployee() - { - var employee = new JsonObject() - { - { "name", "John" } , - { "surname", "Smith"}, - { "age", 45 } - }; - - return new KeyValuePair("employee" + s_id++, employee); - } - - public static IEnumerable> GetTenBestEmployees() - { - for (int i = 0; i < 10; i++) - yield return GetNextEmployee(); - } - - /// - /// Returns following JsonObject: - /// { - /// { "name" : "John" } - /// { "phone numbers" : { "work" : "123-456-7890", "home": "123-456-7890" } } - /// { - /// "reporting employees" : - /// { - /// "software developers" : - /// { - /// "full time employees" : /JsonObject of 3 employees fromk database/ - /// "intern employees" : /JsonObject of 2 employees fromk database/ - /// }, - /// "HR" : /JsonObject of 10 employees fromk database/ - /// } - /// - /// - public static JsonObject GetManager() - { - var manager = GetNextEmployee().Value as JsonObject; - - manager.Add - ( - "phone numbers", - new JsonObject() - { - { "work", "123-456-7890" }, { "home", "123-456-7890" } - } - ); - - manager.Add - ( - "reporting employees", new JsonObject() - { - { - "software developers", new JsonObject() - { - { - "full time employees", new JsonObject() - { - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - } - }, - { - "intern employees", new JsonObject() - { - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - } - } - } - }, - { - "HR", new JsonObject() - { - { - "full time employees", new JsonObject(EmployeesDatabase.GetTenBestEmployees()) - } - } - } - } - ); - - return manager; - } - - public static bool CheckSSN(string ssnNumber) => true; - public static void PerformHeavyOperations(JsonElement employee) { } - } - - /// - /// Helper class simulating sending Json files via network - /// - private static class Mailbox - { - public static void SendEmployeeData(JsonElement employeeData) { } - public static JsonElement RetrieveMutableEmployeeData() { return EmployeesDatabase.GetNextEmployee().Value.AsJsonElement(); } - public static JsonElement RetrieveImmutableEmployeeData() { return new JsonElement(); } - - public static void SendAllEmployeesData(JsonElement employeesData) { } - } - - private static class HealthCare - { - public static void CreateMedicalAppointment(string personName) { } - } - - /// - /// Helper class simulating enum - /// - private enum AvailableStateCodes - { - WA, - CA, - NY, - } - } -} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs deleted file mode 100644 index 6ef4d2659d6c..000000000000 --- a/src/System.Text.Json/tests/WritableJsonApiTests.TestModifying.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using Xunit; - -namespace System.Text.Json -{ - public static partial class WritableJsonApiTests - { - /// - /// Replacing Json object's primnary types - /// - [Fact] - public static void TestReplacingsonObjectPrimaryTypes() - { - var person1 = new JsonObject - { - { "name", "John" }, - { "age", 45 }, - { "is_married", true } - }; - - // Assign by creating a new instance of primary Json type - person1["name"] = new JsonString("Bob"); - - Assert.IsType(person1["name"]); - Assert.Equal("Bob", person1["name"] as JsonString); - - // Assign by using an implicit operator on primary Json type - JsonNumber newAge = 55; - person1["age"] = newAge; - - Assert.IsType(person1["age"]); - Assert.Equal(55, person1["age"] as JsonNumber); - - // Assign by explicit cast from Json primary type - person1["is_married"] = (JsonBoolean)false; - - Assert.IsType(person1["is_married"]); - Assert.Equal(false, person1["is_married"] as JsonBoolean); - - // Not possible scenario (wold require implicit cast operators in JsonNode): - // person["name"] = "Bob"; - - var person2 = new JsonObject - { - { "name", new JsonString[]{ "Emily", "Rosalie" } }, - { "age", 33 }, - { "is_married", true } - }; - - // Copy property from another JsonObject - person1["age"] = person2["age"]; - - Assert.IsType(person1["age"]); - Assert.Equal(33, person1["age"] as JsonNumber); - - // Copy property of different typoe - person1["name"] = person2["name"]; - - Assert.IsType(person1["name"]); - } - - /// - /// Modifying Json object's primnary types - /// - [Fact] - public static void TestModifyingJsonObjectPrimaryTypes() - { - JsonString name = "previous name"; - name.Value = "new name"; - - Assert.Equal("new name", name.Value); - - bool shouldBeEnabled = true; - var isEnabled = new JsonBoolean(false); - isEnabled.Value = shouldBeEnabled; - - Assert.True(isEnabled.Value); - - JsonNumber veryBigConstant = new JsonNumber(); - veryBigConstant.SetFormattedValue("1e1000"); - string bigNumber = veryBigConstant.ToString(); - - Assert.Equal("1e1000", bigNumber); - - veryBigConstant.SetInt16(123); - short smallNumber = veryBigConstant.GetInt16(); - - Assert.Equal(123, smallNumber); - - // Incrementing age: - JsonObject employee = EmployeesDatabase.GetManager(); - int age = ((JsonNumber)employee["age"]).GetInt32(); - ((JsonNumber)employee["age"]).SetInt32(age + 1); - - Assert.Equal(46, ((JsonNumber)employee["age"]).GetInt32()); - } - - /// - /// Adding values to JsonArray - /// - [Fact] - public static void TestAddingToJsonArray() - { - var employeesIds = new JsonArray(); - - foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) - { - employeesIds.Add(employee.Key); - } - - JsonString prevId = new JsonString(); - foreach (JsonNode employeeId in employeesIds) - { - Assert.IsType(employeeId); - var employeeIdString = employeeId as JsonString; - Assert.NotEqual(prevId, employeeIdString); - prevId = employeeIdString; - } - } - - /// - /// Modifying Json object key - remove and add - /// - [Fact] - public static void TestModifyingJsonObjectKeyRemoveAdd() - { - JsonObject manager = EmployeesDatabase.GetManager(); - JsonObject reportingEmployees = manager.GetJsonObjectProperty("reporting employees"); - - static void ModifyProperty(JsonObject jsonObject, string previousName, string newName) - { - JsonNode previousValue = jsonObject[previousName]; - jsonObject.Remove(previousName); - jsonObject.Add(newName, previousValue); - } - - string previousName = "software developers"; - string newName = "software engineers"; - - Assert.True(reportingEmployees.ContainsProperty(previousName)); - JsonNode previousValue = reportingEmployees[previousName]; - - ModifyProperty(reportingEmployees, previousName, newName); - - Assert.False(reportingEmployees.ContainsProperty(previousName)); - Assert.True(reportingEmployees.ContainsProperty(newName)); - Assert.Equal(previousValue, reportingEmployees[newName]); - } - - /// - /// Modifying Json object key - modify method - /// - [Fact] - public static void TestModifyingJsonObjectKeyModifyMethod() - { - JsonObject manager = EmployeesDatabase.GetManager(); - JsonObject reportingEmployees = manager.GetJsonObjectProperty("reporting employees"); - - Assert.True(reportingEmployees.ContainsProperty("software developers")); - JsonNode previousValue = reportingEmployees["software engineers"]; - - reportingEmployees.ModifyPropertyName("software developers", "software engineers"); - - Assert.False(reportingEmployees.ContainsProperty("software developers")); - Assert.True(reportingEmployees.ContainsProperty("software engineers")); - Assert.Equal(previousValue, reportingEmployees["software engineers"]); - } - } -} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs b/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs deleted file mode 100644 index 1707757dcd42..000000000000 --- a/src/System.Text.Json/tests/WritableJsonApiTests.TestTransformations.cs +++ /dev/null @@ -1,230 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Linq; -using Xunit; - -namespace System.Text.Json -{ - public static partial class WritableJsonApiTests - { - /// - /// Transforming JsoneNode to JsonElement - /// - [Fact] - public static void TestTransformingJsonNodeToJsonElement() - { - // Send Json through network, should not throw any exceptions: - JsonNode employeeDataToSend = EmployeesDatabase.GetNextEmployee().Value; - Mailbox.SendEmployeeData(employeeDataToSend.AsJsonElement()); - } - - /// - /// Transforming JsonElement to JsonNode - /// - [Fact] - public static void TestTransformingJsonElementToJsonNode() - { - // Retrieve Json from network, should not throw any exceptions: - JsonNode receivedEmployeeData = JsonNode.DeepCopy(Mailbox.RetrieveMutableEmployeeData()); - if (receivedEmployeeData is JsonObject employee) - { - employee["name"] = new JsonString("Bob"); - Mailbox.SendEmployeeData(employee.AsJsonElement()); - } - } - - /// - /// Transforming JsonDocument to JsonNode and vice versa - /// - [Fact] - public static void TestTransformingToFromJsonDocument() - { - string jsonString = @" - { - ""employee1"" : - { - ""name"" : ""Ann"", - ""surname"" : ""Predictable"", - ""age"" : 30, - }, - ""employee2"" : - { - ""name"" : ""Zoe"", - ""surname"" : ""Coder"", - ""age"" : 24, - } - }"; - - using (JsonDocument employeesToSend = JsonDocument.Parse(jsonString)) - { - // regular send: - Mailbox.SendAllEmployeesData(employeesToSend.RootElement); - - // modified elements send: - JsonObject employees = JsonNode.DeepCopy(employeesToSend) as JsonObject; - Assert.Equal(2, employees.Count()); - - employees.Add(EmployeesDatabase.GetNextEmployee()); - Assert.Equal(3, employees.Count()); - - Mailbox.SendAllEmployeesData(employees.AsJsonElement()); - } - } - - /// - /// Parsing right to JsonNode if user knows data will be modified - /// - [Fact] - public static void TestParsingToJsonNode() - { - string jsonString = @" - { - ""employee1"" : - { - ""name"" : ""Ann"", - ""surname"" : ""Predictable"", - ""age"" : 30, - }, - ""employee2"" : - { - ""name"" : ""Zoe"", - ""surname"" : ""Coder"", - ""age"" : 24, - } - }"; - - JsonObject employees = JsonNode.Parse(jsonString) as JsonObject; - employees.Add(EmployeesDatabase.GetNextEmployee()); - Mailbox.SendAllEmployeesData(employees.AsJsonElement()); - - Assert.Equal(2, employees.Count()); - Assert.True(employees.ContainsProperty("employee1")); - Assert.True(employees.ContainsProperty("employee2")); - - JsonObject employee2 = employees.GetJsonObjectProperty("employee2"); - Assert.IsType(employee2["name"]); - Assert.Equal("Zoe", (JsonString)employee2["name"]); - Assert.IsType(employee2["surname"]); - Assert.Equal("Coder", (JsonString)employee2["surname"]); - Assert.IsType(employee2["age"]); - Assert.Equal(24, (JsonNumber)employee2["age"]); - } - - /// - /// Copying JsoneNode - /// - [Fact] - public static void TestCopyingJsonNode() - { - JsonObject employee = EmployeesDatabase.GetManager(); - JsonNode employeeCopy = JsonNode.DeepCopy(employee); - - static bool RecursiveEquals(JsonNode left, JsonNode right) - { - if (left == null && right == null) - { - return true; - } - - if (right.GetType() != left.GetType()) - { - return false; - } - - switch (left) - { - case JsonObject leftJsonObject: - var rightJsonObject = right as JsonObject; - if (leftJsonObject.Count() != rightJsonObject.Count()) - { - return false; - } - - for (int idx = 0; idx < leftJsonObject.Count(); idx++) - { - KeyValuePair leftElement = leftJsonObject.ElementAt(idx); - KeyValuePair rightElement = rightJsonObject.ElementAt(idx); - - if (leftElement.Key != rightElement.Key || !RecursiveEquals(leftElement.Value, rightElement.Value)) - { - return false; - } - } - - return true; - case JsonArray leftJsonArray: - var rightJsonArray = right as JsonArray; - if (leftJsonArray.Count() != rightJsonArray.Count()) - { - return false; - } - for (int idx = 0; idx < leftJsonArray.Count(); idx++) - { - JsonNode leftElement = leftJsonArray.ElementAt(idx); - JsonNode rightElement = rightJsonArray.ElementAt(idx); - - if (!RecursiveEquals(leftElement, rightElement)) - { - return false; - } - } - - return true; - case JsonString leftJsonString: - return leftJsonString.Equals(right as JsonString); - case JsonNumber leftJsonNumber: - return leftJsonNumber.Equals(right as JsonNumber); - case JsonBoolean leftJsonBoolean: - return leftJsonBoolean.Equals(right as JsonBoolean); - default: - return false; - } - } - - Assert.True(RecursiveEquals(employee, employeeCopy)); - } - - /// - /// Checking IsImmutable property - /// - [Fact] - public static void TestIsImmutable() - { - JsonElement employee = Mailbox.RetrieveMutableEmployeeData(); - Assert.False(employee.IsImmutable); - - if (!employee.IsImmutable) - { - JsonObject employeeNode = JsonNode.GetNode(employee) as JsonObject; - employeeNode["received as node"] = (JsonBoolean)true; - } - - employee = Mailbox.RetrieveImmutableEmployeeData(); - Assert.True(employee.IsImmutable); - } - - /// - /// Retrieving JsonNode from JsonElement - /// - [Fact] - public static void TestTryGetNode() - { - JsonElement employee = Mailbox.RetrieveMutableEmployeeData(); - - static bool CheckIfReceivedAsNode(JsonElement employee) - { - if (JsonNode.TryGetNode(employee, out JsonNode employeeNode)) - { - ((JsonObject)employeeNode)["received as node"] = (JsonBoolean)true; - return true; - } - return false; - } - - Assert.True(CheckIfReceivedAsNode(employee)); - } - } -} diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.cs b/src/System.Text.Json/tests/WritableJsonApiTests.cs deleted file mode 100644 index 18856a103cb6..000000000000 --- a/src/System.Text.Json/tests/WritableJsonApiTests.cs +++ /dev/null @@ -1,553 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Linq; -using Xunit; - -namespace System.Text.Json -{ - public static partial class WritableJsonApiTests - { - /// - /// Creating simple Json object - /// - [Fact] - public static void TestCreatingJsonObject() - { - var developer = new JsonObject - { - { "name", "Kasia" }, - { "age", 22 }, - { "is developer", true }, - { "null property", (JsonNode) null } - }; - - Assert.IsType(developer["name"]); - var developerNameCasted = developer["name"] as JsonString; - Assert.Equal("Kasia", developerNameCasted.Value); - - Assert.IsType(developer["age"]); - var developerAgeCasted = developer["age"] as JsonNumber; - Assert.Equal(22, developerAgeCasted.GetInt32()); - - Assert.IsType(developer["is developer"]); - var isDeveloperCasted = developer["is developer"] as JsonBoolean; - Assert.True(isDeveloperCasted.Value); - - Assert.Null(developer["null property"]); - } - - /// - /// Creating simple Json object by new methods on primary types - /// - [Fact] - public static void TestCreatingJsonObjectNewMethods() - { - var developer = new JsonObject - { - { "name", new JsonString("Kasia") }, - { "age", new JsonNumber(22) }, - { "is developer", new JsonBoolean(true) } - }; - - Assert.IsType(developer["name"]); - var developerNameCasted = developer["name"] as JsonString; - Assert.Equal("Kasia", developerNameCasted.Value); - - Assert.IsType(developer["age"]); - var developerAgeCasted = developer["age"] as JsonNumber; - Assert.Equal(22, developerAgeCasted.GetInt32()); - - Assert.IsType(developer["is developer"]); - var isDeveloperCasted = developer["is developer"] as JsonBoolean; - Assert.True(isDeveloperCasted.Value); - } - - /// - /// Creating and retriving different numeric values - /// - [Fact] - public static void TestNumerics() - { - double PI = 3.14159265359; - var circle = new JsonObject - { - { "radius", 1 }, - { "length", 2*PI }, - { "area", PI } - }; - - Assert.IsType(circle["radius"]); - var radius = circle["radius"] as JsonNumber; - Assert.Equal(1, radius); - - Assert.IsType(circle["length"]); - var length = circle["length"] as JsonNumber; - Assert.Equal(length, 2 * PI); - - Assert.IsType(circle["area"]); - var area = circle["area"] as JsonNumber; - Assert.Equal(area, PI); - - JsonNumber bigConstantBoxed = long.MaxValue; - long bigConstant = bigConstantBoxed.GetInt64(); - - Assert.Equal(long.MaxValue, bigConstant); - - var smallValueBoxed = new JsonNumber(17); - smallValueBoxed.TryGetInt16(out short smallValue); - - Assert.Equal(17, smallValue); - } - - /// - /// Creating nested Json object - /// - [Fact] - public static void TestCreatingNestedJsonObject() - { - var person = new JsonObject - { - { "name", "John" }, - { "surname", "Smith" }, - { - "phone numbers", new JsonObject() - { - { "work", "123-456-7890" }, - { "home", "123-456-7890" } - } - }, - { - "addresses", new JsonObject() - { - { - "office", new JsonObject() - { - { "address line 1", "One Microsoft Way" }, - { "city" , "Redmond" } , - { "zip code" , 98052 } , - { "state" , (int) AvailableStateCodes.WA } - } - }, - { - "home", new JsonObject() - { - { "address line 1", "Pear Ave" }, - { "address line 2", "1288" }, - { "city" , "Mountain View" } , - { "zip code" , 94043 } , - { "state" , (int) AvailableStateCodes.CA } - } - } - } - } - }; - - Assert.IsType(person["phone numbers"]); - var phoneNumbers = person["phone numbers"] as JsonObject; - Assert.IsType(phoneNumbers["work"]); - Assert.IsType(phoneNumbers["home"]); - - Assert.IsType(person["addresses"]); - var addresses = person["office"] as JsonObject; - Assert.IsType(addresses["office"]); - Assert.IsType(addresses["home"]); - } - - /// - /// Defining as KeyValuePair value - /// - [Fact] - public static void TestAssignmentDefinition() - { - JsonNode employee = EmployeesDatabase.GetNextEmployee().Value; - Assert.IsType(employee); - } - - /// - /// Adding KeyValuePair from external library - /// - [Fact] - public static void TestAddingKeyValuePair() - { - var employees = new JsonObject - { - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - EmployeesDatabase.GetNextEmployee(), - }; - - string prevId = ""; - foreach((string id, JsonNode employee) in employees) - { - Assert.NotEqual(prevId, id); - prevId = id; - - Assert.IsType(employee); - } - } - - /// - /// Adding KeyValuePair from external library after initialization - /// - [Fact] - public static void TestAddingKeyValuePairAfterInitialization() - { - var employees = new JsonObject(); - foreach (KeyValuePair employee in EmployeesDatabase.GetTenBestEmployees()) - { - employees.Add(employee); - } - - string prevId = ""; - foreach ((string id, JsonNode employee) in employees) - { - Assert.NotEqual(prevId, id); - prevId = id; - - Assert.IsType(employee); - } - } - - /// - /// Adding KeyValuePairs collection from external library - /// - [Fact] - public static void TestAddingKeyValuePairsCollection() - { - var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); - - string prevId = ""; - foreach ((string id, JsonNode employee) in employees) - { - Assert.NotEqual(prevId, id); - prevId = id; - - Assert.IsType(employee); - } - } - - /// - /// Adding KeyValuePairs collection from external library after initialization - /// - [Fact] - public static void TestAddingKeyValuePairsCollectionAfterInitialization() - { - var employees = new JsonObject(); - employees.AddRange(EmployeesDatabase.GetTenBestEmployees()); - - string prevId = ""; - foreach ((string id, JsonNode employee) in employees) - { - Assert.NotEqual(prevId, id); - prevId = id; - - Assert.IsType(employee); - } - } - - /// - /// Adding JsonArray to JsonObject by creating it in initializing collection - /// - [Fact] - public static void TestAddingJsonArray() - { - var preferences = new JsonObject() - { - { "colours", new JsonArray{ "red", "green", "purple" } } - }; - - Assert.IsType(preferences["colours"]); - var colours = preferences["colours"] as JsonArray; - Assert.Equal(3, colours.Count); - - string[] expected = { "red", "green", "blue" }; - - for (int i = 0; i < colours.Count; i++) - { - Assert.IsType(colours[i]); - Assert.Equal(expected[i], colours[i] as JsonString); - } - } - - /// - /// Adding JsonArray to JsonObject by creating it from string array - /// - [Fact] - public static void TestCretingJsonArrayFromStringArray() - { - string[] expected = { "sushi", "pasta", "cucumber soup" }; - var preferences = new JsonObject() - { - { "dishes", new JsonArray(expected) } - }; - - Assert.IsType(preferences["dishes"]); - var dishesJson = preferences["dishes"] as JsonArray; - Assert.Equal(3, dishesJson.Count); - - for (int i = 0; i < dishesJson.Count; i++) - { - Assert.IsType(dishesJson[i]); - Assert.Equal(expected[i], dishesJson[i] as JsonString); - } - } - - /// - /// Adding JsonArray to JsonObject by passing JsonNumber array - /// - [Fact] - public static void TestAddingJsonArrayFromJsonNumberArray() - { - var preferences = new JsonObject() - { - { "prime numbers", new JsonNumber[] { 19, 37 } } - }; - - Assert.IsType(preferences["prime numbers"]); - var primeNumbers = preferences["prime numbers"] as JsonArray; - Assert.Equal(2, primeNumbers.Count); - - int[] expected = { 19, 37 }; - - for (int i = 0; i < primeNumbers.Count; i++) - { - Assert.IsType(primeNumbers[i]); - Assert.Equal(expected[i], primeNumbers[i] as JsonNumber); - } - } - - /// - /// Adding JsonArray to JsonObject by passing IEnumerable of strings - /// - [Fact] - public static void TestAddingJsonArrayFromIEnumerableOfStrings() - { - var sportsExperienceYears = new JsonObject() - { - { "skiing", 5 }, - { "cycling", 8 }, - { "hiking", 6 }, - { "chess", 2 }, - { "skating", 1 }, - }; - - // choose only sports with > 2 experience years - IEnumerable sports = sportsExperienceYears.Where(sport => ((JsonNumber)sport.Value).GetInt32() > 2).Select(sport => sport.Key); - - var preferences = new JsonObject() - { - { "sports", new JsonArray(sports) } - }; - - Assert.IsType(preferences["sports"]); - var sportsJsonArray = preferences["sports"] as JsonArray; - Assert.Equal(3, sportsJsonArray.Count); - - for (int i = 0; i < sportsJsonArray.Count; i++) - { - Assert.IsType(sportsJsonArray[i]); - Assert.Equal(sports.ElementAt(i), sportsJsonArray[i] as JsonString); - } - } - - /// - /// Adding JsonArray to JsonObject by passing IEnumerable of JsonNodes - /// - [Fact] - public static void TestAddingJsonArrayFromIEnumerableOfJsonNodes() - { - var strangeWords = new JsonArray() - { - "supercalifragilisticexpialidocious", - "gladiolus", - "albumen", - "smaragdine" - }; - - var preferences = new JsonObject() - { - { "strange words", strangeWords.Where(word => ((JsonString)word).Value.Length < 10) } - }; - - Assert.IsType(preferences["strange words"]); - var strangeWordsJsonArray = preferences["strange words"] as JsonArray; - Assert.Equal(2, strangeWordsJsonArray.Count); - - string [] expected = { "gladiolus", "albumen" }; - - for (int i = 0; i < strangeWordsJsonArray.Count; i++) - { - Assert.IsType(strangeWordsJsonArray[i]); - Assert.Equal(expected[i], strangeWordsJsonArray[i] as JsonString); - } - } - - /// - /// Creating nested Json array - /// - [Fact] - public static void TestCreatingNestedJsonArray() - { - var vertices = new JsonArray() - { - new JsonArray - { - new JsonArray - { - new JsonArray { 0, 0, 0 }, - new JsonArray { 0, 0, 1 } - }, - new JsonArray - { - new JsonArray { 0, 1, 0 }, - new JsonArray { 0, 1, 1 } - } - }, - new JsonArray - { - new JsonArray - { - new JsonArray { 1, 0, 0 }, - new JsonArray { 1, 0, 1 } - }, - new JsonArray - { - new JsonArray { 1, 1, 0 }, - new JsonArray { 1, 1, 1 } - } - }, - }; - - Assert.IsType(vertices[0]); - var innerJsonArray = vertices[0] as JsonArray; - Assert.IsType(innerJsonArray[0]); - innerJsonArray = innerJsonArray[0] as JsonArray; - Assert.IsType(innerJsonArray[0]); - } - - - /// - /// Creating Json array from collection - /// - [Fact] - public static void TestCreatingJsonArrayFromCollection() - { - var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => new JsonString(employee.Key))); - - JsonString prevId = new JsonString(); - foreach (JsonNode employeeId in employeesIds) - { - Assert.IsType(employeeId); - var employeeIdString = employeeId as JsonString; - Assert.NotEqual(prevId, employeeIdString); - prevId = employeeIdString; - } - } - - /// - /// Creating Json array from collection of strings - /// - [Fact] - public static void TestCreatingJsonArrayFromCollectionOfString() - { - var employeesIds = new JsonArray(EmployeesDatabase.GetTenBestEmployees().Select(employee => employee.Key)); - - JsonString prevId = new JsonString(); - foreach (JsonNode employeeId in employeesIds) - { - Assert.IsType(employeeId); - var employeeIdString = employeeId as JsonString; - Assert.NotEqual(prevId, employeeIdString); - prevId = employeeIdString; - } - } - - /// - /// Contains checks - /// - [Fact] - public static void TestContains() - { - var person = new JsonObject - { - { "name", "John" }, - { "ssn", "123456789" }, - }; - - if (person.ContainsProperty("ssn")) - { - EmployeesDatabase.CheckSSN(((JsonString)person["ssn"]).Value); - } - - Assert.True(person.ContainsProperty("ssn")); - Assert.False(person.ContainsProperty("surname")); - - // Different scenario: - - var enabledOptions = new JsonArray - { - "readonly", - "no cache", - "continue on failure" - }; - - if (enabledOptions.Contains("no cache")) - { - // do sth without using caching - } - - var requiredOptions = new JsonArray - { - "readonly", - "continue on failure" - }; - - // if all required options are enabled - if (!requiredOptions.Select(option => !enabledOptions.Contains(option)).Any()) - { - // do sth without using caching - } - } - - /// - /// Aquiring all values - /// - [Fact] - public static void TestAquiringAllValues() - { - var employees = new JsonObject(EmployeesDatabase.GetTenBestEmployees()); - ICollection employeesWithoutId = employees.Values; - - foreach(JsonNode employee in employeesWithoutId) - { - Assert.IsType(employee); - } - } - - /// - /// Aquiring all properties - /// - [Fact] - public static void TestAquiringAllProperties() - { - var employees = new JsonObject() - { - { "FTE", "John Smith" }, - { "FTE", "Ann Predictable" }, - { "Intern", "Zoe Coder" }, - { "FTE", "Byron Shadow" }, - }; - - IEnumerable fullTimeEmployees = employees.GetAllProperties("FTE"); - - Assert.Equal(3, fullTimeEmployees.Count()); - Assert.True(fullTimeEmployees.Contains((JsonString)"John Smith")); - Assert.True(fullTimeEmployees.Contains((JsonString)"Ann Predictable")); - Assert.True(fullTimeEmployees.Contains((JsonString)"Byron Shadow")); - } - } -} From 63ff329235fdcebd20db4ca9a62d50d14aa183da Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Tue, 30 Jul 2019 15:29:05 -0700 Subject: [PATCH 07/30] First part of documentation added --- .../src/System/Text/Json/Node/JsonNode.cs | 2 +- .../src/System/Text/Json/Node/JsonNumber.cs | 227 ++++++++++++++++-- 2 files changed, 202 insertions(+), 27 deletions(-) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs index 9e0420f0cfd6..e6fa2ec0bf75 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs @@ -8,7 +8,7 @@ namespace System.Text.Json { /// - /// Represents a specific JSON node. + /// Defines the core behavior of JSON nodes and provides a base for derived classes. /// public abstract partial class JsonNode { diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index d9ce86c8435c..81c54f5737cf 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -2,73 +2,250 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// for now disabling error caused by not adding documentation to methods -#pragma warning disable CS1591 - namespace System.Text.Json { + /// + /// Represents JSON numeric value. + /// public partial class JsonNumber : JsonNode, IEquatable { private string _value; + /// + /// Initializes a new instance of the class representing the value 0. + /// public JsonNumber() => _value = "0"; + /// + /// Initializes a new instance of the class representing a specified value. + /// + /// The string representation of a numeric value in a legal JSON number format. public JsonNumber(string value) => SetFormattedValue(value); - + + /// + /// Initializes a new instance of the class from a Byte value. + /// + /// The value to represent. public JsonNumber(byte value) => SetByte(value); - + + /// + /// Initializes a new instance of the class from an Int16 value. + /// + /// The value to represent. public JsonNumber(short value) => SetInt16(value); - + + /// + /// Initializes a new instance of the class from an Int32 value. + /// + /// The value to represent. public JsonNumber(int value) => SetInt32(value); - + + /// + /// Initializes a new instance of the class from an Int16 value. + /// + /// The value to represent. public JsonNumber(long value) => SetInt64(value); - + + /// + /// Initializes a new instance of the class from a Single value. + /// + /// A value to represent. public JsonNumber(float value) => SetSingle(value); - + + /// + /// Initializes a new instance of the class from a Double value. + /// + /// The value to represent. public JsonNumber(double value) => SetDouble(value); - + + /// + /// Initializes a new instance of the class from a SByte value. + /// + /// The value to represent. [CLSCompliant(false)] public JsonNumber(sbyte value) => SetSByte(value); - + + /// + /// Initializes a new instance of the class from a UInt16 value. + /// + /// The value to represent. [CLSCompliant(false)] public JsonNumber(ushort value) => SetUInt16(value); - + + /// + /// Initializes a new instance of the class from a UInt32 value. + /// + /// The value to represent. [CLSCompliant(false)] public JsonNumber(uint value) => SetUInt32(value); - + + /// + /// Initializes a new instance of the class from a UInt64 value. + /// + /// The value to represent. [CLSCompliant(false)] public JsonNumber(ulong value) => SetUInt64(value); + /// + /// Initializes a new instance of the class from a Decimal value. + /// + /// The value to represent. public JsonNumber(decimal value) => SetDecimal(value); - public override string ToString() => _value; - + /// + /// Converts the numeric value of this instance to its equivalent string representation. + /// + /// The string representation of the value of this instance. + public override string ToString() => _value; + + /// + /// Converts the numeric value of this instance to its Byte equivalent. + /// + /// A Byte equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of Byte. + /// + /// + /// represents a number in a format not compliant with Byte. + /// public byte GetByte() => byte.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its Int16 equivalent. + /// + /// A Int16 equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of Int16. + /// + /// + /// represents a number in a format not compliant with Int16. + /// public short GetInt16() => short.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its Int32 equivalent. + /// + /// A Int32 equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of Int32. + /// + /// + /// represents a number in a format not compliant with Int32. + /// public int GetInt32() => int.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its Int64 equivalent. + /// + /// A Int64 equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of Int64. + /// + /// + /// represents a number in a format not compliant with Int64. + /// public long GetInt64() => long.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its Single equivalent. + /// + /// A Single equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of Single. + /// + /// + /// represents a number in a format not compliant with Single. + /// public float GetSingle() => float.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its Double equivalent. + /// + /// A Double equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of Double. + /// + /// + /// represents a number in a format not compliant with Double. + /// public double GetDouble() => double.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its SByte equivalent. + /// + /// A SByte equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of SByte. + /// + /// + /// represents a number in a format not compliant with SByte. + /// [CLSCompliant(false)] public sbyte GetSByte() => sbyte.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its UInt16 equivalent. + /// + /// A UInt16 equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of UInt16. + /// + /// + /// represents a number in a format not compliant with UInt16. + /// [CLSCompliant(false)] public ushort GetUInt16() => ushort.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its UInt32 equivalent. + /// + /// A UInt32 equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of UInt32. + /// + /// + /// represents a number in a format not compliant with UInt32. + /// [CLSCompliant(false)] public uint GetUInt32() => uint.Parse(_value); - + + /// + /// Converts the numeric value of this instance to its UInt64 equivalent. + /// + /// A UInt64 equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of UInt64. + /// + /// + /// represents a number in a format not compliant with UInt64. + /// [CLSCompliant(false)] public ulong GetUInt64() => ulong.Parse(_value); + /// + /// Converts the numeric value of this instance to its Decimal equivalent. + /// + /// A Decimal equivalent to the number stored by this instance. + /// + /// represents a number less than MinValue or greater than MaxValue of Decimal. + /// + /// + /// represents a number in a format not compliant with Decimal. + /// public decimal GetDecimal() => decimal.Parse(_value); + /// + /// Converts the numeric value of this instance to its Byte equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the Byte value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// public bool TryGetByte(out byte value) => byte.TryParse(_value, out value); public bool TryGetInt16(out short value) => short.TryParse(_value, out value); @@ -170,5 +347,3 @@ public void SetFormattedValue(string value) public static bool operator !=(JsonNumber left, JsonNumber right) => left._value != right._value; } } - -#pragma warning restore CS1591 From 0e0fb7c8f8f7178787ad3acbbc947f5d2c2fb9b1 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Wed, 31 Jul 2019 08:00:47 -0700 Subject: [PATCH 08/30] documentation completed --- .../src/System/Text/Json/Node/JsonNumber.cs | 291 ++++++++++++++++-- 1 file changed, 270 insertions(+), 21 deletions(-) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 81c54f5737cf..cf08bc4a176e 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -248,31 +248,154 @@ public partial class JsonNumber : JsonNode, IEquatable /// public bool TryGetByte(out byte value) => byte.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its Int16 equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the Int16 value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// public bool TryGetInt16(out short value) => short.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its Int32 equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the Int32 value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// public bool TryGetInt32(out int value) => int.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its Int64 equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the Int64 value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// public bool TryGetInt64(out long value) => long.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its Single equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the Single value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// public bool TryGetSingle(out float value) => float.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its Double equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the Double value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// public bool TryGetDouble(out double value) => double.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its SByte equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the SByte value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// [CLSCompliant(false)] public bool TryGetSByte(out sbyte value) => sbyte.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its UInt16 equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the UInt16 value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// [CLSCompliant(false)] public bool TryGetUInt16(out ushort value) => ushort.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its UInt32 equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the UInt32 value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// [CLSCompliant(false)] public bool TryGetUInt32(out uint value) => uint.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its UInt64 equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the UInt64 value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// [CLSCompliant(false)] public bool TryGetUInt64(out ulong value) => ulong.TryParse(_value, out value); + /// + /// Converts the numeric value of this instance to its Decimal equivalent. + /// A return value indicates whether the conversion succeeded. + /// + /// + /// When this method returns, contains the Decimal value equivalent of the number contained in this instance, + /// if the conversion succeeded, or zero if the conversion failed. + /// + /// + /// // if instance was converted successfully; + /// otherwise, + /// public bool TryGetDecimal(out decimal value) => decimal.TryParse(_value, out value); - + /// + /// Changes the numeric value of this instance to represent a specified value. + /// + /// The string representation of a numeric value in a legal JSON number format. public void SetFormattedValue(string value) { if (value == null) @@ -284,66 +407,192 @@ public void SetFormattedValue(string value) _value = value; } + /// + /// Changes the numeric value of this instance to represent a specified Byte value. + /// + /// The value to represent. public void SetByte(byte value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified Int16 value. + /// + /// The value to represent. public void SetInt16(short value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified Int32 value. + /// + /// The value to represent. public void SetInt32(int value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified Int64 value. + /// + /// The value to represent. public void SetInt64(long value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified Single value. + /// + /// The value to represent. public void SetSingle(float value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified Double value. + /// + /// The value to represent. public void SetDouble(double value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified SByte value. + /// + /// The value to represent. [CLSCompliant(false)] public void SetSByte(sbyte value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified UInt16 value. + /// + /// The value to represent. [CLSCompliant(false)] public void SetUInt16(ushort value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified UInt32 value. + /// + /// The value to represent. [CLSCompliant(false)] public void SetUInt32(uint value) => _value = value.ToString(); - + + /// + /// Changes the numeric value of this instance to represent a specified Uint64 value. + /// + /// The value to represent. [CLSCompliant(false)] public void SetUInt64(ulong value) => _value = value.ToString(); + /// + /// Changes the numeric value of this instance to represent a specified Decimal value. + /// + /// The value to represent. public void SetDecimal(decimal value) => _value = value.ToString(); + /// + /// Converts a Byte to a JSON number. + /// + /// The value to convert. public static implicit operator JsonNumber(byte value) => new JsonNumber(value); - - public static implicit operator JsonNumber(int value) => new JsonNumber(value); - + + /// + /// Converts an Int16 to a JSON number. + /// + /// The value to convert. public static implicit operator JsonNumber(short value) => new JsonNumber(value); - + + /// + /// Converts an Int32 to a JSON number. + /// + /// The value to convert. + public static implicit operator JsonNumber(int value) => new JsonNumber(value); + + /// + /// Converts an Int64 to a JSON number. + /// + /// The value to convert. public static implicit operator JsonNumber(long value) => new JsonNumber(value); - + + /// + /// Converts a Single to a JSON number. + /// + /// The value to convert. public static implicit operator JsonNumber(float value) => new JsonNumber(value); - + + /// + /// Converts a Double to a JSON number. + /// + /// The value to convert. public static implicit operator JsonNumber(double value) => new JsonNumber(value); - + + /// + /// Converts a SByte to a JSON number. + /// + /// The value to convert. [CLSCompliant(false)] public static implicit operator JsonNumber(sbyte value) => new JsonNumber(value); - + + /// + /// Converts a UInt16 to a JSON number. + /// + /// The value to convert. [CLSCompliant(false)] public static implicit operator JsonNumber(ushort value) => new JsonNumber(value); - + + /// + /// Converts a UInt32 to a JSON number. + /// + /// The value to convert. [CLSCompliant(false)] public static implicit operator JsonNumber(uint value) => new JsonNumber(value); - + + /// + /// Converts a UInt64 to a JSON number. + /// + /// The value to convert. [CLSCompliant(false)] public static implicit operator JsonNumber(ulong value) => new JsonNumber(value); + /// + /// Converts a Decimal to a JSON number. + /// + /// The value to convert. public static implicit operator JsonNumber(decimal value) => new JsonNumber(value); + /// + /// Compares to the numeric value of this instance. + /// + /// The object to compare against. + /// + /// if the numeric value of this instance matches , + /// otherwise. + /// public override bool Equals(object obj) => obj is JsonNumber number && _value == number._value; + /// + /// Calculates a hash code of this instance. + /// + /// A hash code for this instance. public override int GetHashCode() => _value.GetHashCode(); + /// + /// Compares other JSON number to the numeric value of this instance. + /// + /// The JSON number to compare against. + /// + /// if the numeric value of this instance matches , + /// otherwise. + /// public bool Equals(JsonNumber other) => _value == other._value; + /// + /// Compares numeric values of two JSON numbers. + /// + /// The JSON number to compare. + /// The JSON number to compare. + /// + /// if the numeric value of instances matches, + /// otherwise. + /// public static bool operator ==(JsonNumber left, JsonNumber right) => left._value == right._value; - + + /// + /// Compares numeric values of two JSON numbers. + /// + /// The JSON number to compare. + /// The JSON number to compare. + /// + /// if the numeric value of instances does not match, + /// otherwise. + /// public static bool operator !=(JsonNumber left, JsonNumber right) => left._value != right._value; } } From 47666ce984cbff7f2cb76bed649be8d078b9ad94 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Wed, 31 Jul 2019 08:06:09 -0700 Subject: [PATCH 09/30] missing exceptions added --- .../src/System/Text/Json/Node/JsonNumber.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index cf08bc4a176e..5dc3ff19e547 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -20,6 +20,12 @@ public partial class JsonNumber : JsonNode, IEquatable /// Initializes a new instance of the class representing a specified value. /// /// The string representation of a numeric value in a legal JSON number format. + /// + /// Provided value is null. + /// + /// + /// Provided value is not in a legal JSON number format. + /// public JsonNumber(string value) => SetFormattedValue(value); /// @@ -396,6 +402,12 @@ public partial class JsonNumber : JsonNode, IEquatable /// Changes the numeric value of this instance to represent a specified value. /// /// The string representation of a numeric value in a legal JSON number format. + /// + /// Provided value is null. + /// + /// + /// Provided value is not in a legal JSON number format. + /// public void SetFormattedValue(string value) { if (value == null) From d856681decc2975877d5b7f6b1f7599e26398749 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Wed, 31 Jul 2019 08:10:42 -0700 Subject: [PATCH 10/30] JsonElement changes removed --- src/System.Text.Json/ref/System.Text.Json.cs | 1 - .../src/System/Text/Json/Document/JsonElement.cs | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/System.Text.Json/ref/System.Text.Json.cs b/src/System.Text.Json/ref/System.Text.Json.cs index 0e1aa80d4932..a23bd0887c0f 100644 --- a/src/System.Text.Json/ref/System.Text.Json.cs +++ b/src/System.Text.Json/ref/System.Text.Json.cs @@ -39,7 +39,6 @@ public readonly partial struct JsonElement { private readonly object _dummy; private readonly int _dummyPrimitive; - public bool IsImmutable { get { throw null; } } public System.Text.Json.JsonElement this[int index] { get { throw null; } } public System.Text.Json.JsonValueKind ValueKind { get { throw null; } } public System.Text.Json.JsonElement Clone() { throw null; } diff --git a/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs b/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs index 39369b3828fd..1b142fd5f6a8 100644 --- a/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs +++ b/src/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs @@ -1440,10 +1440,5 @@ private void CheckValidInstance() [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay => $"ValueKind = {ValueKind} : \"{ToString()}\""; - -// for now disabling error caused by not adding documentation to methods -#pragma warning disable CS1591 - public bool IsImmutable => throw null; -#pragma warning restore CS1591 } } From 22e6558fb0dd0ad86633b9f95c810ca2446e86c0 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Thu, 1 Aug 2019 11:57:06 -0700 Subject: [PATCH 11/30] part of the review comments included --- .../src/System.Text.Json.csproj | 4 +- .../src/System/Text/Json/Node/JsonNode.cs | 7 +- .../src/System/Text/Json/Node/JsonNumber.cs | 278 ++++++------- ...itTests.cs => JsonNodeTests.JsonNumber.cs} | 365 +++++++++++++----- .../tests/System.Text.Json.Tests.csproj | 4 +- 5 files changed, 410 insertions(+), 248 deletions(-) rename src/System.Text.Json/tests/{WritableJsonApiTests.JsonNumberUnitTests.cs => JsonNodeTests.JsonNumber.cs} (58%) diff --git a/src/System.Text.Json/src/System.Text.Json.csproj b/src/System.Text.Json/src/System.Text.Json.csproj index ad6319b02c15..eb3439e95d95 100644 --- a/src/System.Text.Json/src/System.Text.Json.csproj +++ b/src/System.Text.Json/src/System.Text.Json.csproj @@ -22,9 +22,7 @@ - - @@ -40,6 +38,8 @@ + + diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs index e6fa2ec0bf75..8b40fec4b3c8 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs @@ -2,15 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Buffers; -using System.IO; - namespace System.Text.Json { /// - /// Defines the core behavior of JSON nodes and provides a base for derived classes. + /// The base class that represents a single node within a JSON document. /// - public abstract partial class JsonNode + public abstract class JsonNode { private protected JsonNode() { } } diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 5dc3ff19e547..8fa841fea8ce 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -5,9 +5,9 @@ namespace System.Text.Json { /// - /// Represents JSON numeric value. + /// Represents a numeric JSON value. /// - public partial class JsonNumber : JsonNode, IEquatable + public class JsonNumber : JsonNode, IEquatable { private string _value; @@ -29,73 +29,73 @@ public partial class JsonNumber : JsonNode, IEquatable public JsonNumber(string value) => SetFormattedValue(value); /// - /// Initializes a new instance of the class from a Byte value. + /// Initializes a new instance of the class from a value. /// - /// The value to represent. + /// The value to represent as a JSON number. public JsonNumber(byte value) => SetByte(value); /// - /// Initializes a new instance of the class from an Int16 value. + /// Initializes a new instance of the class from an value. /// - /// The value to represent. + /// The value to represent as a JSON number. public JsonNumber(short value) => SetInt16(value); /// - /// Initializes a new instance of the class from an Int32 value. + /// Initializes a new instance of the class from an value. /// - /// The value to represent. + /// The value to represent as a JSON number. public JsonNumber(int value) => SetInt32(value); /// - /// Initializes a new instance of the class from an Int16 value. + /// Initializes a new instance of the class from an value. /// - /// The value to represent. + /// The value to represent as a JSON number. public JsonNumber(long value) => SetInt64(value); /// - /// Initializes a new instance of the class from a Single value. + /// Initializes a new instance of the class from a value. /// - /// A value to represent. + /// A value to represent as a JSON number. public JsonNumber(float value) => SetSingle(value); /// - /// Initializes a new instance of the class from a Double value. + /// Initializes a new instance of the class from a value. /// - /// The value to represent. + /// The value to represent as a JSON number. public JsonNumber(double value) => SetDouble(value); /// - /// Initializes a new instance of the class from a SByte value. + /// Initializes a new instance of the class from a value. /// - /// The value to represent. + /// The value to represent as a JSON number. [CLSCompliant(false)] public JsonNumber(sbyte value) => SetSByte(value); /// - /// Initializes a new instance of the class from a UInt16 value. + /// Initializes a new instance of the class from a value. /// - /// The value to represent. + /// The value to represent as a JSON number. [CLSCompliant(false)] public JsonNumber(ushort value) => SetUInt16(value); /// - /// Initializes a new instance of the class from a UInt32 value. + /// Initializes a new instance of the class from a value. /// - /// The value to represent. + /// The value to represent as a JSON number. [CLSCompliant(false)] public JsonNumber(uint value) => SetUInt32(value); /// - /// Initializes a new instance of the class from a UInt64 value. + /// Initializes a new instance of the class from a value. /// - /// The value to represent. + /// The value to represent as a JSON number. [CLSCompliant(false)] public JsonNumber(ulong value) => SetUInt64(value); /// - /// Initializes a new instance of the class from a Decimal value. + /// Initializes a new instance of the class from a value. /// - /// The value to represent. + /// The value to represent as a JSON number. public JsonNumber(decimal value) => SetDecimal(value); /// @@ -105,295 +105,295 @@ public partial class JsonNumber : JsonNode, IEquatable public override string ToString() => _value; /// - /// Converts the numeric value of this instance to its Byte equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A Byte equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of Byte. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with Byte. + /// represents a number in a format not compliant with . /// public byte GetByte() => byte.Parse(_value); /// - /// Converts the numeric value of this instance to its Int16 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A Int16 equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of Int16. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with Int16. + /// represents a number in a format not compliant with . /// public short GetInt16() => short.Parse(_value); /// - /// Converts the numeric value of this instance to its Int32 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A Int32 equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of Int32. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with Int32. + /// represents a number in a format not compliant with . /// public int GetInt32() => int.Parse(_value); /// - /// Converts the numeric value of this instance to its Int64 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A Int64 equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of Int64. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with Int64. + /// represents a number in a format not compliant with . /// public long GetInt64() => long.Parse(_value); /// - /// Converts the numeric value of this instance to its Single equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A Single equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of Single. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with Single. + /// represents a number in a format not compliant with . /// public float GetSingle() => float.Parse(_value); /// - /// Converts the numeric value of this instance to its Double equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A Double equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of Double. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with Double. + /// represents a number in a format not compliant with . /// public double GetDouble() => double.Parse(_value); /// - /// Converts the numeric value of this instance to its SByte equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A SByte equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of SByte. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with SByte. + /// represents a number in a format not compliant with . /// [CLSCompliant(false)] public sbyte GetSByte() => sbyte.Parse(_value); /// - /// Converts the numeric value of this instance to its UInt16 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A UInt16 equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of UInt16. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with UInt16. + /// represents a number in a format not compliant with . /// [CLSCompliant(false)] public ushort GetUInt16() => ushort.Parse(_value); /// - /// Converts the numeric value of this instance to its UInt32 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A UInt32 equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of UInt32. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with UInt32. + /// represents a number in a format not compliant with . /// [CLSCompliant(false)] public uint GetUInt32() => uint.Parse(_value); /// - /// Converts the numeric value of this instance to its UInt64 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A UInt64 equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of UInt64. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with UInt64. + /// represents a number in a format not compliant with . /// [CLSCompliant(false)] public ulong GetUInt64() => ulong.Parse(_value); /// - /// Converts the numeric value of this instance to its Decimal equivalent. + /// Converts the numeric value of this instance to its equivalent. /// - /// A Decimal equivalent to the number stored by this instance. + /// A equivalent to the number stored by this instance. /// - /// represents a number less than MinValue or greater than MaxValue of Decimal. + /// represents a number less than or greater than . /// /// - /// represents a number in a format not compliant with Decimal. + /// represents a number in a format not compliant with . /// public decimal GetDecimal() => decimal.Parse(_value); /// - /// Converts the numeric value of this instance to its Byte equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the Byte value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetByte(out byte value) => byte.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its Int16 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the Int16 value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetInt16(out short value) => short.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its Int32 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the Int32 value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetInt32(out int value) => int.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its Int64 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the Int64 value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetInt64(out long value) => long.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its Single equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the Single value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetSingle(out float value) => float.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its Double equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the Double value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetDouble(out double value) => double.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its SByte equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the SByte value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// [CLSCompliant(false)] public bool TryGetSByte(out sbyte value) => sbyte.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its UInt16 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the UInt16 value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// [CLSCompliant(false)] public bool TryGetUInt16(out ushort value) => ushort.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its UInt32 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the UInt32 value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// [CLSCompliant(false)] public bool TryGetUInt32(out uint value) => uint.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its UInt64 equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the UInt64 value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// [CLSCompliant(false)] public bool TryGetUInt64(out ulong value) => ulong.TryParse(_value, out value); /// - /// Converts the numeric value of this instance to its Decimal equivalent. + /// Converts the numeric value of this instance to its equivalent. /// A return value indicates whether the conversion succeeded. /// /// - /// When this method returns, contains the Decimal value equivalent of the number contained in this instance, + /// When this method returns, contains the value equivalent of the number contained in this instance, /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// // if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetDecimal(out decimal value) => decimal.TryParse(_value, out value); @@ -410,151 +410,155 @@ public partial class JsonNumber : JsonNode, IEquatable /// public void SetFormattedValue(string value) { - if (value == null) - throw new ArgumentNullException(nameof(value)); - if (value.Length == 0) + if (string.IsNullOrEmpty(value)) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } throw new ArgumentException("Expected number, but instead got empty string.", nameof(value)); + } JsonWriterHelper.ValidateNumber(Encoding.UTF8.GetBytes(value).AsSpan()); _value = value; } /// - /// Changes the numeric value of this instance to represent a specified Byte value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. public void SetByte(byte value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified Int16 value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. public void SetInt16(short value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified Int32 value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. public void SetInt32(int value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified Int64 value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. public void SetInt64(long value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified Single value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. public void SetSingle(float value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified Double value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. public void SetDouble(double value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified SByte value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. [CLSCompliant(false)] public void SetSByte(sbyte value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified UInt16 value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. [CLSCompliant(false)] public void SetUInt16(ushort value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified UInt32 value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. [CLSCompliant(false)] public void SetUInt32(uint value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified Uint64 value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. [CLSCompliant(false)] public void SetUInt64(ulong value) => _value = value.ToString(); /// - /// Changes the numeric value of this instance to represent a specified Decimal value. + /// Changes the numeric value of this instance to represent a specified value. /// - /// The value to represent. + /// The value to represent as a JSON number. public void SetDecimal(decimal value) => _value = value.ToString(); /// - /// Converts a Byte to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. public static implicit operator JsonNumber(byte value) => new JsonNumber(value); /// - /// Converts an Int16 to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. public static implicit operator JsonNumber(short value) => new JsonNumber(value); /// - /// Converts an Int32 to a JSON number. + /// Converts an to a JSON number. /// /// The value to convert. public static implicit operator JsonNumber(int value) => new JsonNumber(value); /// - /// Converts an Int64 to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. public static implicit operator JsonNumber(long value) => new JsonNumber(value); /// - /// Converts a Single to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. public static implicit operator JsonNumber(float value) => new JsonNumber(value); /// - /// Converts a Double to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. public static implicit operator JsonNumber(double value) => new JsonNumber(value); /// - /// Converts a SByte to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. [CLSCompliant(false)] public static implicit operator JsonNumber(sbyte value) => new JsonNumber(value); /// - /// Converts a UInt16 to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. [CLSCompliant(false)] public static implicit operator JsonNumber(ushort value) => new JsonNumber(value); /// - /// Converts a UInt32 to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. [CLSCompliant(false)] public static implicit operator JsonNumber(uint value) => new JsonNumber(value); /// - /// Converts a UInt64 to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. [CLSCompliant(false)] public static implicit operator JsonNumber(ulong value) => new JsonNumber(value); /// - /// Converts a Decimal to a JSON number. + /// Converts a to a JSON number. /// /// The value to convert. public static implicit operator JsonNumber(decimal value) => new JsonNumber(value); diff --git a/src/System.Text.Json/tests/WritableJsonApiTests.JsonNumberUnitTests.cs b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs similarity index 58% rename from src/System.Text.Json/tests/WritableJsonApiTests.JsonNumberUnitTests.cs rename to src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs index 2f32a32588da..834ee55d93d5 100644 --- a/src/System.Text.Json/tests/WritableJsonApiTests.JsonNumberUnitTests.cs +++ b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs @@ -4,47 +4,57 @@ using Xunit; -namespace System.Text.Json +namespace System.Text.Json.Tests { - public static partial class WritableJsonApiTests + public static partial class JsonNodeTests { - [Theory] - [InlineData(-456)] - [InlineData(0)] - [InlineData(17)] - [InlineData(long.MaxValue)] - [InlineData(2.3)] - [InlineData(-17.009)] - [InlineData(3.14f)] - [InlineData(0x2A)] - [InlineData(0b_0110_1010)] - [InlineData("1e400")] - [InlineData("1e+100000002")] - [InlineData("184467440737095516150.184467440737095516150")] - public static void TestJsonNumberConstructor(object value) - { - // should not throw any exceptions: - _ = new JsonNumber(value as dynamic); - } - [Fact] public static void TestDefaultCtor() { var jsonNumber = new JsonNumber(); + Assert.Equal(0, jsonNumber.GetByte()); + Assert.Equal(0, jsonNumber.GetInt16()); Assert.Equal(0, jsonNumber.GetInt32()); + Assert.Equal(0, jsonNumber.GetInt64()); + Assert.Equal(0, jsonNumber.GetSingle()); + Assert.Equal(0, jsonNumber.GetDouble()); + Assert.Equal(0, jsonNumber.GetSByte()); + Assert.Equal((ushort)0, jsonNumber.GetUInt16()); + Assert.Equal((uint)0, jsonNumber.GetUInt32()); + Assert.Equal((ulong)0, jsonNumber.GetUInt64()); + Assert.Equal(0, jsonNumber.GetDecimal()); } [Theory] - [InlineData(0)] [InlineData(17)] - [InlineData(255)] + [InlineData(byte.MinValue)] + [InlineData(byte.MaxValue)] public static void TestByte(byte value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetByte(value); Assert.Equal(value, jsonNumber.GetByte()); Assert.True(jsonNumber.TryGetByte(out byte result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetByte()); + Assert.True(jsonNumber.TryGetByte(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetByte()); + Assert.True(jsonNumber.TryGetByte(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetByte()); + Assert.True(jsonNumber.TryGetByte(out result)); + Assert.Equal(value, result); } [Theory] @@ -55,26 +65,66 @@ public static void TestByte(byte value) [InlineData(short.MaxValue)] public static void TestShort(short value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetInt16(value); Assert.Equal(value, jsonNumber.GetInt16()); Assert.True(jsonNumber.TryGetInt16(out short result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetInt16()); + Assert.True(jsonNumber.TryGetInt16(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetInt16()); + Assert.True(jsonNumber.TryGetInt16(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetInt16()); + Assert.True(jsonNumber.TryGetInt16(out result)); + Assert.Equal(value, result); } [Theory] [InlineData(0)] [InlineData(-17)] [InlineData(17)] + [InlineData(0x2A)] + [InlineData(0b_0110_1010)] [InlineData(int.MinValue)] [InlineData(int.MaxValue)] public static void TestInt(int value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetInt32(value); Assert.Equal(value, jsonNumber.GetInt32()); Assert.True(jsonNumber.TryGetInt32(out int result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetInt32()); + Assert.True(jsonNumber.TryGetInt32(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetInt32()); + Assert.True(jsonNumber.TryGetInt32(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetInt32()); + Assert.True(jsonNumber.TryGetInt32(out result)); + Assert.Equal(value, result); } [Theory] @@ -85,11 +135,30 @@ public static void TestInt(int value) [InlineData(long.MaxValue)] public static void TestLong(long value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetInt64(value); Assert.Equal(value, jsonNumber.GetInt64()); Assert.True(jsonNumber.TryGetInt64(out long result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetInt64()); + Assert.True(jsonNumber.TryGetInt64(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetInt64()); + Assert.True(jsonNumber.TryGetInt64(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetInt64()); + Assert.True(jsonNumber.TryGetInt64(out result)); + Assert.Equal(value, result); } [Theory] @@ -102,11 +171,30 @@ public static void TestLong(long value) [InlineData(float.MaxValue)] public static void TestFloat(float value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetSingle(value); Assert.Equal(value, jsonNumber.GetSingle()); Assert.True(jsonNumber.TryGetSingle(out float result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetSingle()); + Assert.True(jsonNumber.TryGetSingle(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetSingle()); + Assert.True(jsonNumber.TryGetSingle(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetSingle()); + Assert.True(jsonNumber.TryGetSingle(out result)); + Assert.Equal(value, result); } [Theory] @@ -119,11 +207,30 @@ public static void TestFloat(float value) [InlineData(double.MaxValue)] public static void TestDouble(double value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetDouble(value); Assert.Equal(value, jsonNumber.GetDouble()); Assert.True(jsonNumber.TryGetDouble(out double result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetDouble()); + Assert.True(jsonNumber.TryGetDouble(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetDouble()); + Assert.True(jsonNumber.TryGetDouble(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetDouble()); + Assert.True(jsonNumber.TryGetDouble(out result)); + Assert.Equal(value, result); } [Theory] @@ -132,13 +239,32 @@ public static void TestDouble(double value) [InlineData(-17)] [InlineData(sbyte.MinValue)] [InlineData(sbyte.MaxValue)] - public static void TestSbyte(sbyte value) + public static void TestSByte(sbyte value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetSByte(value); Assert.Equal(value, jsonNumber.GetSByte()); Assert.True(jsonNumber.TryGetSByte(out sbyte result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetSByte()); + Assert.True(jsonNumber.TryGetSByte(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetSByte()); + Assert.True(jsonNumber.TryGetSByte(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetSByte()); + Assert.True(jsonNumber.TryGetSByte(out result)); + Assert.Equal(value, result); } [Theory] @@ -147,11 +273,30 @@ public static void TestSbyte(sbyte value) [InlineData(ushort.MaxValue)] public static void TestUInt16(ushort value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetUInt16(value); Assert.Equal(value, jsonNumber.GetUInt16()); Assert.True(jsonNumber.TryGetUInt16(out ushort result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetUInt16()); + Assert.True(jsonNumber.TryGetUInt16(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetUInt16()); + Assert.True(jsonNumber.TryGetUInt16(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetUInt16()); + Assert.True(jsonNumber.TryGetUInt16(out result)); + Assert.Equal(value, result); } [Theory] @@ -160,11 +305,30 @@ public static void TestUInt16(ushort value) [InlineData(uint.MaxValue)] public static void TestUInt32(uint value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetUInt32(value); Assert.Equal(value, jsonNumber.GetUInt32()); Assert.True(jsonNumber.TryGetUInt32(out uint result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetUInt32()); + Assert.True(jsonNumber.TryGetUInt32(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetUInt32()); + Assert.True(jsonNumber.TryGetUInt32(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetUInt32()); + Assert.True(jsonNumber.TryGetUInt32(out result)); + Assert.Equal(value, result); } [Theory] @@ -173,35 +337,80 @@ public static void TestUInt32(uint value) [InlineData(ulong.MaxValue)] public static void TestUInt64(ulong value) { + // Default constructor: var jsonNumber = new JsonNumber(); jsonNumber.SetUInt64(value); Assert.Equal(value, jsonNumber.GetUInt64()); Assert.True(jsonNumber.TryGetUInt64(out ulong result)); Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetUInt64()); + Assert.True(jsonNumber.TryGetUInt64(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetUInt64()); + Assert.True(jsonNumber.TryGetUInt64(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetUInt64()); + Assert.True(jsonNumber.TryGetUInt64(out result)); + Assert.Equal(value, result); } - [Fact] - public static void TestDecimal() + [Theory] + [InlineData(0)] + public static void TestDecimal(decimal value) { - var decimalValue = decimal.MaxValue; + //var value = decimal.MaxValue; + + // Default constructor: var jsonNumber = new JsonNumber(); - jsonNumber.SetDecimal(decimalValue); - Assert.Equal(decimalValue, jsonNumber.GetDecimal()); + jsonNumber.SetDecimal(value); + Assert.Equal(value, jsonNumber.GetDecimal()); Assert.True(jsonNumber.TryGetDecimal(out decimal result)); - Assert.Equal(decimalValue, result); + Assert.Equal(value, result); + + // Numeric type constructor: + jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.GetDecimal()); + Assert.True(jsonNumber.TryGetDecimal(out result)); + Assert.Equal(value, result); + + // Implicit cast: + jsonNumber = value; + Assert.Equal(value, jsonNumber.GetDecimal()); + Assert.True(jsonNumber.TryGetDecimal(out result)); + Assert.Equal(value, result); + + // String constructor: + jsonNumber = new JsonNumber(value.ToString()); + Assert.Equal(value, jsonNumber.GetDecimal()); + Assert.True(jsonNumber.TryGetDecimal(out result)); + Assert.Equal(value, result); } [Theory] - [InlineData("3.14")] - [InlineData("-17")] [InlineData("0")] - [InlineData("189")] + [InlineData("17")] + [InlineData("-456")] + [InlineData("2.3")] + [InlineData("-17.009")] [InlineData("1e400")] [InlineData("1e+100000002")] [InlineData("184467440737095516150.184467440737095516150")] + [InlineData("184467440737095516150184467440737095516150")] public static void TestString(string value) { - var jsonNumber = new JsonNumber(); + var jsonNumber = new JsonNumber(value); + Assert.Equal(value, jsonNumber.ToString()); + + jsonNumber = new JsonNumber(); jsonNumber.SetFormattedValue(value); Assert.Equal(value, jsonNumber.ToString()); } @@ -227,6 +436,10 @@ public static void TestString(string value) [InlineData(" 6 ")] [InlineData("+0")] [InlineData("+1")] + [InlineData("long.MaxValue")] + [InlineData("3.14f")] + [InlineData("0x2A")] + [InlineData("0b_0110_1010")] public static void TestInvalidString(string value) { Assert.Throws(() => new JsonNumber(value)); @@ -238,11 +451,22 @@ public static void TestNullString() Assert.Throws(() => new JsonNumber(null)); } - [Fact] - public static void TestIntFromString() + [Theory] + [InlineData("0")] + [InlineData("-17")] + [InlineData("17")] + [InlineData("3.14")] + [InlineData("1.1e1")] + [InlineData("-3.1415")] + [InlineData("1234567890")] + [InlineData("1e400")] + [InlineData("1e+100000002")] + [InlineData("184467440737095516150.184467440737095516150")] + public static void TestToString(string value) { - var jsonNumber = new JsonNumber("145"); - Assert.Equal(145, jsonNumber.GetInt32()); + var jsonNumber = new JsonNumber(); + jsonNumber.SetFormattedValue(value); + Assert.Equal(value, jsonNumber.ToString()); } [Fact] @@ -368,23 +592,6 @@ public static void TestRationalGetMismatches() Assert.Throws(() => jsonNumber.GetUInt64()); } - [Theory] - [InlineData("0")] - [InlineData("-17")] - [InlineData("17")] - [InlineData("3.14")] - [InlineData("-3.1415")] - [InlineData("1234567890")] - [InlineData("1e400")] - [InlineData("1e+100000002")] - [InlineData("184467440737095516150.184467440737095516150")] - public static void TestToString(string value) - { - var jsonNumber = new JsonNumber(); - jsonNumber.SetFormattedValue(value); - Assert.Equal(value, jsonNumber.ToString()); - } - [Fact] public static void TestChangingTypes() { @@ -421,53 +628,5 @@ public static void TestChangingTypes() jsonNumber.SetDecimal(decimal.MaxValue); Assert.Equal(decimal.MaxValue, jsonNumber.GetDecimal()); } - - [Fact] - public static void TestImplicitOperators() - { - byte byteValue = byte.MaxValue; - JsonNumber jsonNumber = byteValue; - Assert.Equal(byteValue, jsonNumber.GetByte()); - - short shortValue = short.MaxValue; - jsonNumber = shortValue; - Assert.Equal(shortValue, jsonNumber.GetInt16()); - - int intValue = int.MaxValue; - jsonNumber = intValue; - Assert.Equal(intValue, jsonNumber.GetInt32()); - - long longValue = long.MaxValue; - jsonNumber = longValue; - Assert.Equal(longValue, jsonNumber.GetInt64()); - - float floatValue = float.MaxValue; - jsonNumber = floatValue; - Assert.Equal(floatValue, jsonNumber.GetSingle()); - - double doubleValue = double.MaxValue; - jsonNumber = doubleValue; - Assert.Equal(doubleValue, jsonNumber.GetDouble()); - - sbyte sbyteValue = sbyte.MaxValue; - jsonNumber = sbyteValue; - Assert.Equal(sbyteValue, jsonNumber.GetSByte()); - - ushort ushortValue = ushort.MaxValue; - jsonNumber = ushortValue; - Assert.Equal(ushortValue, jsonNumber.GetUInt16()); - - uint uintValue = uint.MaxValue; - jsonNumber = uintValue; - Assert.Equal(uintValue, jsonNumber.GetUInt32()); - - ulong ulongValue = ulong.MaxValue; - jsonNumber = ulongValue; - Assert.Equal(ulongValue, jsonNumber.GetUInt64()); - - decimal decimalValue = decimal.MaxValue; - jsonNumber = decimalValue; - Assert.Equal(decimalValue, jsonNumber.GetDecimal()); - } } } diff --git a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj index 395d91349eed..a3a40a96b7b2 100644 --- a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -101,8 +101,10 @@ + + + - From 04441f1224cc0cd632e15e9d96cd737a5aeaffb2 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Thu, 1 Aug 2019 15:44:46 -0700 Subject: [PATCH 12/30] work on review comments --- .../src/System/Text/Json/Node/JsonNumber.cs | 32 ++++++++- .../tests/JsonNodeTests.JsonNumber.cs | 68 ++++++++++++------- 2 files changed, 73 insertions(+), 27 deletions(-) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 8fa841fea8ce..3d051c825200 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -26,6 +26,7 @@ public class JsonNumber : JsonNode, IEquatable /// /// Provided value is not in a legal JSON number format. /// + /// Provided value is stored in the same format as passed. public JsonNumber(string value) => SetFormattedValue(value); /// @@ -162,6 +163,12 @@ public class JsonNumber : JsonNode, IEquatable /// /// represents a number in a format not compliant with . /// + /// + /// On .NET Core this method does not return for values larger than + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. + /// public float GetSingle() => float.Parse(_value); /// @@ -174,6 +181,12 @@ public class JsonNumber : JsonNode, IEquatable /// /// represents a number in a format not compliant with . /// + /// + /// On .NET Core this method does not return for values larger than + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. + /// public double GetDouble() => double.Parse(_value); /// @@ -308,6 +321,12 @@ public class JsonNumber : JsonNode, IEquatable /// if instance was converted successfully; /// otherwise, /// + /// + /// On .NET Core this method does not return for values larger than + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. + /// public bool TryGetSingle(out float value) => float.TryParse(_value, out value); /// @@ -322,6 +341,12 @@ public class JsonNumber : JsonNode, IEquatable /// if instance was converted successfully; /// otherwise, /// + /// + /// On .NET Core this method does not return for values larger than + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. + /// public bool TryGetDouble(out double value) => double.TryParse(_value, out value); /// @@ -408,6 +433,7 @@ public class JsonNumber : JsonNode, IEquatable /// /// Provided value is not in a legal JSON number format. /// + /// Provided value is stored in the same format as passed. public void SetFormattedValue(string value) { if (string.IsNullOrEmpty(value)) @@ -587,7 +613,7 @@ public void SetFormattedValue(string value) /// if the numeric value of this instance matches , /// otherwise. /// - public bool Equals(JsonNumber other) => _value == other._value; + public bool Equals(JsonNumber other) => !(other is null) && _value == other._value; /// /// Compares numeric values of two JSON numbers. @@ -598,7 +624,7 @@ public void SetFormattedValue(string value) /// if the numeric value of instances matches, /// otherwise. /// - public static bool operator ==(JsonNumber left, JsonNumber right) => left._value == right._value; + public static bool operator ==(JsonNumber left, JsonNumber right) => left?._value == right?._value; /// /// Compares numeric values of two JSON numbers. @@ -609,6 +635,6 @@ public void SetFormattedValue(string value) /// if the numeric value of instances does not match, /// otherwise. /// - public static bool operator !=(JsonNumber left, JsonNumber right) => left._value != right._value; + public static bool operator !=(JsonNumber left, JsonNumber right) => left?._value != right?._value; } } diff --git a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs index 834ee55d93d5..cbd7b39ebb1d 100644 --- a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs +++ b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs @@ -8,6 +8,41 @@ namespace System.Text.Json.Tests { public static partial class JsonNodeTests { + private delegate bool TryGetValue(out T result); + + private static void SimpleNumberTests( + T value, + Func ctor, + Action setter, + Func getter, TryGetValue tryGetter, + Func implicitCaster) + { + JsonNumber number = new JsonNumber(); + setter(number, value); + AssertValue(value, number, getter, tryGetter); + + number = ctor(value); + AssertValue(value, number, getter, tryGetter); + + number = new JsonNumber(value.ToString()); + AssertValue(value, number, getter, tryGetter); + + number = implicitCaster(value); + AssertValue(value, number, getter, tryGetter); + } + + private static void AssertValue( + T value, + JsonNumber number, + Func getter, + TryGetValue tryGetter) + { + Assert.Equal(value, getter(number)); + Assert.True(tryGetter(number, out T result)); + Assert.Equal(value, result); + } + + [Fact] public static void TestDefaultCtor() { @@ -31,30 +66,13 @@ public static void TestDefaultCtor() [InlineData(byte.MaxValue)] public static void TestByte(byte value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetByte(value); - Assert.Equal(value, jsonNumber.GetByte()); - Assert.True(jsonNumber.TryGetByte(out byte result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetByte()); - Assert.True(jsonNumber.TryGetByte(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetByte()); - Assert.True(jsonNumber.TryGetByte(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetByte()); - Assert.True(jsonNumber.TryGetByte(out result)); - Assert.Equal(value, result); + SimpleNumberTests( + value, + v => new JsonNumber(v), + (number, v) => number.SetInt16(v), + number => number.GetInt16(), + (number, out v) => number.TryGetValue(out v), + v => v); } [Theory] @@ -453,6 +471,8 @@ public static void TestNullString() [Theory] [InlineData("0")] + [InlineData("1.1e1")] + [InlineData("0.0")] [InlineData("-17")] [InlineData("17")] [InlineData("3.14")] From 30c5dd091c9ecabefe72fab63d887229db819ca4 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Mon, 5 Aug 2019 11:07:10 -0700 Subject: [PATCH 13/30] code refactor --- .../tests/JsonNodeTests.JsonNumber.cs | 345 +++++------------- 1 file changed, 88 insertions(+), 257 deletions(-) diff --git a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs index cbd7b39ebb1d..56a99c7c11f7 100644 --- a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs +++ b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs @@ -8,25 +8,30 @@ namespace System.Text.Json.Tests { public static partial class JsonNodeTests { - private delegate bool TryGetValue(out T result); + private delegate bool TryGetValue(JsonNumber number, out T result); - private static void SimpleNumberTests( + private static void TestInitialization( T value, - Func ctor, + Func ctor, Action setter, - Func getter, TryGetValue tryGetter, + Func getter, + TryGetValue tryGetter, Func implicitCaster) { + // Default constructor: JsonNumber number = new JsonNumber(); setter(number, value); AssertValue(value, number, getter, tryGetter); + // Numeric type constructor: number = ctor(value); AssertValue(value, number, getter, tryGetter); + // String constructor: number = new JsonNumber(value.ToString()); AssertValue(value, number, getter, tryGetter); - + + // Implicit cast: number = implicitCaster(value); AssertValue(value, number, getter, tryGetter); } @@ -34,7 +39,7 @@ private static void SimpleNumberTests( private static void AssertValue( T value, JsonNumber number, - Func getter, + Func getter, TryGetValue tryGetter) { Assert.Equal(value, getter(number)); @@ -42,7 +47,6 @@ private static void AssertValue( Assert.Equal(value, result); } - [Fact] public static void TestDefaultCtor() { @@ -66,12 +70,12 @@ public static void TestDefaultCtor() [InlineData(byte.MaxValue)] public static void TestByte(byte value) { - SimpleNumberTests( + TestInitialization( value, v => new JsonNumber(v), - (number, v) => number.SetInt16(v), - number => number.GetInt16(), - (number, out v) => number.TryGetValue(out v), + (number, v) => number.SetByte(v), + number => number.GetByte(), + (JsonNumber number, out byte v) => number.TryGetByte(out v), v => v); } @@ -83,30 +87,13 @@ public static void TestByte(byte value) [InlineData(short.MaxValue)] public static void TestShort(short value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetInt16(value); - Assert.Equal(value, jsonNumber.GetInt16()); - Assert.True(jsonNumber.TryGetInt16(out short result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetInt16()); - Assert.True(jsonNumber.TryGetInt16(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetInt16()); - Assert.True(jsonNumber.TryGetInt16(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetInt16()); - Assert.True(jsonNumber.TryGetInt16(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetInt16(v), + number => number.GetInt16(), + (JsonNumber number, out short v) => number.TryGetInt16(out v), + v => v); } [Theory] @@ -119,30 +106,13 @@ public static void TestShort(short value) [InlineData(int.MaxValue)] public static void TestInt(int value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetInt32(value); - Assert.Equal(value, jsonNumber.GetInt32()); - Assert.True(jsonNumber.TryGetInt32(out int result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetInt32()); - Assert.True(jsonNumber.TryGetInt32(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetInt32()); - Assert.True(jsonNumber.TryGetInt32(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetInt32()); - Assert.True(jsonNumber.TryGetInt32(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetInt32(v), + number => number.GetInt32(), + (JsonNumber number, out int v) => number.TryGetInt32(out v), + v => v); } [Theory] @@ -153,30 +123,13 @@ public static void TestInt(int value) [InlineData(long.MaxValue)] public static void TestLong(long value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetInt64(value); - Assert.Equal(value, jsonNumber.GetInt64()); - Assert.True(jsonNumber.TryGetInt64(out long result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetInt64()); - Assert.True(jsonNumber.TryGetInt64(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetInt64()); - Assert.True(jsonNumber.TryGetInt64(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetInt64()); - Assert.True(jsonNumber.TryGetInt64(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetInt64(v), + number => number.GetInt64(), + (JsonNumber number, out long v) => number.TryGetInt64(out v), + v => v); } [Theory] @@ -189,30 +142,13 @@ public static void TestLong(long value) [InlineData(float.MaxValue)] public static void TestFloat(float value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetSingle(value); - Assert.Equal(value, jsonNumber.GetSingle()); - Assert.True(jsonNumber.TryGetSingle(out float result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetSingle()); - Assert.True(jsonNumber.TryGetSingle(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetSingle()); - Assert.True(jsonNumber.TryGetSingle(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetSingle()); - Assert.True(jsonNumber.TryGetSingle(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetSingle(v), + number => number.GetSingle(), + (JsonNumber number, out float v) => number.TryGetSingle(out v), + v => v); } [Theory] @@ -225,30 +161,13 @@ public static void TestFloat(float value) [InlineData(double.MaxValue)] public static void TestDouble(double value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetDouble(value); - Assert.Equal(value, jsonNumber.GetDouble()); - Assert.True(jsonNumber.TryGetDouble(out double result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetDouble()); - Assert.True(jsonNumber.TryGetDouble(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetDouble()); - Assert.True(jsonNumber.TryGetDouble(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetDouble()); - Assert.True(jsonNumber.TryGetDouble(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetDouble(v), + number => number.GetDouble(), + (JsonNumber number, out double v) => number.TryGetDouble(out v), + v => v); } [Theory] @@ -259,30 +178,13 @@ public static void TestDouble(double value) [InlineData(sbyte.MaxValue)] public static void TestSByte(sbyte value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetSByte(value); - Assert.Equal(value, jsonNumber.GetSByte()); - Assert.True(jsonNumber.TryGetSByte(out sbyte result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetSByte()); - Assert.True(jsonNumber.TryGetSByte(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetSByte()); - Assert.True(jsonNumber.TryGetSByte(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetSByte()); - Assert.True(jsonNumber.TryGetSByte(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetSByte(v), + number => number.GetSByte(), + (JsonNumber number, out sbyte v) => number.TryGetSByte(out v), + v => v); } [Theory] @@ -291,30 +193,13 @@ public static void TestSByte(sbyte value) [InlineData(ushort.MaxValue)] public static void TestUInt16(ushort value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetUInt16(value); - Assert.Equal(value, jsonNumber.GetUInt16()); - Assert.True(jsonNumber.TryGetUInt16(out ushort result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetUInt16()); - Assert.True(jsonNumber.TryGetUInt16(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetUInt16()); - Assert.True(jsonNumber.TryGetUInt16(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetUInt16()); - Assert.True(jsonNumber.TryGetUInt16(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetUInt16(v), + number => number.GetUInt16(), + (JsonNumber number, out ushort v) => number.TryGetUInt16(out v), + v => v); } [Theory] @@ -323,30 +208,13 @@ public static void TestUInt16(ushort value) [InlineData(uint.MaxValue)] public static void TestUInt32(uint value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetUInt32(value); - Assert.Equal(value, jsonNumber.GetUInt32()); - Assert.True(jsonNumber.TryGetUInt32(out uint result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetUInt32()); - Assert.True(jsonNumber.TryGetUInt32(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetUInt32()); - Assert.True(jsonNumber.TryGetUInt32(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetUInt32()); - Assert.True(jsonNumber.TryGetUInt32(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetUInt32(v), + number => number.GetUInt32(), + (JsonNumber number, out uint v) => number.TryGetUInt32(out v), + v => v); } [Theory] @@ -355,62 +223,26 @@ public static void TestUInt32(uint value) [InlineData(ulong.MaxValue)] public static void TestUInt64(ulong value) { - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetUInt64(value); - Assert.Equal(value, jsonNumber.GetUInt64()); - Assert.True(jsonNumber.TryGetUInt64(out ulong result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetUInt64()); - Assert.True(jsonNumber.TryGetUInt64(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetUInt64()); - Assert.True(jsonNumber.TryGetUInt64(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetUInt64()); - Assert.True(jsonNumber.TryGetUInt64(out result)); - Assert.Equal(value, result); + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetUInt64(v), + number => number.GetUInt64(), + (JsonNumber number, out ulong v) => number.TryGetUInt64(out v), + v => v); } - [Theory] - [InlineData(0)] - public static void TestDecimal(decimal value) + [Fact] + public static void TestDecimal() { - //var value = decimal.MaxValue; - - // Default constructor: - var jsonNumber = new JsonNumber(); - jsonNumber.SetDecimal(value); - Assert.Equal(value, jsonNumber.GetDecimal()); - Assert.True(jsonNumber.TryGetDecimal(out decimal result)); - Assert.Equal(value, result); - - // Numeric type constructor: - jsonNumber = new JsonNumber(value); - Assert.Equal(value, jsonNumber.GetDecimal()); - Assert.True(jsonNumber.TryGetDecimal(out result)); - Assert.Equal(value, result); - - // Implicit cast: - jsonNumber = value; - Assert.Equal(value, jsonNumber.GetDecimal()); - Assert.True(jsonNumber.TryGetDecimal(out result)); - Assert.Equal(value, result); - - // String constructor: - jsonNumber = new JsonNumber(value.ToString()); - Assert.Equal(value, jsonNumber.GetDecimal()); - Assert.True(jsonNumber.TryGetDecimal(out result)); - Assert.Equal(value, result); + decimal value = decimal.MaxValue; + TestInitialization( + value, + v => new JsonNumber(v), + (number, v) => number.SetDecimal(v), + number => number.GetDecimal(), + (JsonNumber number, out decimal v) => number.TryGetDecimal(out v), + v => v); } [Theory] @@ -471,7 +303,6 @@ public static void TestNullString() [Theory] [InlineData("0")] - [InlineData("1.1e1")] [InlineData("0.0")] [InlineData("-17")] [InlineData("17")] From 8f3e51040bef427b062e74e33f6fbcf6a790f963 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Mon, 5 Aug 2019 11:20:21 -0700 Subject: [PATCH 14/30] more decimal tests added using MemberData --- .../tests/JsonNodeTests.JsonNumber.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs index 56a99c7c11f7..b8b346364c1b 100644 --- a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs +++ b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Generic; using Xunit; namespace System.Text.Json.Tests @@ -232,10 +233,23 @@ public static void TestUInt64(ulong value) v => v); } - [Fact] - public static void TestDecimal() + public static IEnumerable DecimalData => + new List + { + decimal.One, + decimal.Zero, + decimal.MinusOne, + decimal.Divide(1,2), + decimal.Divide(1,3), + decimal.Divide(1,10), + decimal.MinValue, + decimal.MaxValue, + }; + + [Theory] + [MemberData(nameof(DecimalData))] + public static void TestDecimal(decimal value) { - decimal value = decimal.MaxValue; TestInitialization( value, v => new JsonNumber(v), From c6ab14809191c0cdc2db72655192a93fd429275e Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Mon, 5 Aug 2019 13:52:29 -0700 Subject: [PATCH 15/30] more decimal tests added using MemberData --- .../tests/JsonNodeTests.JsonNumber.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs index b8b346364c1b..b44dab7034e9 100644 --- a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs +++ b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs @@ -7,7 +7,7 @@ namespace System.Text.Json.Tests { - public static partial class JsonNodeTests + public static class JsonNumberTests { private delegate bool TryGetValue(JsonNumber number, out T result); @@ -233,17 +233,17 @@ public static void TestUInt64(ulong value) v => v); } - public static IEnumerable DecimalData => - new List + public static IEnumerable DecimalData => + new List { - decimal.One, - decimal.Zero, - decimal.MinusOne, - decimal.Divide(1,2), - decimal.Divide(1,3), - decimal.Divide(1,10), - decimal.MinValue, - decimal.MaxValue, + new object[] { decimal.One }, + new object[] { decimal.Zero }, + new object[] { decimal.MinusOne }, + new object[] { decimal.Divide(1, 2) }, + new object[] { decimal.Divide(1, 3) }, + new object[] { decimal.Divide(1, 10) }, + new object[] { decimal.MinValue }, + new object[] { decimal.MaxValue } }; [Theory] From 259590bd979f64598e9b07a23f8d04b602f3bf7b Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Mon, 5 Aug 2019 15:16:29 -0700 Subject: [PATCH 16/30] more test cases added --- .../tests/JsonNodeTests.JsonNumber.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs index b44dab7034e9..76344418d165 100644 --- a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs +++ b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs @@ -84,6 +84,8 @@ public static void TestByte(byte value) [InlineData(0)] [InlineData(-17)] [InlineData(17)] + [InlineData(byte.MinValue-1)] + [InlineData(byte.MaxValue+1)] [InlineData(short.MinValue)] [InlineData(short.MaxValue)] public static void TestShort(short value) @@ -103,6 +105,8 @@ public static void TestShort(short value) [InlineData(17)] [InlineData(0x2A)] [InlineData(0b_0110_1010)] + [InlineData(short.MinValue-1)] + [InlineData(short.MaxValue+1)] [InlineData(int.MinValue)] [InlineData(int.MaxValue)] public static void TestInt(int value) @@ -120,6 +124,8 @@ public static void TestInt(int value) [InlineData(0)] [InlineData(-17)] [InlineData(17)] + [InlineData((long)int.MinValue - 1)] + [InlineData((long)int.MaxValue + 1)] [InlineData(long.MinValue)] [InlineData(long.MaxValue)] public static void TestLong(long value) @@ -158,6 +164,10 @@ public static void TestFloat(float value) [InlineData(-17)] [InlineData(3.14)] [InlineData(-15.5)] + [InlineData(float.MinValue)] + [InlineData(float.MaxValue)] + [InlineData(float.MinValue-1.0)] + [InlineData(float.MaxValue+1.0)] [InlineData(double.MinValue)] [InlineData(double.MaxValue)] public static void TestDouble(double value) @@ -191,6 +201,7 @@ public static void TestSByte(sbyte value) [Theory] [InlineData(0)] [InlineData(17)] + [InlineData(sbyte.MaxValue+1)] [InlineData(ushort.MaxValue)] public static void TestUInt16(ushort value) { @@ -206,6 +217,7 @@ public static void TestUInt16(ushort value) [Theory] [InlineData(0)] [InlineData(17)] + [InlineData(ushort.MaxValue + 1)] [InlineData(uint.MaxValue)] public static void TestUInt32(uint value) { @@ -221,6 +233,7 @@ public static void TestUInt32(uint value) [Theory] [InlineData(0)] [InlineData(17)] + [InlineData((ulong)uint.MaxValue + 1)] [InlineData(ulong.MaxValue)] public static void TestUInt64(ulong value) { @@ -267,6 +280,8 @@ public static void TestDecimal(decimal value) [InlineData("-17.009")] [InlineData("1e400")] [InlineData("1e+100000002")] + [InlineData("-79228162514264337593543950336")] + [InlineData("79228162514264337593543950336")] [InlineData("184467440737095516150.184467440737095516150")] [InlineData("184467440737095516150184467440737095516150")] public static void TestString(string value) From c4d6ef28fc3a7f8aaf6d6ebac1cf17202cf6ae3d Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Mon, 5 Aug 2019 15:28:45 -0700 Subject: [PATCH 17/30] equals summary adjusted, equals tests added --- .../src/System/Text/Json/Node/JsonNumber.cs | 16 +++++++------- .../tests/JsonNodeTests.JsonNumber.cs | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 3d051c825200..1dc2a1e4250b 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -590,11 +590,11 @@ public void SetFormattedValue(string value) public static implicit operator JsonNumber(decimal value) => new JsonNumber(value); /// - /// Compares to the numeric value of this instance. + /// Compares to the value of this instance. /// /// The object to compare against. /// - /// if the numeric value of this instance matches , + /// if the value of this instance matches exactly (is equal and has the same format), /// otherwise. /// public override bool Equals(object obj) => obj is JsonNumber number && _value == number._value; @@ -606,33 +606,33 @@ public void SetFormattedValue(string value) public override int GetHashCode() => _value.GetHashCode(); /// - /// Compares other JSON number to the numeric value of this instance. + /// Compares other JSON number to the value of this instance. /// /// The JSON number to compare against. /// - /// if the numeric value of this instance matches , + /// if the value of this instance matches exactly (is equal and has the same format), /// otherwise. /// public bool Equals(JsonNumber other) => !(other is null) && _value == other._value; /// - /// Compares numeric values of two JSON numbers. + /// Compares values of two JSON numbers. /// /// The JSON number to compare. /// The JSON number to compare. /// - /// if the numeric value of instances matches, + /// if values of instances match exactly (are equal and have the same format), /// otherwise. /// public static bool operator ==(JsonNumber left, JsonNumber right) => left?._value == right?._value; /// - /// Compares numeric values of two JSON numbers. + /// Compares values of two JSON numbers. /// /// The JSON number to compare. /// The JSON number to compare. /// - /// if the numeric value of instances does not match, + /// if values of instances do not match exactly (are not equal or have different format), /// otherwise. /// public static bool operator !=(JsonNumber left, JsonNumber right) => left?._value != right?._value; diff --git a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs index 76344418d165..66f177ddeea4 100644 --- a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs +++ b/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs @@ -508,5 +508,27 @@ public static void TestChangingTypes() jsonNumber.SetDecimal(decimal.MaxValue); Assert.Equal(decimal.MaxValue, jsonNumber.GetDecimal()); } + + [Fact] + public static void TestEquals() + { + var jsonNumber = new JsonNumber(123); + + Assert.True(jsonNumber.Equals(new JsonNumber(123))); + Assert.True(jsonNumber.Equals(new JsonNumber((ushort)123))); + Assert.True(jsonNumber.Equals(new JsonNumber("123"))); + Assert.False(jsonNumber.Equals(new JsonNumber("123e1"))); + Assert.False(jsonNumber.Equals(new JsonNumber(17))); + + Assert.True(jsonNumber == new JsonNumber(123)); + Assert.True(jsonNumber != new JsonNumber(17)); + + JsonNode jsonNode = new JsonNumber(123); + Assert.True(jsonNumber.Equals(jsonNode)); + + IEquatable jsonNumberIEquatable = jsonNumber; + Assert.True(jsonNumberIEquatable.Equals(jsonNumber)); + Assert.True(jsonNumber.Equals(jsonNumberIEquatable)); + } } } From 01c230f7fdfe7f18828ddb825a9282beba7a25e7 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Tue, 6 Aug 2019 08:06:23 -0700 Subject: [PATCH 18/30] more Equals tests added, GetHashCode tests added, minor changes --- .../src/System.Text.Json.csproj | 6 +- .../src/System/Text/Json/Node/JsonNumber.cs | 10 +-- ...Tests.JsonNumber.cs => JsonNumberTests.cs} | 65 +++++++++++++++++-- .../tests/System.Text.Json.Tests.csproj | 4 +- 4 files changed, 70 insertions(+), 15 deletions(-) rename src/System.Text.Json/tests/{JsonNodeTests.JsonNumber.cs => JsonNumberTests.cs} (87%) diff --git a/src/System.Text.Json/src/System.Text.Json.csproj b/src/System.Text.Json/src/System.Text.Json.csproj index eb3439e95d95..fcee8a8fbd59 100644 --- a/src/System.Text.Json/src/System.Text.Json.csproj +++ b/src/System.Text.Json/src/System.Text.Json.csproj @@ -38,8 +38,6 @@ - - @@ -210,4 +208,8 @@ + + + + diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 1dc2a1e4250b..9bc4159e4df4 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -183,9 +183,9 @@ public class JsonNumber : JsonNode, IEquatable /// /// /// On .NET Core this method does not return for values larger than - /// (or smaller than ), - /// instead is returned and (or - /// ) is emitted. + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. /// public double GetDouble() => double.Parse(_value); @@ -594,7 +594,7 @@ public void SetFormattedValue(string value) /// /// The object to compare against. /// - /// if the value of this instance matches exactly (is equal and has the same format), + /// if the value of this instance matches exactly (is equal and has the same format), /// otherwise. /// public override bool Equals(object obj) => obj is JsonNumber number && _value == number._value; @@ -610,7 +610,7 @@ public void SetFormattedValue(string value) /// /// The JSON number to compare against. /// - /// if the value of this instance matches exactly (is equal and has the same format), + /// if the value of this instance matches exactly (is equal and has the same format), /// otherwise. /// public bool Equals(JsonNumber other) => !(other is null) && _value == other._value; diff --git a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs b/src/System.Text.Json/tests/JsonNumberTests.cs similarity index 87% rename from src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs rename to src/System.Text.Json/tests/JsonNumberTests.cs index 66f177ddeea4..dba8a09ca348 100644 --- a/src/System.Text.Json/tests/JsonNodeTests.JsonNumber.cs +++ b/src/System.Text.Json/tests/JsonNumberTests.cs @@ -84,8 +84,8 @@ public static void TestByte(byte value) [InlineData(0)] [InlineData(-17)] [InlineData(17)] - [InlineData(byte.MinValue-1)] - [InlineData(byte.MaxValue+1)] + [InlineData(byte.MinValue - 1)] + [InlineData(byte.MaxValue + 1)] [InlineData(short.MinValue)] [InlineData(short.MaxValue)] public static void TestShort(short value) @@ -105,8 +105,8 @@ public static void TestShort(short value) [InlineData(17)] [InlineData(0x2A)] [InlineData(0b_0110_1010)] - [InlineData(short.MinValue-1)] - [InlineData(short.MaxValue+1)] + [InlineData(short.MinValue - 1)] + [InlineData(short.MaxValue + 1)] [InlineData(int.MinValue)] [InlineData(int.MaxValue)] public static void TestInt(int value) @@ -166,8 +166,8 @@ public static void TestFloat(float value) [InlineData(-15.5)] [InlineData(float.MinValue)] [InlineData(float.MaxValue)] - [InlineData(float.MinValue-1.0)] - [InlineData(float.MaxValue+1.0)] + [InlineData(float.MinValue - 1.0)] + [InlineData(float.MaxValue + 1.0)] [InlineData(double.MinValue)] [InlineData(double.MaxValue)] public static void TestDouble(double value) @@ -201,7 +201,7 @@ public static void TestSByte(sbyte value) [Theory] [InlineData(0)] [InlineData(17)] - [InlineData(sbyte.MaxValue+1)] + [InlineData(sbyte.MaxValue + 1)] [InlineData(ushort.MaxValue)] public static void TestUInt16(ushort value) { @@ -515,10 +515,22 @@ public static void TestEquals() var jsonNumber = new JsonNumber(123); Assert.True(jsonNumber.Equals(new JsonNumber(123))); + Assert.True(new JsonNumber(123).Equals(jsonNumber)); + Assert.True(jsonNumber.Equals(new JsonNumber((ushort)123))); + Assert.True(new JsonNumber((ushort)123).Equals(jsonNumber)); + Assert.True(jsonNumber.Equals(new JsonNumber("123"))); + Assert.True(new JsonNumber("123").Equals(jsonNumber)); + + Assert.False(jsonNumber.Equals(new JsonNumber("123e0"))); + Assert.False(new JsonNumber("123e0").Equals(jsonNumber)); + Assert.False(jsonNumber.Equals(new JsonNumber("123e1"))); + Assert.False(new JsonNumber("123e1").Equals(jsonNumber)); + Assert.False(jsonNumber.Equals(new JsonNumber(17))); + Assert.False(new JsonNumber(17).Equals(jsonNumber)); Assert.True(jsonNumber == new JsonNumber(123)); Assert.True(jsonNumber != new JsonNumber(17)); @@ -529,6 +541,45 @@ public static void TestEquals() IEquatable jsonNumberIEquatable = jsonNumber; Assert.True(jsonNumberIEquatable.Equals(jsonNumber)); Assert.True(jsonNumber.Equals(jsonNumberIEquatable)); + + Assert.False(jsonNumber.Equals(null)); + + object jsonNumberCopy = jsonNumber; + object jsonNumberObject = new JsonNumber(123); + Assert.True(jsonNumber.Equals(jsonNumberObject)); + Assert.True(jsonNumberCopy.Equals(jsonNumberObject)); + Assert.True(jsonNumberObject.Equals(jsonNumber)); + + jsonNumber = new JsonNumber(); + Assert.True(jsonNumber.Equals(new JsonNumber())); + Assert.False(jsonNumber.Equals(new JsonNumber(5))); + } + + [Fact] + public static void TestGetHashCode() + { + var jsonNumber = new JsonNumber(123); + + Assert.Equal(jsonNumber.GetHashCode(), new JsonNumber(123).GetHashCode()); + Assert.Equal(jsonNumber.GetHashCode(), new JsonNumber((ushort)123).GetHashCode()); + Assert.Equal(jsonNumber.GetHashCode(), new JsonNumber("123").GetHashCode()); + Assert.NotEqual(jsonNumber.GetHashCode(), new JsonNumber("123e0").GetHashCode()); + Assert.NotEqual(jsonNumber.GetHashCode(), new JsonNumber("123e1").GetHashCode()); + Assert.NotEqual(jsonNumber.GetHashCode(), new JsonNumber(17).GetHashCode()); + + JsonNode jsonNode = new JsonNumber(123); + Assert.Equal(jsonNumber.GetHashCode(), jsonNode.GetHashCode()); + + IEquatable jsonNumberIEquatable = jsonNumber; + Assert.Equal(jsonNumber.GetHashCode(), jsonNumberIEquatable.GetHashCode()); + + object jsonNumberCopy = jsonNumber; + object jsonNumberObject = new JsonNumber(17); + + Assert.Equal(jsonNumber.GetHashCode(), jsonNumberCopy.GetHashCode()); + Assert.NotEqual(jsonNumber.GetHashCode(), jsonNumberObject.GetHashCode()); + + Assert.Equal(new JsonNumber().GetHashCode(), new JsonNumber().GetHashCode()); } } } diff --git a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj index a3a40a96b7b2..a76a4fcabc0c 100644 --- a/src/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -101,7 +101,6 @@ - @@ -111,6 +110,9 @@ CommonTest\System\Buffers\ArrayBufferWriter.cs + + + From 392142a7ece2bea0556291947eb07a06fb256eea Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Tue, 6 Aug 2019 09:43:46 -0700 Subject: [PATCH 19/30] scientifing notation support added, rational numbers tests fixes --- .../src/System/Text/Json/Node/JsonNumber.cs | 81 +++++++++++++++++-- src/System.Text.Json/tests/JsonNumberTests.cs | 78 ++++++++++++++++-- 2 files changed, 145 insertions(+), 14 deletions(-) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 9bc4159e4df4..58c224b6e935 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Globalization; + namespace System.Text.Json { /// @@ -103,6 +105,9 @@ public class JsonNumber : JsonNode, IEquatable /// Converts the numeric value of this instance to its equivalent string representation. /// /// The string representation of the value of this instance. + /// + /// Returns exactly the same value as it was set using . + /// public override string ToString() => _value; /// @@ -169,7 +174,18 @@ public class JsonNumber : JsonNode, IEquatable /// instead is returned and (or /// ) is emitted. /// - public float GetSingle() => float.Parse(_value); + /// + /// Allows scientific mode. + /// + public float GetSingle() + { + if (float.TryParse(_value, out float value)) + { + return value; + } + + return float.Parse(_value, NumberStyles.AllowExponent, GetJsonCulture()); + } /// /// Converts the numeric value of this instance to its equivalent. @@ -187,7 +203,18 @@ public class JsonNumber : JsonNode, IEquatable /// instead is returned and (or /// ) is emitted. /// - public double GetDouble() => double.Parse(_value); + /// + /// Allows scientific mode. + /// + public double GetDouble() + { + if (double.TryParse(_value, out double value)) + { + return value; + } + + return double.Parse(_value, NumberStyles.AllowExponent, GetJsonCulture()); + } /// /// Converts the numeric value of this instance to its equivalent. @@ -327,7 +354,15 @@ public class JsonNumber : JsonNode, IEquatable /// instead is returned and (or /// ) is emitted. /// - public bool TryGetSingle(out float value) => float.TryParse(_value, out value); + public bool TryGetSingle(out float value) + { + if (float.TryParse(_value, out value)) + { + return true; + } + + return float.TryParse(_value, NumberStyles.AllowExponent, GetJsonCulture(), out value); + } /// /// Converts the numeric value of this instance to its equivalent. @@ -347,7 +382,15 @@ public class JsonNumber : JsonNode, IEquatable /// instead is returned and (or /// ) is emitted. /// - public bool TryGetDouble(out double value) => double.TryParse(_value, out value); + public bool TryGetDouble(out double value) + { + if (double.TryParse(_value, out value)) + { + return true; + } + + return double.TryParse(_value, NumberStyles.AllowExponent, GetJsonCulture(), out value); + } /// /// Converts the numeric value of this instance to its equivalent. @@ -477,13 +520,26 @@ public void SetFormattedValue(string value) /// Changes the numeric value of this instance to represent a specified value. /// /// The value to represent as a JSON number. - public void SetSingle(float value) => _value = value.ToString(); - + public void SetSingle(float value) + { + if (value.Equals(float.PositiveInfinity) || value.Equals(float.NegativeInfinity)) + { + throw new FormatException("Provided value does not represent legal JSON number."); + } + _value = value.ToString(); + } /// /// Changes the numeric value of this instance to represent a specified value. /// /// The value to represent as a JSON number. - public void SetDouble(double value) => _value = value.ToString(); + public void SetDouble(double value) + { + if(value.Equals(double.PositiveInfinity) || value.Equals(double.NegativeInfinity)) + { + throw new FormatException("Provided value does not represent legal JSON number."); + } + _value = value.ToString(); + } /// /// Changes the numeric value of this instance to represent a specified value. @@ -636,5 +692,16 @@ public void SetFormattedValue(string value) /// otherwise. /// public static bool operator !=(JsonNumber left, JsonNumber right) => left?._value != right?._value; + + /// + /// Returns object with number decimal separator set to `.` + /// + /// + private CultureInfo GetJsonCulture() + { + CultureInfo jsonCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone(); + jsonCulture.NumberFormat.NumberDecimalSeparator = "."; + return jsonCulture; + } } } diff --git a/src/System.Text.Json/tests/JsonNumberTests.cs b/src/System.Text.Json/tests/JsonNumberTests.cs index dba8a09ca348..6af76c2fdfa7 100644 --- a/src/System.Text.Json/tests/JsonNumberTests.cs +++ b/src/System.Text.Json/tests/JsonNumberTests.cs @@ -9,6 +9,8 @@ namespace System.Text.Json.Tests { public static class JsonNumberTests { + private const int Precision = 5; + private delegate bool TryGetValue(JsonNumber number, out T result); private static void TestInitialization( @@ -29,7 +31,7 @@ private static void TestInitialization( AssertValue(value, number, getter, tryGetter); // String constructor: - number = new JsonNumber(value.ToString()); + number = new JsonNumber(value.ToString().Replace(',','.')); AssertValue(value, number, getter, tryGetter); // Implicit cast: @@ -37,15 +39,41 @@ private static void TestInitialization( AssertValue(value, number, getter, tryGetter); } + private static void AssertWithPrecision( + double value, + JsonNumber number, + Func getter, + TryGetValue tryGetter) + { + Assert.Equal(value, Convert.ToDouble(getter(number)), Precision); + Assert.True(tryGetter(number, out T tryGetterResult)); + Assert.Equal(value, Convert.ToDouble(tryGetterResult), Precision); + } + private static void AssertValue( T value, JsonNumber number, Func getter, TryGetValue tryGetter) { - Assert.Equal(value, getter(number)); - Assert.True(tryGetter(number, out T result)); - Assert.Equal(value, result); + + switch (value) + { + case double doubleValue: + AssertWithPrecision(doubleValue, number, getter, tryGetter); + return; + case float floatValue: + AssertWithPrecision(Convert.ToDouble(floatValue), number, getter, tryGetter); + return; + case decimal decimalValue: + AssertWithPrecision(Convert.ToDouble(decimalValue), number, getter, tryGetter); + return; + default: + Assert.Equal(value, getter(number)); + Assert.True(tryGetter(number, out T result)); + Assert.Equal(value, result); + return; + } } [Fact] @@ -370,11 +398,11 @@ public static void TestUpcasts() Assert.Equal(value, jsonNumber.GetSingle()); Assert.True(jsonNumber.TryGetSingle(out float floatResult)); - Assert.Equal(value, floatResult); + Assert.Equal(value, floatResult, Precision); Assert.Equal(value, jsonNumber.GetDouble()); Assert.True(jsonNumber.TryGetDouble(out double doubleResult)); - Assert.Equal(value, doubleResult); + Assert.Equal(value, doubleResult, Precision); Assert.Equal(value, (byte)jsonNumber.GetSByte()); Assert.True(jsonNumber.TryGetSByte(out sbyte sbyteResult)); @@ -394,7 +422,7 @@ public static void TestUpcasts() Assert.Equal(value, jsonNumber.GetDecimal()); Assert.True(jsonNumber.TryGetDecimal(out decimal decimalResult)); - Assert.Equal(value, decimalResult); + Assert.Equal(value, decimalResult, Precision); } [Fact] @@ -472,6 +500,42 @@ public static void TestRationalGetMismatches() Assert.Throws(() => jsonNumber.GetUInt64()); } + [InlineData(float.PositiveInfinity)] + [InlineData(float.NegativeInfinity)] + [Theory] + public static void TestFloatninities(float value) + { + Assert.Throws(() => new JsonNumber(value)); + } + + [InlineData(double.PositiveInfinity)] + [InlineData(double.NegativeInfinity)] + [Theory] + public static void TestDoubleIninities(double value) + { + Assert.Throws (() => new JsonNumber(value)); + } + + [Fact] + public static void TestScientificNotation() + { + var jsonNumber = new JsonNumber("5e6"); + Assert.Equal(5000000, jsonNumber.GetSingle(), Precision); + Assert.Equal(5000000, jsonNumber.GetDouble(), Precision); + + jsonNumber = new JsonNumber("3.14e0"); + Assert.Equal(3.14, jsonNumber.GetSingle(), Precision); + Assert.Equal(3.14, jsonNumber.GetDouble(), Precision); + + jsonNumber = new JsonNumber("7e-3"); + Assert.Equal(0.007, jsonNumber.GetSingle(), Precision); + Assert.Equal(0.007, jsonNumber.GetDouble(), Precision); + + jsonNumber = new JsonNumber("-7e-3"); + Assert.Equal(-0.007, jsonNumber.GetSingle(), Precision); + Assert.Equal(-0.007, jsonNumber.GetDouble(), Precision); + } + [Fact] public static void TestChangingTypes() { From 310a5a69c8d2848d16a264139ecbd632a1bcf30f Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Tue, 6 Aug 2019 10:03:53 -0700 Subject: [PATCH 20/30] rational overflow tests added --- src/System.Text.Json/tests/JsonNumberTests.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/System.Text.Json/tests/JsonNumberTests.cs b/src/System.Text.Json/tests/JsonNumberTests.cs index 6af76c2fdfa7..48d73243224e 100644 --- a/src/System.Text.Json/tests/JsonNumberTests.cs +++ b/src/System.Text.Json/tests/JsonNumberTests.cs @@ -498,6 +498,15 @@ public static void TestRationalGetMismatches() Assert.False(jsonNumber.TryGetUInt64(out ulong ulongResult)); Assert.Throws(() => jsonNumber.GetUInt64()); + + jsonNumber = new JsonNumber(double.MaxValue); + Assert.Equal(float.PositiveInfinity, jsonNumber.GetSingle()); + Assert.Throws(() => jsonNumber.GetDecimal()); + + jsonNumber = new JsonNumber("1e100"); + Assert.Equal(float.PositiveInfinity, jsonNumber.GetSingle()); + Assert.Equal(double.PositiveInfinity, jsonNumber.GetSingle()); + Assert.Throws(() => jsonNumber.GetDecimal()); } [InlineData(float.PositiveInfinity)] From e03b80325cc9878dcc24b31883c3074000782468 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Tue, 6 Aug 2019 10:09:59 -0700 Subject: [PATCH 21/30] ulong maxvalue tests added to rational types --- src/System.Text.Json/tests/JsonNumberTests.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/System.Text.Json/tests/JsonNumberTests.cs b/src/System.Text.Json/tests/JsonNumberTests.cs index 48d73243224e..d2da19a90ac5 100644 --- a/src/System.Text.Json/tests/JsonNumberTests.cs +++ b/src/System.Text.Json/tests/JsonNumberTests.cs @@ -175,6 +175,8 @@ public static void TestLong(long value) [InlineData(-15.5)] [InlineData(float.MinValue)] [InlineData(float.MaxValue)] + [InlineData(ulong.MinValue)] + [InlineData(ulong.MaxValue)] public static void TestFloat(float value) { TestInitialization( @@ -198,6 +200,8 @@ public static void TestFloat(float value) [InlineData(float.MaxValue + 1.0)] [InlineData(double.MinValue)] [InlineData(double.MaxValue)] + [InlineData(ulong.MinValue)] + [InlineData(ulong.MaxValue)] public static void TestDouble(double value) { TestInitialization( @@ -284,7 +288,9 @@ public static void TestUInt64(ulong value) new object[] { decimal.Divide(1, 3) }, new object[] { decimal.Divide(1, 10) }, new object[] { decimal.MinValue }, - new object[] { decimal.MaxValue } + new object[] { decimal.MaxValue }, + new object[] { ulong.MaxValue }, + new object[] { ulong.MinValue } }; [Theory] From 95a9401bdf3e44a151079ab41a0c55be57c38661 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Tue, 6 Aug 2019 15:20:06 -0700 Subject: [PATCH 22/30] presision problems fixes --- .../src/System/Text/Json/Node/JsonNumber.cs | 53 ++---------- src/System.Text.Json/tests/JsonNumberTests.cs | 83 ++++++++----------- 2 files changed, 40 insertions(+), 96 deletions(-) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 58c224b6e935..e4ace00663b0 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -177,16 +177,8 @@ public class JsonNumber : JsonNode, IEquatable /// /// Allows scientific mode. /// - public float GetSingle() - { - if (float.TryParse(_value, out float value)) - { - return value; - } - - return float.Parse(_value, NumberStyles.AllowExponent, GetJsonCulture()); - } - + public float GetSingle() => float.Parse(_value); + /// /// Converts the numeric value of this instance to its equivalent. /// @@ -206,15 +198,7 @@ public float GetSingle() /// /// Allows scientific mode. /// - public double GetDouble() - { - if (double.TryParse(_value, out double value)) - { - return value; - } - - return double.Parse(_value, NumberStyles.AllowExponent, GetJsonCulture()); - } + public double GetDouble() => double.Parse(_value); /// /// Converts the numeric value of this instance to its equivalent. @@ -354,15 +338,7 @@ public double GetDouble() /// instead is returned and (or /// ) is emitted. /// - public bool TryGetSingle(out float value) - { - if (float.TryParse(_value, out value)) - { - return true; - } - - return float.TryParse(_value, NumberStyles.AllowExponent, GetJsonCulture(), out value); - } + public bool TryGetSingle(out float value) => float.TryParse(_value, out value); /// /// Converts the numeric value of this instance to its equivalent. @@ -382,15 +358,7 @@ public bool TryGetSingle(out float value) /// instead is returned and (or /// ) is emitted. /// - public bool TryGetDouble(out double value) - { - if (double.TryParse(_value, out value)) - { - return true; - } - - return double.TryParse(_value, NumberStyles.AllowExponent, GetJsonCulture(), out value); - } + public bool TryGetDouble(out double value) => double.TryParse(_value, out value); /// /// Converts the numeric value of this instance to its equivalent. @@ -692,16 +660,5 @@ public void SetDouble(double value) /// otherwise. /// public static bool operator !=(JsonNumber left, JsonNumber right) => left?._value != right?._value; - - /// - /// Returns object with number decimal separator set to `.` - /// - /// - private CultureInfo GetJsonCulture() - { - CultureInfo jsonCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone(); - jsonCulture.NumberFormat.NumberDecimalSeparator = "."; - return jsonCulture; - } } } diff --git a/src/System.Text.Json/tests/JsonNumberTests.cs b/src/System.Text.Json/tests/JsonNumberTests.cs index d2da19a90ac5..6a1ce1bc863f 100644 --- a/src/System.Text.Json/tests/JsonNumberTests.cs +++ b/src/System.Text.Json/tests/JsonNumberTests.cs @@ -3,21 +3,20 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Globalization; using Xunit; namespace System.Text.Json.Tests { public static class JsonNumberTests { - private const int Precision = 5; - private delegate bool TryGetValue(JsonNumber number, out T result); private static void TestInitialization( T value, Func ctor, Action setter, - Func getter, + Func getter, TryGetValue tryGetter, Func implicitCaster) { @@ -31,7 +30,13 @@ private static void TestInitialization( AssertValue(value, number, getter, tryGetter); // String constructor: - number = new JsonNumber(value.ToString().Replace(',','.')); + number = value switch + { + double doubleValue => new JsonNumber(doubleValue.ToString(CultureInfo.InvariantCulture)), + float floatValue => new JsonNumber(floatValue.ToString(CultureInfo.InvariantCulture)), + decimal decimalValue => new JsonNumber(decimalValue.ToString(CultureInfo.InvariantCulture)), + _ => new JsonNumber(value.ToString()), + }; AssertValue(value, number, getter, tryGetter); // Implicit cast: @@ -39,41 +44,15 @@ private static void TestInitialization( AssertValue(value, number, getter, tryGetter); } - private static void AssertWithPrecision( - double value, - JsonNumber number, - Func getter, - TryGetValue tryGetter) - { - Assert.Equal(value, Convert.ToDouble(getter(number)), Precision); - Assert.True(tryGetter(number, out T tryGetterResult)); - Assert.Equal(value, Convert.ToDouble(tryGetterResult), Precision); - } - private static void AssertValue( T value, JsonNumber number, Func getter, TryGetValue tryGetter) { - - switch (value) - { - case double doubleValue: - AssertWithPrecision(doubleValue, number, getter, tryGetter); - return; - case float floatValue: - AssertWithPrecision(Convert.ToDouble(floatValue), number, getter, tryGetter); - return; - case decimal decimalValue: - AssertWithPrecision(Convert.ToDouble(decimalValue), number, getter, tryGetter); - return; - default: - Assert.Equal(value, getter(number)); - Assert.True(tryGetter(number, out T result)); - Assert.Equal(value, result); - return; - } + Assert.Equal(value, getter(number)); + Assert.True(tryGetter(number, out T result)); + Assert.Equal(value, result); } [Fact] @@ -173,10 +152,12 @@ public static void TestLong(long value) [InlineData(-17)] [InlineData(3.14)] [InlineData(-15.5)] +#if BUILDING_INBOX_LIBRARY [InlineData(float.MinValue)] [InlineData(float.MaxValue)] [InlineData(ulong.MinValue)] [InlineData(ulong.MaxValue)] +#endif public static void TestFloat(float value) { TestInitialization( @@ -194,6 +175,7 @@ public static void TestFloat(float value) [InlineData(-17)] [InlineData(3.14)] [InlineData(-15.5)] +#if BUILDING_INBOX_LIBRARY [InlineData(float.MinValue)] [InlineData(float.MaxValue)] [InlineData(float.MinValue - 1.0)] @@ -202,6 +184,7 @@ public static void TestFloat(float value) [InlineData(double.MaxValue)] [InlineData(ulong.MinValue)] [InlineData(ulong.MaxValue)] +#endif public static void TestDouble(double value) { TestInitialization( @@ -402,14 +385,19 @@ public static void TestUpcasts() Assert.True(jsonNumber.TryGetInt64(out long longResult)); Assert.Equal(value, longResult); +#if BUILDING_INBOX_LIBRARY Assert.Equal(value, jsonNumber.GetSingle()); Assert.True(jsonNumber.TryGetSingle(out float floatResult)); - Assert.Equal(value, floatResult, Precision); + Assert.Equal(value, floatResult); Assert.Equal(value, jsonNumber.GetDouble()); Assert.True(jsonNumber.TryGetDouble(out double doubleResult)); - Assert.Equal(value, doubleResult, Precision); + Assert.Equal(value, doubleResult); + Assert.Equal(value, jsonNumber.GetDecimal()); + Assert.True(jsonNumber.TryGetDecimal(out decimal decimalResult)); + Assert.Equal(value, decimalResult); +#endif Assert.Equal(value, (byte)jsonNumber.GetSByte()); Assert.True(jsonNumber.TryGetSByte(out sbyte sbyteResult)); Assert.Equal(value, (byte)sbyteResult); @@ -425,10 +413,6 @@ public static void TestUpcasts() Assert.Equal(value, jsonNumber.GetUInt64()); Assert.True(jsonNumber.TryGetUInt64(out ulong ulongResult)); Assert.Equal(value, ulongResult); - - Assert.Equal(value, jsonNumber.GetDecimal()); - Assert.True(jsonNumber.TryGetDecimal(out decimal decimalResult)); - Assert.Equal(value, decimalResult, Precision); } [Fact] @@ -504,7 +488,7 @@ public static void TestRationalGetMismatches() Assert.False(jsonNumber.TryGetUInt64(out ulong ulongResult)); Assert.Throws(() => jsonNumber.GetUInt64()); - +#if BUILDING_INBOX_LIBRARY jsonNumber = new JsonNumber(double.MaxValue); Assert.Equal(float.PositiveInfinity, jsonNumber.GetSingle()); Assert.Throws(() => jsonNumber.GetDecimal()); @@ -513,6 +497,7 @@ public static void TestRationalGetMismatches() Assert.Equal(float.PositiveInfinity, jsonNumber.GetSingle()); Assert.Equal(double.PositiveInfinity, jsonNumber.GetSingle()); Assert.Throws(() => jsonNumber.GetDecimal()); +#endif } [InlineData(float.PositiveInfinity)] @@ -531,25 +516,27 @@ public static void TestDoubleIninities(double value) Assert.Throws (() => new JsonNumber(value)); } +#if BUILDING_INBOX_LIBRARY [Fact] public static void TestScientificNotation() { var jsonNumber = new JsonNumber("5e6"); - Assert.Equal(5000000, jsonNumber.GetSingle(), Precision); - Assert.Equal(5000000, jsonNumber.GetDouble(), Precision); + Assert.Equal(5000000f, jsonNumber.GetSingle()); + Assert.Equal(5000000, jsonNumber.GetDouble()); jsonNumber = new JsonNumber("3.14e0"); - Assert.Equal(3.14, jsonNumber.GetSingle(), Precision); - Assert.Equal(3.14, jsonNumber.GetDouble(), Precision); + Assert.Equal(3.14f, jsonNumber.GetSingle()); + Assert.Equal(3.14, jsonNumber.GetDouble()); jsonNumber = new JsonNumber("7e-3"); - Assert.Equal(0.007, jsonNumber.GetSingle(), Precision); - Assert.Equal(0.007, jsonNumber.GetDouble(), Precision); + Assert.Equal(0.007f, jsonNumber.GetSingle()); + Assert.Equal(0.007, jsonNumber.GetDouble()); jsonNumber = new JsonNumber("-7e-3"); - Assert.Equal(-0.007, jsonNumber.GetSingle(), Precision); - Assert.Equal(-0.007, jsonNumber.GetDouble(), Precision); + Assert.Equal(-0.007f, jsonNumber.GetSingle()); + Assert.Equal(-0.007, jsonNumber.GetDouble()); } +#endif [Fact] public static void TestChangingTypes() From 2bd68719e8a912a7ed0834913895ab5a83dbddbd Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Tue, 6 Aug 2019 15:34:30 -0700 Subject: [PATCH 23/30] exception strings fixed --- src/System.Text.Json/src/Resources/Strings.resx | 8 +++++++- .../src/System/Text/Json/Node/JsonNumber.cs | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/System.Text.Json/src/Resources/Strings.resx b/src/System.Text.Json/src/Resources/Strings.resx index de5355866702..fedca40b03c3 100644 --- a/src/System.Text.Json/src/Resources/Strings.resx +++ b/src/System.Text.Json/src/Resources/Strings.resx @@ -423,4 +423,10 @@ Either the JSON value is not in a supported format, or is out of bounds for a UInt16. - + + Expected number, but instead got empty string. + + + Provided value does not represent legal JSON number. + + \ No newline at end of file diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index e4ace00663b0..84ac342b8323 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -453,7 +453,7 @@ public void SetFormattedValue(string value) { throw new ArgumentNullException(nameof(value)); } - throw new ArgumentException("Expected number, but instead got empty string.", nameof(value)); + throw new ArgumentException(SR.EmptyStringToInitializeNumber, nameof(value)); } JsonWriterHelper.ValidateNumber(Encoding.UTF8.GetBytes(value).AsSpan()); @@ -492,7 +492,7 @@ public void SetSingle(float value) { if (value.Equals(float.PositiveInfinity) || value.Equals(float.NegativeInfinity)) { - throw new FormatException("Provided value does not represent legal JSON number."); + throw new FormatException(SR.IllegalNumberFormat); } _value = value.ToString(); } @@ -504,7 +504,7 @@ public void SetDouble(double value) { if(value.Equals(double.PositiveInfinity) || value.Equals(double.NegativeInfinity)) { - throw new FormatException("Provided value does not represent legal JSON number."); + throw new FormatException(SR.IllegalNumberFormat); } _value = value.ToString(); } From f0c4814ff03b710d7f7b65f03ca02e0cba1c3d9f Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Wed, 7 Aug 2019 09:51:45 -0700 Subject: [PATCH 24/30] CI failing fixes (hopefully), review comments included --- .../src/Resources/Strings.resx | 2 +- .../src/System/Text/Json/Node/JsonNumber.cs | 47 ++++++++++------- src/System.Text.Json/tests/JsonNumberTests.cs | 51 +++++++++++++------ 3 files changed, 66 insertions(+), 34 deletions(-) diff --git a/src/System.Text.Json/src/Resources/Strings.resx b/src/System.Text.Json/src/Resources/Strings.resx index fedca40b03c3..c828f15a4b26 100644 --- a/src/System.Text.Json/src/Resources/Strings.resx +++ b/src/System.Text.Json/src/Resources/Strings.resx @@ -424,7 +424,7 @@ Either the JSON value is not in a supported format, or is out of bounds for a UInt16. - Expected number, but instead got empty string. + Expected a number, but instead got empty string. Provided value does not represent legal JSON number. diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 84ac342b8323..16f18e6f2138 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -59,12 +59,18 @@ public class JsonNumber : JsonNode, IEquatable /// Initializes a new instance of the class from a value. /// /// A value to represent as a JSON number. + /// + /// Provided value is not in a legal JSON number format. + /// public JsonNumber(float value) => SetSingle(value); /// /// Initializes a new instance of the class from a value. /// /// The value to represent as a JSON number. + /// + /// Provided value is not in a legal JSON number format. + /// public JsonNumber(double value) => SetDouble(value); /// @@ -177,7 +183,7 @@ public class JsonNumber : JsonNode, IEquatable /// /// Allows scientific mode. /// - public float GetSingle() => float.Parse(_value); + public float GetSingle() => float.Parse(_value, NumberStyles.Float, CultureInfo.InvariantCulture); /// /// Converts the numeric value of this instance to its equivalent. @@ -198,7 +204,7 @@ public class JsonNumber : JsonNode, IEquatable /// /// Allows scientific mode. /// - public double GetDouble() => double.Parse(_value); + public double GetDouble() => double.Parse(_value, NumberStyles.Float, CultureInfo.InvariantCulture); /// /// Converts the numeric value of this instance to its equivalent. @@ -262,7 +268,7 @@ public class JsonNumber : JsonNode, IEquatable /// /// represents a number in a format not compliant with . /// - public decimal GetDecimal() => decimal.Parse(_value); + public decimal GetDecimal() => decimal.Parse(_value, NumberStyles.Float, CultureInfo.InvariantCulture); /// /// Converts the numeric value of this instance to its equivalent. @@ -338,7 +344,7 @@ public class JsonNumber : JsonNode, IEquatable /// instead is returned and (or /// ) is emitted. /// - public bool TryGetSingle(out float value) => float.TryParse(_value, out value); + public bool TryGetSingle(out float value) => float.TryParse(_value, NumberStyles.Float, CultureInfo.InvariantCulture, out value); /// /// Converts the numeric value of this instance to its equivalent. @@ -358,7 +364,7 @@ public class JsonNumber : JsonNode, IEquatable /// instead is returned and (or /// ) is emitted. /// - public bool TryGetDouble(out double value) => double.TryParse(_value, out value); + public bool TryGetDouble(out double value) => double.TryParse(_value, NumberStyles.Float, CultureInfo.InvariantCulture, out value); /// /// Converts the numeric value of this instance to its equivalent. @@ -432,7 +438,7 @@ public class JsonNumber : JsonNode, IEquatable /// if instance was converted successfully; /// otherwise, /// - public bool TryGetDecimal(out decimal value) => decimal.TryParse(_value, out value); + public bool TryGetDecimal(out decimal value) => decimal.TryParse(_value, NumberStyles.Float, CultureInfo.InvariantCulture, out value); /// /// Changes the numeric value of this instance to represent a specified value. @@ -488,25 +494,25 @@ public void SetFormattedValue(string value) /// Changes the numeric value of this instance to represent a specified value. /// /// The value to represent as a JSON number. + /// + /// Provided value is not in a legal JSON number format. + /// public void SetSingle(float value) { - if (value.Equals(float.PositiveInfinity) || value.Equals(float.NegativeInfinity)) - { - throw new FormatException(SR.IllegalNumberFormat); - } - _value = value.ToString(); + JsonWriterHelper.ValidateSingle(value); + _value = value.ToString(CultureInfo.InvariantCulture); } /// /// Changes the numeric value of this instance to represent a specified value. /// /// The value to represent as a JSON number. + /// + /// Provided value is not in a legal JSON number format. + /// public void SetDouble(double value) { - if(value.Equals(double.PositiveInfinity) || value.Equals(double.NegativeInfinity)) - { - throw new FormatException(SR.IllegalNumberFormat); - } - _value = value.ToString(); + JsonWriterHelper.ValidateDouble(value); + _value = value.ToString(CultureInfo.InvariantCulture); } /// @@ -541,7 +547,8 @@ public void SetDouble(double value) /// Changes the numeric value of this instance to represent a specified value. /// /// The value to represent as a JSON number. - public void SetDecimal(decimal value) => _value = value.ToString(); + public void SetDecimal(decimal value) => _value = value.ToString(CultureInfo.InvariantCulture); + /// /// Converts a to a JSON number. @@ -571,12 +578,18 @@ public void SetDouble(double value) /// Converts a to a JSON number. /// /// The value to convert. + /// + /// Provided value is not in a legal JSON number format. + /// public static implicit operator JsonNumber(float value) => new JsonNumber(value); /// /// Converts a to a JSON number. /// /// The value to convert. + /// + /// Provided value is not in a legal JSON number format. + /// public static implicit operator JsonNumber(double value) => new JsonNumber(value); /// diff --git a/src/System.Text.Json/tests/JsonNumberTests.cs b/src/System.Text.Json/tests/JsonNumberTests.cs index 6a1ce1bc863f..ab1db847ce5a 100644 --- a/src/System.Text.Json/tests/JsonNumberTests.cs +++ b/src/System.Text.Json/tests/JsonNumberTests.cs @@ -32,6 +32,7 @@ private static void TestInitialization( // String constructor: number = value switch { + // Adding CultureInfo.InvariantCulture to support tests on plantforms where `,` is a default decimal separator instead of `.` double doubleValue => new JsonNumber(doubleValue.ToString(CultureInfo.InvariantCulture)), float floatValue => new JsonNumber(floatValue.ToString(CultureInfo.InvariantCulture)), decimal decimalValue => new JsonNumber(decimalValue.ToString(CultureInfo.InvariantCulture)), @@ -182,7 +183,6 @@ public static void TestFloat(float value) [InlineData(float.MaxValue + 1.0)] [InlineData(double.MinValue)] [InlineData(double.MaxValue)] - [InlineData(ulong.MinValue)] [InlineData(ulong.MaxValue)] #endif public static void TestDouble(double value) @@ -385,7 +385,6 @@ public static void TestUpcasts() Assert.True(jsonNumber.TryGetInt64(out long longResult)); Assert.Equal(value, longResult); -#if BUILDING_INBOX_LIBRARY Assert.Equal(value, jsonNumber.GetSingle()); Assert.True(jsonNumber.TryGetSingle(out float floatResult)); Assert.Equal(value, floatResult); @@ -397,7 +396,7 @@ public static void TestUpcasts() Assert.Equal(value, jsonNumber.GetDecimal()); Assert.True(jsonNumber.TryGetDecimal(out decimal decimalResult)); Assert.Equal(value, decimalResult); -#endif + Assert.Equal(value, (byte)jsonNumber.GetSByte()); Assert.True(jsonNumber.TryGetSByte(out sbyte sbyteResult)); Assert.Equal(value, (byte)sbyteResult); @@ -488,24 +487,45 @@ public static void TestRationalGetMismatches() Assert.False(jsonNumber.TryGetUInt64(out ulong ulongResult)); Assert.Throws(() => jsonNumber.GetUInt64()); -#if BUILDING_INBOX_LIBRARY + jsonNumber = new JsonNumber(double.MaxValue); - Assert.Equal(float.PositiveInfinity, jsonNumber.GetSingle()); - Assert.Throws(() => jsonNumber.GetDecimal()); - jsonNumber = new JsonNumber("1e100"); - Assert.Equal(float.PositiveInfinity, jsonNumber.GetSingle()); - Assert.Equal(double.PositiveInfinity, jsonNumber.GetSingle()); - Assert.Throws(() => jsonNumber.GetDecimal()); -#endif + if (PlatformDetection.IsFullFramework) + { + // Full framework throws for overflow rather than returning Infinity + // This was fixed for .NET Core 3.0 in order to be IEEE 754 compliant + Assert.Throws(() => jsonNumber.GetSingle()); + // Getting double fails as well + Assert.Throws(() => jsonNumber.GetDouble()); + } + else + { + Assert.Equal(float.PositiveInfinity, jsonNumber.GetSingle()); + } + Assert.Throws(() => jsonNumber.GetDecimal()); + + jsonNumber = new JsonNumber("5e500"); + + if (PlatformDetection.IsFullFramework) + { + Assert.Throws(() => jsonNumber.GetSingle()); + Assert.Throws(() => jsonNumber.GetDouble()); + } + else + { + Assert.Equal(float.PositiveInfinity, jsonNumber.GetSingle()); + Assert.Equal(double.PositiveInfinity, jsonNumber.GetDouble()); + } + + Assert.Throws(() => jsonNumber.GetDecimal()); } [InlineData(float.PositiveInfinity)] [InlineData(float.NegativeInfinity)] [Theory] - public static void TestFloatninities(float value) + public static void TestFloatInfinities(float value) { - Assert.Throws(() => new JsonNumber(value)); + Assert.Throws(() => new JsonNumber(value)); } [InlineData(double.PositiveInfinity)] @@ -513,10 +533,9 @@ public static void TestFloatninities(float value) [Theory] public static void TestDoubleIninities(double value) { - Assert.Throws (() => new JsonNumber(value)); + Assert.Throws (() => new JsonNumber(value)); } -#if BUILDING_INBOX_LIBRARY [Fact] public static void TestScientificNotation() { @@ -536,7 +555,7 @@ public static void TestScientificNotation() Assert.Equal(-0.007f, jsonNumber.GetSingle()); Assert.Equal(-0.007, jsonNumber.GetDouble()); } -#endif + [Fact] public static void TestChangingTypes() From c22b36dd32139e33a851b23bcb0ab02cdd5b76ff Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Wed, 7 Aug 2019 10:04:33 -0700 Subject: [PATCH 25/30] missing == tests added to achieve 100% branch coverage --- src/System.Text.Json/tests/JsonNumberTests.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/System.Text.Json/tests/JsonNumberTests.cs b/src/System.Text.Json/tests/JsonNumberTests.cs index ab1db847ce5a..d7764ac5839b 100644 --- a/src/System.Text.Json/tests/JsonNumberTests.cs +++ b/src/System.Text.Json/tests/JsonNumberTests.cs @@ -638,6 +638,15 @@ public static void TestEquals() jsonNumber = new JsonNumber(); Assert.True(jsonNumber.Equals(new JsonNumber())); Assert.False(jsonNumber.Equals(new JsonNumber(5))); + + Assert.False(jsonNumber.Equals(new Exception())); + + JsonNumber jsonNumberNull = null; + Assert.False(jsonNumber == jsonNumberNull); + Assert.False(jsonNumberNull == jsonNumber); + + Assert.True(jsonNumber != jsonNumberNull); + Assert.True(jsonNumberNull != jsonNumber); } [Fact] From 7dfc891c9fb87b314464b73f9231cbf1b505dc67 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Thu, 8 Aug 2019 08:28:45 -0700 Subject: [PATCH 26/30] review comments included --- src/System.Text.Json/ref/System.Text.Json.cs | 2 +- src/System.Text.Json/src/Resources/Strings.resx | 3 --- .../src/System/Text/Json/Node/JsonNumber.cs | 14 +++++++++++--- src/System.Text.Json/tests/JsonNumberTests.cs | 3 +-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/System.Text.Json/ref/System.Text.Json.cs b/src/System.Text.Json/ref/System.Text.Json.cs index a23bd0887c0f..1677a542ee48 100644 --- a/src/System.Text.Json/ref/System.Text.Json.cs +++ b/src/System.Text.Json/ref/System.Text.Json.cs @@ -160,7 +160,7 @@ public abstract partial class JsonNode { internal JsonNode() { } } - public partial class JsonNumber : System.Text.Json.JsonNode, System.IEquatable + public sealed partial class JsonNumber : System.Text.Json.JsonNode, System.IEquatable { public JsonNumber() { } public JsonNumber(byte value) { } diff --git a/src/System.Text.Json/src/Resources/Strings.resx b/src/System.Text.Json/src/Resources/Strings.resx index c828f15a4b26..cd7633baa66c 100644 --- a/src/System.Text.Json/src/Resources/Strings.resx +++ b/src/System.Text.Json/src/Resources/Strings.resx @@ -426,7 +426,4 @@ Expected a number, but instead got empty string. - - Provided value does not represent legal JSON number. - \ No newline at end of file diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 16f18e6f2138..04fe3539e010 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -9,7 +9,7 @@ namespace System.Text.Json /// /// Represents a numeric JSON value. /// - public class JsonNumber : JsonNode, IEquatable + public sealed class JsonNumber : JsonNode, IEquatable { private string _value; @@ -661,7 +661,15 @@ public void SetDouble(double value) /// if values of instances match exactly (are equal and have the same format), /// otherwise. /// - public static bool operator ==(JsonNumber left, JsonNumber right) => left?._value == right?._value; + public static bool operator ==(JsonNumber left, JsonNumber right) + { + if (right is null) + { + return (left is null) ? true : false; + } + + return right.Equals(left); + } /// /// Compares values of two JSON numbers. @@ -672,6 +680,6 @@ public void SetDouble(double value) /// if values of instances do not match exactly (are not equal or have different format), /// otherwise. /// - public static bool operator !=(JsonNumber left, JsonNumber right) => left?._value != right?._value; + public static bool operator !=(JsonNumber left, JsonNumber right) => !(left == right); } } diff --git a/src/System.Text.Json/tests/JsonNumberTests.cs b/src/System.Text.Json/tests/JsonNumberTests.cs index d7764ac5839b..ed5f9d671ced 100644 --- a/src/System.Text.Json/tests/JsonNumberTests.cs +++ b/src/System.Text.Json/tests/JsonNumberTests.cs @@ -32,7 +32,7 @@ private static void TestInitialization( // String constructor: number = value switch { - // Adding CultureInfo.InvariantCulture to support tests on plantforms where `,` is a default decimal separator instead of `.` + // Adding CultureInfo.InvariantCulture to support tests on platforms where `,` is a default decimal separator instead of `.` double doubleValue => new JsonNumber(doubleValue.ToString(CultureInfo.InvariantCulture)), float floatValue => new JsonNumber(floatValue.ToString(CultureInfo.InvariantCulture)), decimal decimalValue => new JsonNumber(decimalValue.ToString(CultureInfo.InvariantCulture)), @@ -156,7 +156,6 @@ public static void TestLong(long value) #if BUILDING_INBOX_LIBRARY [InlineData(float.MinValue)] [InlineData(float.MaxValue)] - [InlineData(ulong.MinValue)] [InlineData(ulong.MaxValue)] #endif public static void TestFloat(float value) From ab1401afccbc3c7166e28684fa546876bcaaddbc Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Thu, 8 Aug 2019 10:01:41 -0700 Subject: [PATCH 27/30] trailing whitespaces fixes --- .../src/System/Text/Json/Node/JsonNumber.cs | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 04fe3539e010..9914cd8b3af8 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -28,7 +28,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// /// Provided value is not in a legal JSON number format. /// - /// Provided value is stored in the same format as passed. + /// Provided value is stored in the same format as passed. public JsonNumber(string value) => SetFormattedValue(value); /// @@ -111,9 +111,9 @@ public sealed class JsonNumber : JsonNode, IEquatable /// Converts the numeric value of this instance to its equivalent string representation. /// /// The string representation of the value of this instance. - /// - /// Returns exactly the same value as it was set using . - /// + /// + /// Returns exactly the same value as it was set using . + /// public override string ToString() => _value; /// @@ -174,17 +174,17 @@ public sealed class JsonNumber : JsonNode, IEquatable /// /// represents a number in a format not compliant with . /// - /// - /// On .NET Core this method does not return for values larger than - /// (or smaller than ), - /// instead is returned and (or - /// ) is emitted. - /// - /// + /// + /// On .NET Core this method does not return for values larger than + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. + /// + /// /// Allows scientific mode. - /// + /// public float GetSingle() => float.Parse(_value, NumberStyles.Float, CultureInfo.InvariantCulture); - + /// /// Converts the numeric value of this instance to its equivalent. /// @@ -195,13 +195,13 @@ public sealed class JsonNumber : JsonNode, IEquatable /// /// represents a number in a format not compliant with . /// - /// - /// On .NET Core this method does not return for values larger than - /// (or smaller than ), - /// instead is returned and (or - /// ) is emitted. - /// - /// + /// + /// On .NET Core this method does not return for values larger than + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. + /// + /// /// Allows scientific mode. /// public double GetDouble() => double.Parse(_value, NumberStyles.Float, CultureInfo.InvariantCulture); @@ -279,7 +279,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetByte(out byte value) => byte.TryParse(_value, out value); @@ -293,7 +293,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetInt16(out short value) => short.TryParse(_value, out value); @@ -307,7 +307,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetInt32(out int value) => int.TryParse(_value, out value); @@ -321,7 +321,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetInt64(out long value) => long.TryParse(_value, out value); @@ -335,15 +335,15 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// - /// - /// On .NET Core this method does not return for values larger than - /// (or smaller than ), - /// instead is returned and (or - /// ) is emitted. - /// + /// + /// On .NET Core this method does not return for values larger than + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. + /// public bool TryGetSingle(out float value) => float.TryParse(_value, NumberStyles.Float, CultureInfo.InvariantCulture, out value); /// @@ -355,15 +355,15 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// - /// - /// On .NET Core this method does not return for values larger than - /// (or smaller than ), - /// instead is returned and (or - /// ) is emitted. - /// + /// + /// On .NET Core this method does not return for values larger than + /// (or smaller than ), + /// instead is returned and (or + /// ) is emitted. + /// public bool TryGetDouble(out double value) => double.TryParse(_value, NumberStyles.Float, CultureInfo.InvariantCulture, out value); /// @@ -375,7 +375,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// [CLSCompliant(false)] @@ -390,7 +390,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// [CLSCompliant(false)] @@ -405,7 +405,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// [CLSCompliant(false)] @@ -420,7 +420,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// [CLSCompliant(false)] @@ -435,7 +435,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// if the conversion succeeded, or zero if the conversion failed. /// /// - /// if instance was converted successfully; + /// if instance was converted successfully; /// otherwise, /// public bool TryGetDecimal(out decimal value) => decimal.TryParse(_value, NumberStyles.Float, CultureInfo.InvariantCulture, out value); @@ -450,7 +450,7 @@ public sealed class JsonNumber : JsonNode, IEquatable /// /// Provided value is not in a legal JSON number format. /// - /// Provided value is stored in the same format as passed. + /// Provided value is stored in the same format as passed. public void SetFormattedValue(string value) { if (string.IsNullOrEmpty(value)) @@ -460,8 +460,8 @@ public void SetFormattedValue(string value) throw new ArgumentNullException(nameof(value)); } throw new ArgumentException(SR.EmptyStringToInitializeNumber, nameof(value)); - } - + } + JsonWriterHelper.ValidateNumber(Encoding.UTF8.GetBytes(value).AsSpan()); _value = value; } @@ -548,7 +548,7 @@ public void SetDouble(double value) /// /// The value to represent as a JSON number. public void SetDecimal(decimal value) => _value = value.ToString(CultureInfo.InvariantCulture); - + /// /// Converts a to a JSON number. @@ -627,7 +627,7 @@ public void SetDouble(double value) public static implicit operator JsonNumber(decimal value) => new JsonNumber(value); /// - /// Compares to the value of this instance. + /// Compares to the value of this instance. /// /// The object to compare against. /// @@ -643,7 +643,7 @@ public void SetDouble(double value) public override int GetHashCode() => _value.GetHashCode(); /// - /// Compares other JSON number to the value of this instance. + /// Compares other JSON number to the value of this instance. /// /// The JSON number to compare against. /// @@ -653,7 +653,7 @@ public void SetDouble(double value) public bool Equals(JsonNumber other) => !(other is null) && _value == other._value; /// - /// Compares values of two JSON numbers. + /// Compares values of two JSON numbers. /// /// The JSON number to compare. /// The JSON number to compare. @@ -672,7 +672,7 @@ public void SetDouble(double value) } /// - /// Compares values of two JSON numbers. + /// Compares values of two JSON numbers. /// /// The JSON number to compare. /// The JSON number to compare. From 217bade85fb747f3f851ece50ff64aee7865e2e1 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Thu, 8 Aug 2019 15:14:54 -0700 Subject: [PATCH 28/30] equals comments added --- src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 9914cd8b3af8..f47d651329da 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -663,8 +663,11 @@ public void SetDouble(double value) /// public static bool operator ==(JsonNumber left, JsonNumber right) { + // Test "right" first to allow branch elimination when inlined for null checks (== null) + // so it can become a simple test if (right is null) { + // return true/false not the test result https://github.com/dotnet/coreclr/issues/914 return (left is null) ? true : false; } From 40a664971b2898e47d8d2e6cef9022540d05e24e Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Thu, 8 Aug 2019 15:19:57 -0700 Subject: [PATCH 29/30] equals object refactored to call quals json number --- src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index f47d651329da..57b4c754bcfc 100644 --- a/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -634,7 +634,7 @@ public void SetDouble(double value) /// if the value of this instance matches exactly (is equal and has the same format), /// otherwise. /// - public override bool Equals(object obj) => obj is JsonNumber number && _value == number._value; + public override bool Equals(object obj) => obj is JsonNumber jsonNumber && Equals(jsonNumber); /// /// Calculates a hash code of this instance. From f5344152c6fcaea213eb5e6bba2cad5ade89e088 Mon Sep 17 00:00:00 2001 From: Katarzyna Bulat Date: Thu, 8 Aug 2019 15:26:19 -0700 Subject: [PATCH 30/30] merge fix --- src/System.Text.Json/src/Resources/Strings.resx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/System.Text.Json/src/Resources/Strings.resx b/src/System.Text.Json/src/Resources/Strings.resx index ae046eabcd57..898e45978013 100644 --- a/src/System.Text.Json/src/Resources/Strings.resx +++ b/src/System.Text.Json/src/Resources/Strings.resx @@ -426,8 +426,7 @@ A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of {0}. - Expected a number, but instead got empty string. - \ No newline at end of file +