diff --git a/NWN.Anvil.Tests/src/main/API/ColorTests.cs b/NWN.Anvil.Tests/src/main/API/ColorTests.cs index 9cf445b30..cb213c6a5 100644 --- a/NWN.Anvil.Tests/src/main/API/ColorTests.cs +++ b/NWN.Anvil.Tests/src/main/API/ColorTests.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; +using System.Text.Json; using Anvil.API; -using Newtonsoft.Json; using NUnit.Framework; namespace Anvil.Tests.API @@ -46,7 +46,7 @@ public void CreateColorTokenContainsNoNullTerminators(Color color) [TestCase("""{"r":255,"g":100,"b":10,"a":30}""", 255, 100, 10, 30)] public void DeserializeColorCreatesCorrectColor(string json, byte expectedRed, byte expectedGreen, byte expectedBlue, byte expectedAlpha) { - Color color = JsonConvert.DeserializeObject(json); + Color color = JsonSerializer.Deserialize(json); Assert.That(color, Is.EqualTo(new Color(expectedRed, expectedGreen, expectedBlue, expectedAlpha))); } @@ -96,8 +96,8 @@ public void ParseRGBAReturnsCorrectColor(uint packedColor, byte expectedRed, byt [TestCaseSource(nameof(ColorTestCases))] public void SerializeColorRetainsColorValues(Color color) { - string serializedColor = JsonConvert.SerializeObject(color); - Color deserializedColor = JsonConvert.DeserializeObject(serializedColor); + string serializedColor = JsonSerializer.Serialize(color); + Color deserializedColor = JsonSerializer.Deserialize(serializedColor); Assert.That(deserializedColor, Is.EqualTo(color)); } diff --git a/NWN.Anvil.Tests/src/main/API/EngineStructures/JsonTests.cs b/NWN.Anvil.Tests/src/main/API/EngineStructures/JsonTests.cs index 6306dbc29..b45c6a20e 100644 --- a/NWN.Anvil.Tests/src/main/API/EngineStructures/JsonTests.cs +++ b/NWN.Anvil.Tests/src/main/API/EngineStructures/JsonTests.cs @@ -10,7 +10,7 @@ public sealed class JsonTests public void CreateAndDisposeJsonFreesNativeStructure() { int[] test = [1, 2]; - Json json = JsonUtility.ToJsonStructure(test); + Json json = Json.Serialize(test); Assert.That(json.IsValid, Is.True, "Json struct was not valid after creation."); json.Dispose(); diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Bindings/NuiBindTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Bindings/NuiBindTests.cs index 48b5c3f80..ebf78c876 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Bindings/NuiBindTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Bindings/NuiBindTests.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -10,44 +11,44 @@ public sealed class NuiBindTests public void SerializeNuiBindStringReturnsValidJson() { NuiBind bind = new NuiBind("test"); - Assert.That(JsonUtility.ToJson(bind), Is.EqualTo("""{"bind":"test"}""")); - Assert.That(JsonUtility.ToJson>(bind), Is.EqualTo("""{"bind":"test"}""")); + Assert.That(JsonSerializer.Serialize(bind), Is.EqualTo("""{"bind":"test"}""")); + Assert.That(JsonSerializer.Serialize((NuiProperty)bind), Is.EqualTo("""{"bind":"test"}""")); } [Test(Description = "Serializing a NuiBind creates a valid JSON structure.")] public void SerializeNuiBindStrRefReturnsValidJson() { NuiBindStrRef bind = new NuiBindStrRef("test"); - Assert.That(JsonUtility.ToJson(bind), Is.EqualTo("""{"bind":"test"}""")); - Assert.That(JsonUtility.ToJson>(bind), Is.EqualTo("""{"bind":"test"}""")); + Assert.That(JsonSerializer.Serialize(bind), Is.EqualTo("""{"bind":"test"}""")); + Assert.That(JsonSerializer.Serialize((NuiProperty)bind), Is.EqualTo("""{"bind":"test"}""")); } [Test(Description = "Serializing a NuiBind creates a valid JSON structure.")] public void SerializeNuiBindNuiRectReturnsValidJson() { NuiBind bind = new NuiBind("test"); - Assert.That(JsonUtility.ToJson(bind), Is.EqualTo("""{"bind":"test"}""")); - Assert.That(JsonUtility.ToJson>(bind), Is.EqualTo("""{"bind":"test"}""")); + Assert.That(JsonSerializer.Serialize(bind), Is.EqualTo("""{"bind":"test"}""")); + Assert.That(JsonSerializer.Serialize((NuiProperty)bind), Is.EqualTo("""{"bind":"test"}""")); } - [Test(Description = "Deerializing a NuiBind creates a valid value/object.")] + [Test(Description = "Deserializing a NuiBind creates a valid value/object.")] public void DeserializeNuiBindStringReturnsValidJson() { - NuiBind? bind = JsonUtility.FromJson>("""{"bind":"test"}"""); + NuiBind? bind = JsonSerializer.Deserialize>("""{"bind":"test"}"""); Assert.That(bind?.Key, Is.EqualTo("test")); } - [Test(Description = "Deerializing a NuiBind creates a valid value/object.")] + [Test(Description = "Deserializing a NuiBind creates a valid value/object.")] public void DeserializeNuiBindStrRefReturnsValidJson() { - NuiBind? bind = JsonUtility.FromJson>("""{"bind":"test"}"""); + NuiBind? bind = JsonSerializer.Deserialize>("""{"bind":"test"}"""); Assert.That(bind?.Key, Is.EqualTo("test")); } - [Test(Description = "Deerializing a NuiBind creates a valid value/object.")] + [Test(Description = "Deserializing a NuiBind creates a valid value/object.")] public void DeserializeNuiBindNuiRectReturnsValidJson() { - NuiBind? bind = JsonUtility.FromJson>("""{"bind":"test"}"""); + NuiBind? bind = JsonSerializer.Deserialize>("""{"bind":"test"}"""); Assert.That(bind?.Key, Is.EqualTo("test")); } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Bindings/NuiValueTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Bindings/NuiValueTests.cs index 29d3016af..1083b9a6e 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Bindings/NuiValueTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Bindings/NuiValueTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -18,8 +19,8 @@ public sealed class NuiValueTests public void SerializeNuiValueStringReturnsValidJson(string rawValue, string expected) { NuiValue value = new NuiValue(rawValue); - Assert.That(JsonUtility.ToJson(value), Is.EqualTo(expected)); - Assert.That(JsonUtility.ToJson>(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize((NuiProperty)value), Is.EqualTo(expected)); } [Test(Description = "Serializing a NuiValueStrRef creates a valid JSON structure.")] @@ -29,8 +30,8 @@ public void SerializeNuiValueStringReturnsValidJson(string rawValue, string expe public void SerializeNuiValueStrRefReturnsValidJson(uint? rawValue, string expected) { NuiValueStrRef value = new NuiValueStrRef(rawValue != null ? new StrRef(rawValue.Value) : null); - Assert.That(JsonUtility.ToJson(value), Is.EqualTo(expected)); - Assert.That(JsonUtility.ToJson>(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize((NuiProperty)value), Is.EqualTo(expected)); } [Test(Description = "Serializing a NuiValue creates a valid JSON structure.")] @@ -43,8 +44,8 @@ public void SerializeNuiValueStrRefReturnsValidJson(uint? rawValue, string expec public void SerializeNuiValueIntReturnsValidJson(int rawValue, string expected) { NuiValue value = new NuiValue(rawValue); - Assert.That(JsonUtility.ToJson(value), Is.EqualTo(expected)); - Assert.That(JsonUtility.ToJson>(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize((NuiProperty)value), Is.EqualTo(expected)); } [Test(Description = "Serializing a NuiValue creates a valid JSON structure.")] @@ -58,72 +59,54 @@ public void SerializeNuiValueIntReturnsValidJson(int rawValue, string expected) public void SerializeNuiValueNullableIntReturnsValidJson(int? rawValue, string expected) { NuiValue value = new NuiValue(rawValue); - Assert.That(JsonUtility.ToJson(value), Is.EqualTo(expected)); - Assert.That(JsonUtility.ToJson>(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize((NuiProperty)value), Is.EqualTo(expected)); } [Test(Description = "Serializing a NuiValue creates a valid JSON structure.")] - [TestCase(0f, @"0.0")] + [TestCase(0f, @"0")] [TestCase(0.1f, @"0.1")] [TestCase(0.125f, @"0.125")] - [TestCase(2f, @"2.0")] + [TestCase(2f, @"2")] [TestCase(2.5f, @"2.5")] [TestCase(2.5122f, @"2.5122")] - [TestCase(float.NaN, """ - "NaN" - """)] - [TestCase(float.NegativeInfinity, """ - "-Infinity" - """)] - [TestCase(float.PositiveInfinity, """ - "Infinity" - """)] public void SerializeNuiValueFloatReturnsValidJson(float rawValue, string expected) { NuiValue value = new NuiValue(rawValue); - Assert.That(JsonUtility.ToJson(value), Is.EqualTo(expected)); - Assert.That(JsonUtility.ToJson>(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize((NuiProperty)value), Is.EqualTo(expected)); } [Test(Description = "Serializing a NuiValue creates a valid JSON structure.")] - [TestCase(0f, @"0.0")] + [TestCase(0f, @"0")] [TestCase(0.1f, @"0.1")] [TestCase(0.125f, @"0.125")] - [TestCase(2f, @"2.0")] + [TestCase(2f, @"2")] [TestCase(2.5f, @"2.5")] [TestCase(2.5122f, @"2.5122")] [TestCase(null, @"null")] - [TestCase(float.NaN, """ - "NaN" - """)] - [TestCase(float.NegativeInfinity, """ - "-Infinity" - """)] - [TestCase(float.PositiveInfinity, """ - "Infinity" - """)] public void SerializeNuiValueFloatNullableReturnsValidJson(float? rawValue, string expected) { NuiValue value = new NuiValue(rawValue); - Assert.That(JsonUtility.ToJson(value), Is.EqualTo(expected)); - Assert.That(JsonUtility.ToJson>(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize((NuiProperty)value), Is.EqualTo(expected)); } [Test(Description = "Serializing a NuiValue creates a valid JSON structure.")] public void SerializeNuiValueNuiRectReturnsValidJson() { NuiValue value = new NuiValue(new NuiRect(100f, 50.251f, 30.11f, 20f)); - Assert.That(JsonUtility.ToJson>(value), Is.EqualTo("""{"h":20.0,"w":30.11,"x":100.0,"y":50.251}""")); + Assert.That(JsonSerializer.Serialize((NuiProperty)value), Is.EqualTo("""{"h":20,"w":30.11,"x":100,"y":50.251}""")); } [Test(Description = "Serializing a NuiValue> creates a valid JSON structure.")] public void SerializeNuiValueIntListReturnsValidJson() { NuiValue> value = new NuiValue>([1, 2, 3]); - Assert.That(JsonUtility.ToJson>>(value), Is.EqualTo(@"[1,2,3]")); + Assert.That(JsonSerializer.Serialize((NuiProperty>)value), Is.EqualTo(@"[1,2,3]")); } - [Test(Description = "Deerializing a NuiValue creates a valid value/object.")] + [Test(Description = "Deserializing a NuiValue creates a valid value/object.")] [TestCase("test", """ "test" """)] @@ -133,21 +116,21 @@ public void SerializeNuiValueIntListReturnsValidJson() """)] public void DeserializeNuiValueStringReturnsValidJson(string expected, string serialized) { - NuiValue? value = JsonUtility.FromJson>(serialized); + NuiValue? value = JsonSerializer.Deserialize>(serialized); Assert.That(value?.Value, Is.EqualTo(expected)); } - [Test(Description = "Deerializing a NuiValueStrRef creates a valid value/object.")] + [Test(Description = "Deserializing a NuiValueStrRef creates a valid value/object.")] [TestCase(0u, """{"strref":0}""")] [TestCase(null, @"null")] [TestCase(1000u, """{"strref":1000}""")] public void DeserializeNuiValueStrRefReturnsValidJson(uint? expected, string serialized) { - NuiValueStrRef? value = JsonUtility.FromJson(serialized); + NuiValueStrRef? value = JsonSerializer.Deserialize(serialized); Assert.That(value?.Value?.Id, Is.EqualTo(expected)); } - [Test(Description = "Deerializing a NuiValue creates a valid value/object.")] + [Test(Description = "Deserializing a NuiValue creates a valid value/object.")] [TestCase(0, @"0")] [TestCase(-0, @"0")] [TestCase(10, @"10")] @@ -156,11 +139,11 @@ public void DeserializeNuiValueStrRefReturnsValidJson(uint? expected, string ser [TestCase(int.MinValue, @"-2147483648")] public void DeserializeNuiValueIntReturnsValidJson(int expected, string serialized) { - NuiValue? value = JsonUtility.FromJson>(serialized); + NuiValue? value = JsonSerializer.Deserialize>(serialized); Assert.That(value?.Value, Is.EqualTo(expected)); } - [Test(Description = "Deerializing a NuiValue creates a valid value/object.")] + [Test(Description = "Deserializing a NuiValue creates a valid value/object.")] [TestCase(0, @"0")] [TestCase(-0, @"0")] [TestCase(10, @"10")] @@ -170,59 +153,41 @@ public void DeserializeNuiValueIntReturnsValidJson(int expected, string serializ [TestCase(int.MinValue, @"-2147483648")] public void DeserializeNuiValueNullableIntReturnsValidJson(int? expected, string serialized) { - NuiValue? value = JsonUtility.FromJson>(serialized); + NuiValue? value = JsonSerializer.Deserialize>(serialized); Assert.That(value?.Value, Is.EqualTo(expected)); } - [Test(Description = "Deerializing a NuiValue creates a valid value/object.")] - [TestCase(0f, @"0.0")] + [Test(Description = "Deserializing a NuiValue creates a valid value/object.")] + [TestCase(0f, @"0")] [TestCase(0.1f, @"0.1")] [TestCase(0.125f, @"0.125")] - [TestCase(2f, @"2.0")] + [TestCase(2f, @"2")] [TestCase(2.5f, @"2.5")] [TestCase(2.5122f, @"2.5122")] - [TestCase(float.NaN, """ - "NaN" - """)] - [TestCase(float.NegativeInfinity, """ - "-Infinity" - """)] - [TestCase(float.PositiveInfinity, """ - "Infinity" - """)] public void DeserializeNuiValueFloatReturnsValidJson(float expected, string serialized) { - NuiValue? value = JsonUtility.FromJson>(serialized); + NuiValue? value = JsonSerializer.Deserialize>(serialized); Assert.That(value?.Value, Is.EqualTo(expected)); } - [Test(Description = "Deerializing a NuiValue creates a valid value/object.")] - [TestCase(0f, @"0.0")] + [Test(Description = "Deserializing a NuiValue creates a valid value/object.")] + [TestCase(0f, @"0")] [TestCase(0.1f, @"0.1")] [TestCase(0.125f, @"0.125")] - [TestCase(2f, @"2.0")] + [TestCase(2f, @"2")] [TestCase(2.5f, @"2.5")] [TestCase(2.5122f, @"2.5122")] [TestCase(null, @"null")] - [TestCase(float.NaN, """ - "NaN" - """)] - [TestCase(float.NegativeInfinity, """ - "-Infinity" - """)] - [TestCase(float.PositiveInfinity, """ - "Infinity" - """)] public void DeserializeNuiValueFloatNullableReturnsValidJson(float? expected, string serialized) { - NuiValue? value = JsonUtility.FromJson>(serialized); + NuiValue? value = JsonSerializer.Deserialize>(serialized); Assert.That(value?.Value, Is.EqualTo(expected)); } - [Test(Description = "Deerializing a NuiValue creates a valid value/object.")] + [Test(Description = "Deserializing a NuiValue creates a valid value/object.")] public void DeserializeNuiValueNuiRectReturnsValidJson() { - NuiValue? value = JsonUtility.FromJson>("""{"h":20.0,"w":30.11,"x":100.0,"y":50.251}"""); + NuiValue? value = JsonSerializer.Deserialize>("""{"h":20,"w":30.11,"x":100,"y":50.251}"""); NuiRect expected = new NuiRect(100.0f, 50.251f, 30.11f, 20.0f); Assert.That(value?.Value, Is.EqualTo(expected)); @@ -231,7 +196,7 @@ public void DeserializeNuiValueNuiRectReturnsValidJson() [Test(Description = "Deserializing a NuiValue> creates a valid value/object.")] public void DeserializeNuiValueIntListReturnsValidJson() { - NuiValue>? value = JsonUtility.FromJson>>(@"[1,2,3]"); + NuiValue>? value = JsonSerializer.Deserialize>>(@"[1,2,3]"); List expected = [1, 2, 3]; Assert.That(value?.Value, Is.EqualTo(expected)); diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiColumnTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiColumnTests.cs index eaf90cf98..c84b9a638 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiColumnTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiColumnTests.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -28,8 +29,8 @@ public void SerializeNuiColumnReturnsValidJson() ], }; - Assert.That(JsonUtility.ToJson(layout), Is.EqualTo("""{"type":"col","children":[{"text_halign":1,"value":"test","type":"label","text_valign":1},{"type":"row","children":[]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10.0,"id":"test_column","margin":2.0,"padding":3.0,"tooltip":"test_tooltip","visible":false,"width":100.0}""")); - Assert.That(JsonUtility.ToJson(layout), Is.EqualTo("""{"type":"col","children":[{"text_halign":1,"value":"test","type":"label","text_valign":1},{"type":"row","children":[]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10.0,"id":"test_column","margin":2.0,"padding":3.0,"tooltip":"test_tooltip","visible":false,"width":100.0}""")); + Assert.That(JsonSerializer.Serialize(layout), Is.EqualTo("""{"type":"col","children":[{"text_halign":1,"value":"test","type":"label","text_valign":1},{"type":"row","children":[]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10,"id":"test_column","margin":2,"padding":3,"tooltip":"test_tooltip","visible":false,"width":100}""")); + Assert.That(JsonSerializer.Serialize((NuiLayout)layout), Is.EqualTo("""{"type":"col","children":[{"text_halign":1,"value":"test","type":"label","text_valign":1},{"type":"row","children":[]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10,"id":"test_column","margin":2,"padding":3,"tooltip":"test_tooltip","visible":false,"width":100}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiGroupTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiGroupTests.cs index 5554932b9..3a7857a3d 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiGroupTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiGroupTests.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -32,8 +33,8 @@ public void SerializeNuiGroupReturnsValidJson() }, }; - Assert.That(JsonUtility.ToJson(layout), Is.EqualTo("""{"border":true,"scrollbars":3,"type":"group","children":[{"type":"col","children":[{"text_halign":1,"value":"Test","type":"label","text_valign":1}]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10.0,"id":"test_group","margin":2.0,"padding":3.0,"tooltip":"test_tooltip","visible":false,"width":100.0}""")); - Assert.That(JsonUtility.ToJson(layout), Is.EqualTo("""{"border":true,"scrollbars":3,"type":"group","children":[{"type":"col","children":[{"text_halign":1,"value":"Test","type":"label","text_valign":1}]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10.0,"id":"test_group","margin":2.0,"padding":3.0,"tooltip":"test_tooltip","visible":false,"width":100.0}""")); + Assert.That(JsonSerializer.Serialize(layout), Is.EqualTo("""{"border":true,"scrollbars":3,"type":"group","children":[{"type":"col","children":[{"text_halign":1,"value":"Test","type":"label","text_valign":1}]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10,"id":"test_group","margin":2,"padding":3,"tooltip":"test_tooltip","visible":false,"width":100}""")); + Assert.That(JsonSerializer.Serialize((NuiLayout)layout), Is.EqualTo("""{"border":true,"scrollbars":3,"type":"group","children":[{"type":"col","children":[{"text_halign":1,"value":"Test","type":"label","text_valign":1}]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10,"id":"test_group","margin":2,"padding":3,"tooltip":"test_tooltip","visible":false,"width":100}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiRowTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiRowTests.cs index 511c03bd7..db85da31b 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiRowTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Layout/NuiRowTests.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -28,8 +29,8 @@ public void SerializeNuiRowReturnsValidJson() ], }; - Assert.That(JsonUtility.ToJson(layout), Is.EqualTo("""{"type":"row","children":[{"text_halign":1,"value":"test","type":"label","text_valign":1},{"type":"row","children":[]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10.0,"id":"test_row","margin":2.0,"padding":3.0,"tooltip":"test_tooltip","visible":false,"width":100.0}""")); - Assert.That(JsonUtility.ToJson(layout), Is.EqualTo("""{"type":"row","children":[{"text_halign":1,"value":"test","type":"label","text_valign":1},{"type":"row","children":[]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10.0,"id":"test_row","margin":2.0,"padding":3.0,"tooltip":"test_tooltip","visible":false,"width":100.0}""")); + Assert.That(JsonSerializer.Serialize(layout), Is.EqualTo("""{"type":"row","children":[{"text_halign":1,"value":"test","type":"label","text_valign":1},{"type":"row","children":[]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10,"id":"test_row","margin":2,"padding":3,"tooltip":"test_tooltip","visible":false,"width":100}""")); + Assert.That(JsonSerializer.Serialize((NuiLayout)layout), Is.EqualTo("""{"type":"row","children":[{"text_halign":1,"value":"test","type":"label","text_valign":1},{"type":"row","children":[]}],"aspect":1.5,"enabled":{"bind":"enabled_bind"},"foreground_color":{"bind":"color_bind"},"height":10,"id":"test_row","margin":2,"padding":3,"tooltip":"test_tooltip","visible":false,"width":100}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonImageTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonImageTests.cs index a5362ebec..54970dc85 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonImageTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonImageTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -14,8 +15,8 @@ public void SerializeNuiButtonImageReturnsValidJson() Enabled = true, }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"btn_resref","type":"button_image","enabled":true}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"btn_resref","type":"button_image","enabled":true}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"label":"btn_resref","type":"button_image","enabled":true}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"label":"btn_resref","type":"button_image","enabled":true}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonSelectTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonSelectTests.cs index 233ab8771..4a05fd377 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonSelectTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonSelectTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiButtonSelectReturnsValidJson() { NuiButtonSelect element = new NuiButtonSelect("test_label", new NuiBind("selected")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"test_label","value":{"bind":"selected"},"type":"button_select"}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"test_label","value":{"bind":"selected"},"type":"button_select"}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"label":"test_label","value":{"bind":"selected"},"type":"button_select"}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"label":"test_label","value":{"bind":"selected"},"type":"button_select"}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonTests.cs index c7b761f2a..714bf2e08 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiButtonTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiButtonReturnsValidJson() { NuiButton element = new NuiButton("btn_label"); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"btn_label","type":"button"}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"btn_label","type":"button"}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"label":"btn_label","type":"button"}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"label":"btn_label","type":"button"}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiChartTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiChartTests.cs index 4aca5ad64..3a6662979 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiChartTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiChartTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -18,8 +19,8 @@ public void SerializeNuiChartReturnsValidJson() ], }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"value":[{"type":1,"color":{"a":255,"b":0,"g":0,"r":128},"data":[1.0,2.0,3.0],"legend":"slot1"},{"type":1,"color":{"a":255,"b":128,"g":0,"r":0},"data":[0.0,-1.0,-2.0],"legend":"slot2"}],"type":"chart"}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"value":[{"type":1,"color":{"a":255,"b":0,"g":0,"r":128},"data":[1.0,2.0,3.0],"legend":"slot1"},{"type":1,"color":{"a":255,"b":128,"g":0,"r":0},"data":[0.0,-1.0,-2.0],"legend":"slot2"}],"type":"chart"}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"value":[{"type":1,"color":{"a":255,"b":0,"g":0,"r":128},"data":[1,2,3],"legend":"slot1"},{"type":1,"color":{"a":255,"b":128,"g":0,"r":0},"data":[0,-1,-2],"legend":"slot2"}],"type":"chart"}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"value":[{"type":1,"color":{"a":255,"b":0,"g":0,"r":128},"data":[1,2,3],"legend":"slot1"},{"type":1,"color":{"a":255,"b":128,"g":0,"r":0},"data":[0,-1,-2],"legend":"slot2"}],"type":"chart"}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiCheckTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiCheckTests.cs index 2c2895826..7c02932a6 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiCheckTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiCheckTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiCheckReturnsValidJson() { NuiCheck element = new NuiCheck("chk_label", new NuiBind("is_checked")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"chk_label","value":{"bind":"is_checked"},"type":"check"}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"chk_label","value":{"bind":"is_checked"},"type":"check"}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"label":"chk_label","value":{"bind":"is_checked"},"type":"check"}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"label":"chk_label","value":{"bind":"is_checked"},"type":"check"}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiColorPickerTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiColorPickerTests.cs index 49b4f9f69..a9aeeb60c 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiColorPickerTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiColorPickerTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiColorPickerReturnsValidJson() { NuiColorPicker element = new NuiColorPicker(new NuiBind("selected_color")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"value":{"bind":"selected_color"},"type":"color_picker"}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"value":{"bind":"selected_color"},"type":"color_picker"}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"value":{"bind":"selected_color"},"type":"color_picker"}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"value":{"bind":"selected_color"},"type":"color_picker"}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiComboTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiComboTests.cs index 2271d2973..6261ffec7 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiComboTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiComboTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -20,8 +21,8 @@ public void SerializeNuiComboReturnsValidJson() Selected = 1, }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"elements":[["Entry 1",1],["Entry 2",2],["Entry 3",3]],"value":1,"type":"combo"}"""), JsonUtility.ToJson(element)); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"elements":[["Entry 1",1],["Entry 2",2],["Entry 3",3]],"value":1,"type":"combo"}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"elements":[["Entry 1",1],["Entry 2",2],["Entry 3",3]],"value":1,"type":"combo"}"""), JsonSerializer.Serialize(element)); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"elements":[["Entry 1",1],["Entry 2",2],["Entry 3",3]],"value":1,"type":"combo"}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiDrawListTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiDrawListTests.cs index 4bc349d74..559166e2f 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiDrawListTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiDrawListTests.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -14,8 +15,8 @@ public void SerializeNuiDrawListReturnsValidJson() DrawList = [new NuiDrawListText(ColorConstants.Red, new NuiRect(0, 0, 100, 100), "Draw list text")], }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"btn_label","type":"button","draw_list":[{"rect":{"h":100.0,"w":100.0,"x":0.0,"y":0.0},"text":"Draw list text","type":4,"color":{"a":255,"b":0,"g":0,"r":255},"enabled":true,"fill":null,"line_thickness":null,"order":1,"render":0}]}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"btn_label","type":"button","draw_list":[{"rect":{"h":100.0,"w":100.0,"x":0.0,"y":0.0},"text":"Draw list text","type":4,"color":{"a":255,"b":0,"g":0,"r":255},"enabled":true,"fill":null,"line_thickness":null,"order":1,"render":0}]}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"label":"btn_label","type":"button","draw_list":[{"rect":{"h":100,"w":100,"x":0,"y":0},"text":"Draw list text","type":4,"color":{"a":255,"b":0,"g":0,"r":255},"enabled":true,"fill":null,"line_thickness":null,"order":1,"render":0}]}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"label":"btn_label","type":"button","draw_list":[{"rect":{"h":100,"w":100,"x":0,"y":0},"text":"Draw list text","type":4,"color":{"a":255,"b":0,"g":0,"r":255},"enabled":true,"fill":null,"line_thickness":null,"order":1,"render":0}]}""")); } [Test(Description = "Serializing a NuiDrawListArc creates a valid JSON structure.")] @@ -26,8 +27,8 @@ public void SerializeNuiDrawListArcReturnsValidJson() Enabled = false, }; - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"amax":170.0,"amin":90.0,"c":{"x":1.0,"y":2.0},"radius":2.0,"type":3,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":1.0,"order":1,"render":0}""")); - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"amax":170.0,"amin":90.0,"c":{"x":1.0,"y":2.0},"radius":2.0,"type":3,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":1.0,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize(item), Is.EqualTo("""{"amax":170,"amin":90,"c":{"x":1,"y":2},"radius":2,"type":3,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":1,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize((NuiDrawListItem)item), Is.EqualTo("""{"amax":170,"amin":90,"c":{"x":1,"y":2},"radius":2,"type":3,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":1,"order":1,"render":0}""")); } [Test(Description = "Serializing a NuiDrawListCircle creates a valid JSON structure.")] @@ -38,8 +39,8 @@ public void SerializeNuiDrawListCircleReturnsValidJson() Enabled = false, }; - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"rect":{"h":4.0,"w":3.0,"x":1.0,"y":2.0},"type":2,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":1.0,"order":1,"render":0}""")); - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"rect":{"h":4.0,"w":3.0,"x":1.0,"y":2.0},"type":2,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":1.0,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize(item), Is.EqualTo("""{"rect":{"h":4,"w":3,"x":1,"y":2},"type":2,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":1,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize((NuiDrawListItem)item), Is.EqualTo("""{"rect":{"h":4,"w":3,"x":1,"y":2},"type":2,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":1,"order":1,"render":0}""")); } [Test(Description = "Serializing a NuiDrawListCurve creates a valid JSON structure.")] @@ -50,8 +51,8 @@ public void SerializeNuiDrawListCurveReturnsValidJson() Enabled = false, }; - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"ctrl0":{"x":9.5,"y":3.0},"ctrl1":{"x":22.0,"y":11.3},"a":{"x":10.0,"y":5.0},"b":{"x":6.0,"y":2.0},"type":1,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":false,"line_thickness":1.0,"order":1,"render":0}""")); - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"ctrl0":{"x":9.5,"y":3.0},"ctrl1":{"x":22.0,"y":11.3},"a":{"x":10.0,"y":5.0},"b":{"x":6.0,"y":2.0},"type":1,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":false,"line_thickness":1.0,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize(item), Is.EqualTo("""{"ctrl0":{"x":9.5,"y":3},"ctrl1":{"x":22,"y":11.3},"a":{"x":10,"y":5},"b":{"x":6,"y":2},"type":1,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":false,"line_thickness":1,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize((NuiDrawListItem)item), Is.EqualTo("""{"ctrl0":{"x":9.5,"y":3},"ctrl1":{"x":22,"y":11.3},"a":{"x":10,"y":5},"b":{"x":6,"y":2},"type":1,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":false,"line_thickness":1,"order":1,"render":0}""")); } [Test(Description = "Serializing a NuiDrawListImage creates a valid JSON structure.")] @@ -62,8 +63,8 @@ public void SerializeNuiDrawListImageReturnsValidJson() Enabled = false, }; - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"image_aspect":3,"image_halign":1,"rect":{"h":4.0,"w":3.0,"x":1.0,"y":2.0},"image":"test_img","type":5,"image_valign":1,"color":null,"enabled":false,"fill":null,"line_thickness":null,"order":1,"render":0}""")); - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"image_aspect":3,"image_halign":1,"rect":{"h":4.0,"w":3.0,"x":1.0,"y":2.0},"image":"test_img","type":5,"image_valign":1,"color":null,"enabled":false,"fill":null,"line_thickness":null,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize(item), Is.EqualTo("""{"image_aspect":3,"image_halign":1,"rect":{"h":4,"w":3,"x":1,"y":2},"image":"test_img","type":5,"image_valign":1,"color":null,"enabled":false,"fill":null,"line_thickness":null,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize((NuiDrawListItem)item), Is.EqualTo("""{"image_aspect":3,"image_halign":1,"rect":{"h":4,"w":3,"x":1,"y":2},"image":"test_img","type":5,"image_valign":1,"color":null,"enabled":false,"fill":null,"line_thickness":null,"order":1,"render":0}""")); } [Test(Description = "Serializing a NuiDrawListPolyLine creates a valid JSON structure.")] @@ -74,8 +75,8 @@ public void SerializeNuiDrawListPolyLineReturnsValidJson() Enabled = false, }; - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"points":[2.0,4.0,6.0,11.0],"type":0,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":2.0,"order":1,"render":0}""")); - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"points":[2.0,4.0,6.0,11.0],"type":0,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":2.0,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize(item), Is.EqualTo("""{"points":[2,4,6,11],"type":0,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":2,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize((NuiDrawListItem)item), Is.EqualTo("""{"points":[2,4,6,11],"type":0,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":true,"line_thickness":2,"order":1,"render":0}""")); } [Test(Description = "Serializing a NuiDrawListText creates a valid JSON structure.")] @@ -86,8 +87,8 @@ public void SerializeNuiDrawListTextReturnsValidJson() Enabled = false, }; - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"rect":{"h":8.0,"w":7.0,"x":5.0,"y":6.0},"text":"Test string","type":4,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":null,"line_thickness":null,"order":1,"render":0}""")); - Assert.That(JsonUtility.ToJson(item), Is.EqualTo("""{"rect":{"h":8.0,"w":7.0,"x":5.0,"y":6.0},"text":"Test string","type":4,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":null,"line_thickness":null,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize(item), Is.EqualTo("""{"rect":{"h":8,"w":7,"x":5,"y":6},"text":"Test string","type":4,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":null,"line_thickness":null,"order":1,"render":0}""")); + Assert.That(JsonSerializer.Serialize((NuiDrawListItem)item), Is.EqualTo("""{"rect":{"h":8,"w":7,"x":5,"y":6},"text":"Test string","type":4,"color":{"a":255,"b":170,"g":170,"r":255},"enabled":false,"fill":null,"line_thickness":null,"order":1,"render":0}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiImageTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiImageTests.cs index da6ceaaf0..aee5f8c63 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiImageTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiImageTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -18,8 +19,8 @@ public void SerializeNuiImageReturnsValidJson() Margin = 0.0f, }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"image_halign":2,"image_aspect":4,"image_region":null,"value":"gui_chr_arrowbtn","type":"image","image_valign":0,"height":16.0,"margin":0.0,"width":16.0}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"image_halign":2,"image_aspect":4,"image_region":null,"value":"gui_chr_arrowbtn","type":"image","image_valign":0,"height":16.0,"margin":0.0,"width":16.0}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"image_halign":2,"image_aspect":4,"image_region":null,"value":"gui_chr_arrowbtn","type":"image","image_valign":0,"height":16,"margin":0,"width":16}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"image_halign":2,"image_aspect":4,"image_region":null,"value":"gui_chr_arrowbtn","type":"image","image_valign":0,"height":16,"margin":0,"width":16}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiLabelTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiLabelTests.cs index 0842a2773..a1e3144bf 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiLabelTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiLabelTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -14,8 +15,8 @@ public void SerializeNuiLabelReturnsValidJson() VerticalAlign = NuiVAlign.Middle, }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"text_halign":0,"value":"Label","type":"label","text_valign":0}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"text_halign":0,"value":"Label","type":"label","text_valign":0}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"text_halign":0,"value":"Label","type":"label","text_valign":0}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"text_halign":0,"value":"Label","type":"label","text_valign":0}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiOptionsTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiOptionsTests.cs index ccf837822..c47297915 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiOptionsTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiOptionsTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -15,8 +16,8 @@ public void SerializeNuiOptionsReturnsValidJson() Selection = new NuiBind("selection"), }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"direction":1,"elements":["option1","option2"],"value":{"bind":"selection"},"type":"options"}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"direction":1,"elements":["option1","option2"],"value":{"bind":"selection"},"type":"options"}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"direction":1,"elements":["option1","option2"],"value":{"bind":"selection"},"type":"options"}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"direction":1,"elements":["option1","option2"],"value":{"bind":"selection"},"type":"options"}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiProgressTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiProgressTests.cs index 7fe3cec68..001844265 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiProgressTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiProgressTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiProgressReturnsValidJson() { NuiProgress element = new NuiProgress(new NuiBind("progress")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"type":"progress","value":{"bind":"progress"}}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"type":"progress","value":{"bind":"progress"}}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"type":"progress","value":{"bind":"progress"}}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"type":"progress","value":{"bind":"progress"}}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSliderFloatTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSliderFloatTests.cs index bf3bf12e7..46ea0b901 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSliderFloatTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSliderFloatTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiSliderFloatReturnsValidJson() { NuiSliderFloat element = new NuiSliderFloat(new NuiBind("value"), 0f, 100f); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"max":100.0,"min":0.0,"step":0.01,"type":"sliderf","value":{"bind":"value"}}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"max":100.0,"min":0.0,"step":0.01,"type":"sliderf","value":{"bind":"value"}}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"max":100,"min":0,"step":0.01,"type":"sliderf","value":{"bind":"value"}}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"max":100,"min":0,"step":0.01,"type":"sliderf","value":{"bind":"value"}}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSliderTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSliderTests.cs index c6e94cc76..281256aa2 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSliderTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSliderTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -13,8 +14,8 @@ public void SerializeNuiSliderReturnsValidJson() Step = 2, }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"max":10,"min":0,"step":2,"type":"slider","value":{"bind":"value"}}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"max":10,"min":0,"step":2,"type":"slider","value":{"bind":"value"}}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"max":10,"min":0,"step":2,"type":"slider","value":{"bind":"value"}}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"max":10,"min":0,"step":2,"type":"slider","value":{"bind":"value"}}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSpacerTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSpacerTests.cs index 4d1c3f2f9..6c274bb9d 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSpacerTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiSpacerTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiSpacerReturnsValidJson() { NuiSpacer element = new NuiSpacer(); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"type":"spacer"}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"type":"spacer"}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"type":"spacer"}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"type":"spacer"}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTextEditTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTextEditTests.cs index 5b6284985..89177033d 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTextEditTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTextEditTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiTextEditReturnsValidJson() { NuiTextEdit element = new NuiTextEdit("Label", new NuiBind("input"), 255, true); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"Label","max":255,"multiline":true,"type":"textedit","value":{"bind":"input"},"wordwrap":true}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"label":"Label","max":255,"multiline":true,"type":"textedit","value":{"bind":"input"},"wordwrap":true}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"label":"Label","max":255,"multiline":true,"type":"textedit","value":{"bind":"input"},"wordwrap":true}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"label":"Label","max":255,"multiline":true,"type":"textedit","value":{"bind":"input"},"wordwrap":true}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTextTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTextTests.cs index 943c3ad37..0a5f4de36 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTextTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTextTests.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Anvil.API; using NUnit.Framework; @@ -16,8 +17,8 @@ public void SerializeNuiTextReturnsValidJson() Scrollbars = NuiScrollbars.Y, }; - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"value":"Some Text","border":false,"scrollbars":2,"type":"text","enabled":false}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"value":"Some Text","border":false,"scrollbars":2,"type":"text","enabled":false}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"value":"Some Text","border":false,"scrollbars":2,"type":"text","enabled":false}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"value":"Some Text","border":false,"scrollbars":2,"type":"text","enabled":false}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTogglesTests.cs b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTogglesTests.cs index d6240852f..0bf230cfa 100644 --- a/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTogglesTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Nui/Widgets/NuiTogglesTests.cs @@ -1,4 +1,5 @@ -using Anvil.API; +using System.Text.Json; +using Anvil.API; using NUnit.Framework; namespace Anvil.Tests.API @@ -10,8 +11,8 @@ public void SerializeNuiTogglesReturnsValidJson() { NuiToggles element = new NuiToggles(NuiDirection.Vertical, ["Tab 1", "Tab 2", "Tab 3"]); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"type":"tabbar","direction":1,"elements":["Tab 1","Tab 2","Tab 3"]}""")); - Assert.That(JsonUtility.ToJson(element), Is.EqualTo("""{"type":"tabbar","direction":1,"elements":["Tab 1","Tab 2","Tab 3"]}""")); + Assert.That(JsonSerializer.Serialize(element), Is.EqualTo("""{"type":"tabbar","direction":1,"elements":["Tab 1","Tab 2","Tab 3"]}""")); + Assert.That(JsonSerializer.Serialize((NuiElement)element), Is.EqualTo("""{"type":"tabbar","direction":1,"elements":["Tab 1","Tab 2","Tab 3"]}""")); } } } diff --git a/NWN.Anvil.Tests/src/main/API/Utils/JsonUtilityTests.cs b/NWN.Anvil.Tests/src/main/API/Utils/JsonUtilityTests.cs index b506978ff..954d95bde 100644 --- a/NWN.Anvil.Tests/src/main/API/Utils/JsonUtilityTests.cs +++ b/NWN.Anvil.Tests/src/main/API/Utils/JsonUtilityTests.cs @@ -1,4 +1,4 @@ -using Anvil.API; +using System.Text.Json; using NUnit.Framework; // ReSharper disable UnusedAutoPropertyAccessor.Local @@ -10,9 +10,9 @@ public sealed class JsonUtilityTests [Test(Description = "Serializing a value creates valid json.")] [TestCase(null, "null")] [TestCase(1, "1")] - [TestCase(1f, "1.0")] + [TestCase(1f, "1")] [TestCase(1.532f, "1.532")] - [TestCase(1.0d, "1.0")] + [TestCase(1.0d, "1")] [TestCase(1.689d, "1.689")] [TestCase(false, "false")] [TestCase(true, "true")] @@ -24,7 +24,7 @@ public sealed class JsonUtilityTests """)] public void SerializeValueCreatesValidJson(object value, string expected) { - Assert.That(JsonUtility.ToJson(value), Is.EqualTo(expected)); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo(expected)); } [Test(Description = "Serializing a struct creates valid json.")] @@ -38,7 +38,7 @@ public void SerializeStructCreatesValidJson() TestS = "test", }; - Assert.That(JsonUtility.ToJson(value), Is.EqualTo("""{"TestI":5,"TestS":"test","TestF":10.0,"TestB":true}""")); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo("""{"TestI":5,"TestS":"test","TestF":10,"TestB":true}""")); } [Test(Description = "Serializing a class creates valid json.")] @@ -52,7 +52,7 @@ public void SerializeClassCreatesValidJson() TestS = "test", }; - Assert.That(JsonUtility.ToJson(value), Is.EqualTo("""{"TestI":5,"TestS":"test","TestF":10.0,"TestB":true}""")); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo("""{"TestI":5,"TestS":"test","TestF":10,"TestB":true}""")); } [Test(Description = "Serializing a record creates valid json.")] @@ -66,7 +66,7 @@ public void SerializeRecordCreatesValidJson() TestS = "test", }; - Assert.That(JsonUtility.ToJson(value), Is.EqualTo("""{"TestI":5,"TestS":"test","TestF":10.0,"TestB":true}""")); + Assert.That(JsonSerializer.Serialize(value), Is.EqualTo("""{"TestI":5,"TestS":"test","TestF":10,"TestB":true}""")); } private struct TestStruct diff --git a/NWN.Anvil/NWN.Anvil.csproj b/NWN.Anvil/NWN.Anvil.csproj index ccb5ccf06..52a9c78e6 100644 --- a/NWN.Anvil/NWN.Anvil.csproj +++ b/NWN.Anvil/NWN.Anvil.csproj @@ -64,7 +64,6 @@ - diff --git a/NWN.Anvil/src/main/API/Color.cs b/NWN.Anvil/src/main/API/Color.cs index dd482041c..a95ed6f24 100644 --- a/NWN.Anvil/src/main/API/Color.cs +++ b/NWN.Anvil/src/main/API/Color.cs @@ -1,5 +1,5 @@ using System; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using NWNX.NET.Native; namespace Anvil.API @@ -12,25 +12,29 @@ namespace Anvil.API /// /// Gets the alpha value of this color as a byte (0-255). /// - [JsonProperty("a")] + [JsonPropertyName("a")] + [JsonInclude] public readonly byte Alpha; /// /// Gets the blue value of this color as a byte (0-255). /// - [JsonProperty("b")] + [JsonPropertyName("b")] + [JsonInclude] public readonly byte Blue; /// /// Gets the green value of this color as a byte (0-255). /// - [JsonProperty("g")] + [JsonPropertyName("g")] + [JsonInclude] public readonly byte Green; /// /// Gets the red value of this color as a byte (0-255). /// - [JsonProperty("r")] + [JsonPropertyName("r")] + [JsonInclude] public readonly byte Red; /// diff --git a/NWN.Anvil/src/main/API/EngineStructures/Json.cs b/NWN.Anvil/src/main/API/EngineStructures/Json.cs index d2c7e720c..cfc7139b9 100644 --- a/NWN.Anvil/src/main/API/EngineStructures/Json.cs +++ b/NWN.Anvil/src/main/API/EngineStructures/Json.cs @@ -1,4 +1,5 @@ using System; +using System.Text.Json; using NWN.Core; namespace Anvil.API @@ -7,7 +8,7 @@ namespace Anvil.API /// Represents a json engine structure. /// /// This class is specifically for compatibility with the base game.
- /// It is recommended to use and for all json-related problems in C#.
+ /// It is recommended to use for all json-related problems in C#. public sealed class Json : EngineStructure { internal Json(IntPtr handle, bool memoryOwn) : base(handle, memoryOwn) {} @@ -61,5 +62,27 @@ public string Dump() { return NWScript.JsonToObject(this, location, owner, loadObjectState.ToInt()).ToNwObject(); } + + /// + /// Deserializes a Json game engine structure. + /// + /// The type to deserialize to. + /// The deserialized object. + public T? Deserialize() + { + return JsonSerializer.Deserialize(Dump()); + } + + /// + /// Serializes a value as a JSON engine structure. + /// + /// The value to serialize. + /// The type of the value to serialize. + /// A JSON engine structure representing the value. + public static Json Serialize(T value) + { + string serialized = JsonSerializer.Serialize(value); + return Parse(serialized); + } } } diff --git a/NWN.Anvil/src/main/API/EngineStructures/TileData.cs b/NWN.Anvil/src/main/API/EngineStructures/TileData.cs index d4cfe7d9b..5d9bfecd5 100644 --- a/NWN.Anvil/src/main/API/EngineStructures/TileData.cs +++ b/NWN.Anvil/src/main/API/EngineStructures/TileData.cs @@ -1,5 +1,5 @@ using System; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -18,43 +18,43 @@ public sealed class TileData /// 3 4 5
/// 0 1 2
/// - [JsonProperty("index")] + [JsonPropertyName("index")] public int Index { get; set; } /// /// The new tile ID to assign. /// - [JsonProperty("tileid")] + [JsonPropertyName("tileid")] public int TileId { get; set; } /// /// The rotation of the new tile. /// - [JsonProperty("orientation")] + [JsonPropertyName("orientation")] public TileRotation Orientation { get; set; } /// /// The height of the new tile. /// - [JsonProperty("height")] + [JsonPropertyName("height")] public int Height { get; set; } /// /// The animation state of the new tile (1/0). /// - [JsonProperty("animloop1")] + [JsonPropertyName("animloop1")] public int AnimationLoop1 { get; set; } /// /// The animation state of the new tile (1/0). /// - [JsonProperty("animloop2")] + [JsonPropertyName("animloop2")] public int AnimationLoop2 { get; set; } /// /// The animation state of the new tile (1/0). /// - [JsonProperty("animloop3")] + [JsonPropertyName("animloop3")] public int AnimationLoop3 { get; set; } } } diff --git a/NWN.Anvil/src/main/API/Events/Game/ModuleEvents/ModuleEvents.OnNuiEvent.cs b/NWN.Anvil/src/main/API/Events/Game/ModuleEvents/ModuleEvents.OnNuiEvent.cs index 062704a0d..6807993ec 100644 --- a/NWN.Anvil/src/main/API/Events/Game/ModuleEvents/ModuleEvents.OnNuiEvent.cs +++ b/NWN.Anvil/src/main/API/Events/Game/ModuleEvents/ModuleEvents.OnNuiEvent.cs @@ -1,4 +1,5 @@ using System; +using System.Text.Json; using Anvil.API.Events; using NWN.Core; @@ -74,7 +75,7 @@ public OnNuiEvent() /// The payload data, or null if the event has no payload. public T? GetEventPayload() { - return JsonUtility.FromJson(eventPayload); + return JsonSerializer.Deserialize(eventPayload); } } } diff --git a/NWN.Anvil/src/main/API/Nui/Bindings/NuiBind.cs b/NWN.Anvil/src/main/API/Nui/Bindings/NuiBind.cs index e7ca11a8a..23fa0657b 100644 --- a/NWN.Anvil/src/main/API/Nui/Bindings/NuiBind.cs +++ b/NWN.Anvil/src/main/API/Nui/Bindings/NuiBind.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using NWN.Core; namespace Anvil.API @@ -11,7 +11,7 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiBind(string key) : NuiProperty { - [JsonProperty("bind")] + [JsonPropertyName("bind")] public string Key { get; init; } = key; /// @@ -22,7 +22,7 @@ public sealed class NuiBind(string key) : NuiProperty /// The current value of the binding. public T? GetBindValue(NwPlayer player, int uiToken) { - return JsonUtility.FromJson(NWScript.NuiGetBind(player.ControlledCreature, uiToken, Key)); + return ((Json)NWScript.NuiGetBind(player.ControlledCreature, uiToken, Key)).Deserialize(); } /// @@ -33,7 +33,7 @@ public sealed class NuiBind(string key) : NuiProperty /// The current values of the binding. public List? GetBindValues(NwPlayer player, int uiToken) { - return JsonUtility.FromJson>(NWScript.NuiGetBind(player.ControlledCreature, uiToken, Key)); + return ((Json)NWScript.NuiGetBind(player.ControlledCreature, uiToken, Key)).Deserialize>(); } /// @@ -44,7 +44,7 @@ public sealed class NuiBind(string key) : NuiProperty /// The new value to assign. public void SetBindValue(NwPlayer player, int uiToken, T value) { - NWScript.NuiSetBind(player.ControlledCreature, uiToken, Key, JsonUtility.ToJsonStructure(value)); + NWScript.NuiSetBind(player.ControlledCreature, uiToken, Key, Json.Serialize(value)); } /// @@ -55,7 +55,7 @@ public void SetBindValue(NwPlayer player, int uiToken, T value) /// The new value to assign. public void SetBindValues(NwPlayer player, int uiToken, IEnumerable values) { - NWScript.NuiSetBind(player.ControlledCreature, uiToken, Key, JsonUtility.ToJsonStructure(values)); + NWScript.NuiSetBind(player.ControlledCreature, uiToken, Key, Json.Serialize(values)); } /// diff --git a/NWN.Anvil/src/main/API/Nui/Bindings/NuiBindStrRef.cs b/NWN.Anvil/src/main/API/Nui/Bindings/NuiBindStrRef.cs index e142df617..099d17d81 100644 --- a/NWN.Anvil/src/main/API/Nui/Bindings/NuiBindStrRef.cs +++ b/NWN.Anvil/src/main/API/Nui/Bindings/NuiBindStrRef.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using NWN.Core; namespace Anvil.API @@ -7,7 +7,7 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiBindStrRef(string key) : NuiProperty { - [JsonProperty("bind")] + [JsonPropertyName("bind")] public string Key { get; init; } = key; /// @@ -18,7 +18,7 @@ public sealed class NuiBindStrRef(string key) : NuiProperty /// The current value of the binding. public StrRef? GetBindValue(NwPlayer player, int uiToken) { - return JsonUtility.FromJson(NWScript.NuiGetBind(player.ControlledCreature, uiToken, Key)); + return ((Json)NWScript.NuiGetBind(player.ControlledCreature, uiToken, Key)).Deserialize(); } /// @@ -29,7 +29,7 @@ public sealed class NuiBindStrRef(string key) : NuiProperty /// The current values of the binding. public List? GetBindValues(NwPlayer player, int uiToken) { - return JsonUtility.FromJson>(NWScript.NuiGetBind(player.ControlledCreature, uiToken, Key)); + return ((Json)NWScript.NuiGetBind(player.ControlledCreature, uiToken, Key)).Deserialize>(); } /// @@ -40,7 +40,7 @@ public sealed class NuiBindStrRef(string key) : NuiProperty /// The new value to assign. public void SetBindValue(NwPlayer player, int uiToken, StrRef? value) { - NWScript.NuiSetBind(player.ControlledCreature, uiToken, Key, JsonUtility.ToJsonStructure(value)); + NWScript.NuiSetBind(player.ControlledCreature, uiToken, Key, Json.Serialize(value)); } /// @@ -51,7 +51,7 @@ public void SetBindValue(NwPlayer player, int uiToken, StrRef? value) /// The new value to assign. public void SetBindValues(NwPlayer player, int uiToken, IEnumerable values) { - NWScript.NuiSetBind(player.ControlledCreature, uiToken, Key, JsonUtility.ToJsonStructure(values)); + NWScript.NuiSetBind(player.ControlledCreature, uiToken, Key, Json.Serialize(values)); } /// diff --git a/NWN.Anvil/src/main/API/Nui/Bindings/NuiProperty.cs b/NWN.Anvil/src/main/API/Nui/Bindings/NuiProperty.cs index f7c043833..cdb8915e7 100644 --- a/NWN.Anvil/src/main/API/Nui/Bindings/NuiProperty.cs +++ b/NWN.Anvil/src/main/API/Nui/Bindings/NuiProperty.cs @@ -1,9 +1,12 @@ +using System.Text.Json.Serialization; + namespace Anvil.API { /// /// A NUI property that can be configured as a static readonly value, or a property that can be updated at runtime. /// /// The underlying type of the property. + [JsonConverter(typeof(NuiPropertyConverter))] public abstract class NuiProperty { /// diff --git a/NWN.Anvil/src/main/API/Nui/Bindings/NuiPropertyConverter.cs b/NWN.Anvil/src/main/API/Nui/Bindings/NuiPropertyConverter.cs new file mode 100644 index 000000000..dd22d85f6 --- /dev/null +++ b/NWN.Anvil/src/main/API/Nui/Bindings/NuiPropertyConverter.cs @@ -0,0 +1,64 @@ +using System; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Anvil.API +{ + internal sealed class NuiPropertyConverter : JsonConverterFactory + { + public override bool CanConvert(Type objectType) + { + if (!objectType.IsGenericType) + { + return false; + } + + return objectType.GetGenericTypeDefinition() == typeof(NuiProperty<>); + } + + public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + Type valueType = typeToConvert.GetGenericArguments()[0]; + Type converterType = typeof(NuiPropertyConverterInner<>).MakeGenericType(valueType); + + return (JsonConverter?)Activator.CreateInstance(converterType, + BindingFlags.Instance | BindingFlags.Public, + null, + [options], + null); + } + + private sealed class NuiPropertyConverterInner(JsonSerializerOptions options) : JsonConverter> + { + private readonly JsonConverter bindStrRefConverter = (JsonConverter)options.GetConverter(typeof(NuiBindStrRef)); + private readonly JsonConverter valueStrRefConverter = (JsonConverter)options.GetConverter(typeof(NuiValueStrRef)); + private readonly JsonConverter> bindConverter = (JsonConverter>)options.GetConverter(typeof(NuiBind)); + private readonly JsonConverter> valueConverter = (JsonConverter>)options.GetConverter(typeof(NuiValue)); + + public override NuiProperty Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, NuiProperty property, JsonSerializerOptions options) + { + switch (property) + { + case NuiBind bind: + bindConverter.Write(writer, bind, options); + break; + case NuiValue value: + valueConverter.Write(writer, value, options); + break; + case NuiBindStrRef bindStrRef: + bindStrRefConverter.Write(writer, bindStrRef, options); + break; + case NuiValueStrRef valueStrRef: + valueStrRefConverter.Write(writer, valueStrRef, options); + break; + } + } + } + } +} diff --git a/NWN.Anvil/src/main/API/Nui/Bindings/NuiValue.cs b/NWN.Anvil/src/main/API/Nui/Bindings/NuiValue.cs index 676cf983d..867cf4466 100644 --- a/NWN.Anvil/src/main/API/Nui/Bindings/NuiValue.cs +++ b/NWN.Anvil/src/main/API/Nui/Bindings/NuiValue.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -9,7 +9,7 @@ namespace Anvil.API [JsonConverter(typeof(NuiValueConverter))] public sealed class NuiValue : NuiProperty { - public NuiValue(T value) + public NuiValue(T? value) { Value = value; } diff --git a/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueConverter.cs b/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueConverter.cs index af0c67011..21e2b1a6a 100644 --- a/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueConverter.cs +++ b/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueConverter.cs @@ -1,54 +1,62 @@ using System; using System.Reflection; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Anvil.API { - public sealed class NuiValueConverter : JsonConverter + internal sealed class NuiValueConverter : JsonConverterFactory { public override bool CanConvert(Type objectType) { - return objectType.GetGenericTypeDefinition() == typeof(NuiValue<>); - } - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - object? retVal = Activator.CreateInstance(objectType, true); - if (retVal == null) - { - return null; - } - - PropertyInfo? propertyInfo = objectType.GetProperty(nameof(NuiValue.Value)); - if (propertyInfo == null) + if (!objectType.IsGenericType) { - return null; + return false; } - Type valueType = objectType.GetGenericArguments()[0]; - propertyInfo.SetValue(retVal, serializer.Deserialize(reader, valueType)); + return objectType.GetGenericTypeDefinition() == typeof(NuiValue<>); + } - return retVal; + public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + Type valueType = typeToConvert.GetGenericArguments()[0]; + Type converterType = typeof(NuiValueConverterInner<>).MakeGenericType(valueType); + + return (JsonConverter?)Activator.CreateInstance(converterType, + BindingFlags.Instance | BindingFlags.Public, + null, + [options], + null); } - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) + private sealed class NuiValueConverterInner : JsonConverter> { - if (value == null) + private readonly JsonConverter valueConverter; + private readonly Type valueType; + + public NuiValueConverterInner(JsonSerializerOptions options) { - writer.WriteNull(); - return; + valueType = typeof(TValue); + valueConverter = (JsonConverter)options.GetConverter(valueType); } - Type type = value.GetType(); - PropertyInfo? propertyInfo = type.GetProperty(nameof(NuiValue.Value)); - - if (propertyInfo == null) + public override NuiValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - writer.WriteNull(); - return; + TValue? value = valueConverter.Read(ref reader, valueType, options); + return new NuiValue(value); } - serializer.Serialize(writer, propertyInfo.GetValue(value)); + public override void Write(Utf8JsonWriter writer, NuiValue value, JsonSerializerOptions options) + { + if (value.Value is not null) + { + valueConverter.Write(writer, value.Value, options); + } + else + { + writer.WriteNullValue(); + } + } } } } diff --git a/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueStrRef.cs b/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueStrRef.cs index b1fe98a6b..613f7dcda 100644 --- a/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueStrRef.cs +++ b/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueStrRef.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { diff --git a/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueStrRefConverter.cs b/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueStrRefConverter.cs index 77310b399..e997e712f 100644 --- a/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueStrRefConverter.cs +++ b/NWN.Anvil/src/main/API/Nui/Bindings/NuiValueStrRefConverter.cs @@ -1,25 +1,30 @@ using System; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Anvil.API { - public sealed class NuiValueStrRefConverter : JsonConverter + internal sealed class NuiValueStrRefConverter : JsonConverter { - public override NuiValueStrRef? ReadJson(JsonReader reader, Type objectType, NuiValueStrRef? existingValue, bool hasExistingValue, JsonSerializer serializer) + public override NuiValueStrRef? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - StrRef? value = serializer.Deserialize(reader); + JsonConverter valueConverter = (JsonConverter)options.GetConverter(typeof(StrRef)); + + StrRef? value = valueConverter.Read(ref reader, typeof(StrRef?), options); return value != null ? new NuiValueStrRef(value) : null; } - public override void WriteJson(JsonWriter writer, NuiValueStrRef? value, JsonSerializer serializer) + public override void Write(Utf8JsonWriter writer, NuiValueStrRef? value, JsonSerializerOptions options) { + JsonConverter valueConverter = (JsonConverter)options.GetConverter(typeof(StrRef)); + if (value?.Value != null) { - serializer.Serialize(writer, value.Value); + valueConverter.Write(writer, value.Value.Value, options); } else { - writer.WriteNull(); + writer.WriteNullValue(); } } } diff --git a/NWN.Anvil/src/main/API/Nui/Layout/NuiColumn.cs b/NWN.Anvil/src/main/API/Nui/Layout/NuiColumn.cs index 0682cdab6..86fa66980 100644 --- a/NWN.Anvil/src/main/API/Nui/Layout/NuiColumn.cs +++ b/NWN.Anvil/src/main/API/Nui/Layout/NuiColumn.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -11,8 +11,10 @@ public sealed class NuiColumn : NuiLayout [JsonIgnore] public List Children { get; set; } = []; + [JsonPropertyName("type")] public override string Type => "col"; + [JsonPropertyName("children")] protected override IEnumerable SerializedChildren => Children; } } diff --git a/NWN.Anvil/src/main/API/Nui/Layout/NuiGroup.cs b/NWN.Anvil/src/main/API/Nui/Layout/NuiGroup.cs index 58001e3ef..e7c0ca432 100644 --- a/NWN.Anvil/src/main/API/Nui/Layout/NuiGroup.cs +++ b/NWN.Anvil/src/main/API/Nui/Layout/NuiGroup.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using NWN.Core; namespace Anvil.API @@ -11,7 +11,7 @@ namespace Anvil.API /// public sealed class NuiGroup : NuiLayout { - [JsonProperty("border")] + [JsonPropertyName("border")] public bool Border { get; set; } = true; [JsonIgnore] @@ -24,11 +24,13 @@ public NuiLayout? Layout [JsonIgnore] public NuiElement? Element { get; set; } - [JsonProperty("scrollbars")] + [JsonPropertyName("scrollbars")] public NuiScrollbars Scrollbars { get; set; } = NuiScrollbars.Auto; + [JsonPropertyName("type")] public override string Type => "group"; + [JsonPropertyName("children")] protected override IEnumerable SerializedChildren => Element.SafeYield(); /// @@ -45,7 +47,7 @@ public void SetLayout(NwPlayer player, int token, NuiLayout newLayout) throw new InvalidOperationException("Layout cannot be updated as the NuiGroup does not have an ID."); } - NWScript.NuiSetGroupLayout(player.ControlledCreature, token, Id, JsonUtility.ToJsonStructure(newLayout)); + NWScript.NuiSetGroupLayout(player.ControlledCreature, token, Id, Json.Serialize(newLayout)); } } } diff --git a/NWN.Anvil/src/main/API/Nui/Layout/NuiLayout.cs b/NWN.Anvil/src/main/API/Nui/Layout/NuiLayout.cs index 6f51754f7..d1784e1fd 100644 --- a/NWN.Anvil/src/main/API/Nui/Layout/NuiLayout.cs +++ b/NWN.Anvil/src/main/API/Nui/Layout/NuiLayout.cs @@ -1,11 +1,16 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { + [JsonPolymorphic] + [JsonDerivedType(typeof(NuiColumn))] + [JsonDerivedType(typeof(NuiGroup))] + [JsonDerivedType(typeof(NuiRow))] public abstract class NuiLayout : NuiElement { - [JsonProperty("children")] + [JsonPropertyName("children")] + [JsonInclude] protected abstract IEnumerable SerializedChildren { get; } } } diff --git a/NWN.Anvil/src/main/API/Nui/Layout/NuiRow.cs b/NWN.Anvil/src/main/API/Nui/Layout/NuiRow.cs index d13ddd5e2..9a4d2f4f9 100644 --- a/NWN.Anvil/src/main/API/Nui/Layout/NuiRow.cs +++ b/NWN.Anvil/src/main/API/Nui/Layout/NuiRow.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -11,8 +11,10 @@ public sealed class NuiRow : NuiLayout [JsonIgnore] public List Children { get; set; } = []; + [JsonPropertyName("type")] public override string Type => "row"; + [JsonPropertyName("children")] protected override IEnumerable SerializedChildren => Children; } } diff --git a/NWN.Anvil/src/main/API/Nui/NuiElement.cs b/NWN.Anvil/src/main/API/Nui/NuiElement.cs index 440c31469..9be9a1e37 100644 --- a/NWN.Anvil/src/main/API/Nui/NuiElement.cs +++ b/NWN.Anvil/src/main/API/Nui/NuiElement.cs @@ -1,23 +1,47 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { /// /// A dynamic NUI element with style support. /// + [JsonPolymorphic] + [JsonDerivedType(typeof(NuiColumn))] + [JsonDerivedType(typeof(NuiGroup))] + [JsonDerivedType(typeof(NuiRow))] + [JsonDerivedType(typeof(NuiList))] + [JsonDerivedType(typeof(NuiButton))] + [JsonDerivedType(typeof(NuiButtonImage))] + [JsonDerivedType(typeof(NuiButtonSelect))] + [JsonDerivedType(typeof(NuiChart))] + [JsonDerivedType(typeof(NuiCheck))] + [JsonDerivedType(typeof(NuiColorPicker))] + [JsonDerivedType(typeof(NuiCombo))] + [JsonDerivedType(typeof(NuiImage))] + [JsonDerivedType(typeof(NuiLabel))] + [JsonDerivedType(typeof(NuiOptions))] + [JsonDerivedType(typeof(NuiProgress))] + [JsonDerivedType(typeof(NuiSlider))] + [JsonDerivedType(typeof(NuiSliderFloat))] + [JsonDerivedType(typeof(NuiSpacer))] + [JsonDerivedType(typeof(NuiText))] + [JsonDerivedType(typeof(NuiTextEdit))] + [JsonDerivedType(typeof(NuiToggles))] public abstract class NuiElement { /// /// The aspect ratio (x/y) for this element. /// - [JsonProperty("aspect", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("aspect")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public float? Aspect { get; set; } /// /// Toggles if this element is active/interactable, or disabled/greyed out. /// - [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("enabled")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NuiProperty? Enabled { get; set; } /// @@ -25,70 +49,83 @@ public abstract class NuiElement /// This is dependent on the widget in question and only supports solid/full colors right now (no texture skinning).
/// For example, labels would style their text color; progress bars would style the bar. ///
- [JsonProperty("foreground_color", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("foreground_color")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NuiProperty? ForegroundColor { get; set; } /// /// The height of this element, in pixels. /// - [JsonProperty("height", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("height")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public float? Height { get; set; } /// /// A unique identifier for this element. /// - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("id")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Id { get; set; } /// /// The margin on the widget. The margin is the spacing outside of the widget. /// - [JsonProperty("margin", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("margin")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public float? Margin { get; set; } /// /// The padding on the widget. The padding is the spacing inside of the widget. /// - [JsonProperty("padding", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("padding")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public float? Padding { get; set; } /// /// A tooltip to show when hovering over this element. /// - [JsonProperty("tooltip", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("tooltip")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NuiProperty? Tooltip { get; set; } - [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("type")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public abstract string Type { get; } /// /// Toggles if this element should/should not be rendered. Invisible elements still take up layout space, and cannot be clicked through. /// - [JsonProperty("visible", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("visible")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NuiProperty? Visible { get; set; } /// /// The width of this element, in pixels. /// - [JsonProperty("width", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("width")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public float? Width { get; set; } - [JsonProperty("draw_list", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("draw_list")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public List? DrawList { get; set; } - [JsonProperty("draw_list_scissor", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("draw_list_scissor")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NuiProperty? Scissor { get; set; } /// /// Tooltips for disabled elements show on mouse hover. /// - [JsonProperty("disabled_tooltip", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("disabled_tooltip")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NuiProperty? DisabledTooltip { get; set; } /// /// Encouraged elements have a breathing animated glow inside of it. /// - [JsonProperty("encouraged", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("encouraged")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NuiProperty? Encouraged { get; set; } } } diff --git a/NWN.Anvil/src/main/API/Nui/NuiList.cs b/NWN.Anvil/src/main/API/Nui/NuiList.cs index 3316383b1..81f04e273 100644 --- a/NWN.Anvil/src/main/API/Nui/NuiList.cs +++ b/NWN.Anvil/src/main/API/Nui/NuiList.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -12,35 +12,36 @@ public sealed class NuiList(IReadOnlyCollection rowTemplate /// /// Gets or sets whether a border should be rendered around this list view. /// - [JsonProperty("border")] + [JsonPropertyName("border")] public bool Border { get; set; } = true; /// /// Gets or sets the number of rows in this list. /// - [JsonProperty("row_count")] + [JsonPropertyName("row_count")] public NuiProperty RowCount { get; set; } = rowCount; /// /// Gets or sets the row height. /// - [JsonProperty("row_height")] + [JsonPropertyName("row_height")] public float RowHeight { get; set; } = NuiStyle.RowHeight; /// /// Gets or sets the list of cells composing the row template.
/// A max of 16 cells are supported. ///
- [JsonProperty("row_template")] + [JsonPropertyName("row_template")] public List RowTemplate { get; set; } = [..rowTemplate]; /// /// Gets or sets whether scroll bars should be rendered for this scroll list.
/// is not supported. ///
- [JsonProperty("scrollbars")] + [JsonPropertyName("scrollbars")] public NuiScrollbars Scrollbars { get; set; } = NuiScrollbars.Y; + [JsonPropertyName("type")] public override string Type => "list"; } } diff --git a/NWN.Anvil/src/main/API/Nui/NuiListTemplateCell.cs b/NWN.Anvil/src/main/API/Nui/NuiListTemplateCell.cs index 75ee830c5..c3c28466c 100644 --- a/NWN.Anvil/src/main/API/Nui/NuiListTemplateCell.cs +++ b/NWN.Anvil/src/main/API/Nui/NuiListTemplateCell.cs @@ -1,30 +1,26 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { /// /// A cell template for use in . /// - [JsonConverter(typeof(ObjectToArrayConverter))] - [method: JsonConstructor] + [JsonConverter(typeof(NuiListTemplateCellConverter))] public sealed class NuiListTemplateCell(NuiElement element) { /// /// The cell element. /// - [JsonProperty(Order = 1)] public NuiElement Element { get; set; } = element; /// /// Gets or sets if this cell can grow if space is available (true), or if it is static (false) /// - [JsonProperty(Order = 3)] public bool VariableSize { get; set; } /// /// The width of the cell. 0 = auto, >1 = pixel width. /// - [JsonProperty(Order = 2)] public float Width { get; set; } } } diff --git a/NWN.Anvil/src/main/API/Nui/NuiListTemplateCellConverter.cs b/NWN.Anvil/src/main/API/Nui/NuiListTemplateCellConverter.cs new file mode 100644 index 000000000..975eee908 --- /dev/null +++ b/NWN.Anvil/src/main/API/Nui/NuiListTemplateCellConverter.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Anvil.API +{ + internal sealed class NuiListTemplateCellConverter : JsonConverter + { + public override NuiListTemplateCell? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + JsonConverter nuiElementConverter = (JsonConverter)options.GetConverter(typeof(NuiElement)); + + reader.Read(); + if (reader.TokenType != JsonTokenType.StartArray) + { + throw new JsonException(); + } + + NuiElement? element = nuiElementConverter.Read(ref reader, typeof(NuiElement), options); + bool variableSize = reader.GetBoolean(); + float width = reader.GetSingle(); + + NuiListTemplateCell? retVal = null; + if (element != null) + { + retVal = new NuiListTemplateCell(element) + { + VariableSize = variableSize, + Width = width, + }; + } + + reader.Read(); + if (reader.TokenType != JsonTokenType.EndArray) + { + throw new JsonException(); + } + + return retVal; + } + + public override void Write(Utf8JsonWriter writer, NuiListTemplateCell value, JsonSerializerOptions options) + { + JsonConverter nuiElementConverter = (JsonConverter)options.GetConverter(typeof(NuiElement)); + + writer.WriteStartArray(); + nuiElementConverter.Write(writer, value.Element, options); + writer.WriteBooleanValue(value.VariableSize); + writer.WriteNumberValue(value.Width); + } + } +} diff --git a/NWN.Anvil/src/main/API/Nui/NuiRect.cs b/NWN.Anvil/src/main/API/Nui/NuiRect.cs index 753f419fe..5edbebedc 100644 --- a/NWN.Anvil/src/main/API/Nui/NuiRect.cs +++ b/NWN.Anvil/src/main/API/Nui/NuiRect.cs @@ -1,20 +1,20 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { [method: JsonConstructor] public readonly struct NuiRect(float x, float y, float width, float height) { - [JsonProperty("h")] + [JsonPropertyName("h")] public float Height { get; } = height; - [JsonProperty("w")] + [JsonPropertyName("w")] public float Width { get; } = width; - [JsonProperty("x")] + [JsonPropertyName("x")] public float X { get; } = x; - [JsonProperty("y")] + [JsonPropertyName("y")] public float Y { get; } = y; } } diff --git a/NWN.Anvil/src/main/API/Nui/NuiVector.cs b/NWN.Anvil/src/main/API/Nui/NuiVector.cs index a9dc043e0..4a452e046 100644 --- a/NWN.Anvil/src/main/API/Nui/NuiVector.cs +++ b/NWN.Anvil/src/main/API/Nui/NuiVector.cs @@ -1,16 +1,18 @@ using System; using System.Numerics; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { [method: JsonConstructor] public readonly struct NuiVector(float x, float y) : IEquatable { - [JsonProperty("x")] + [JsonPropertyName("x")] + [JsonInclude] public readonly float X = x; - [JsonProperty("y")] + [JsonPropertyName("y")] + [JsonInclude] public readonly float Y = y; public static NuiVector operator +(NuiVector a, NuiVector b) diff --git a/NWN.Anvil/src/main/API/Nui/NuiWindow.cs b/NWN.Anvil/src/main/API/Nui/NuiWindow.cs index b51d8e959..b799fe83f 100644 --- a/NWN.Anvil/src/main/API/Nui/NuiWindow.cs +++ b/NWN.Anvil/src/main/API/Nui/NuiWindow.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -11,21 +11,21 @@ public sealed class NuiWindow(NuiLayout root, NuiProperty title) /// /// Gets or sets whether the window border should be rendered. /// - [JsonProperty("border")] + [JsonPropertyName("border")] public NuiProperty Border { get; set; } = true; /// /// Gets or sets whether this window can be closed.
/// You must provide a way to close the window if you set this to false. ///
- [JsonProperty("closable")] + [JsonPropertyName("closable")] public NuiProperty Closable { get; set; } = true; /// /// Gets or sets whether this window is collapsed.
/// Use a static value to force the popup into a collapsed/unfolded state. ///
- [JsonProperty("collapsed")] + [JsonPropertyName("collapsed")] public NuiProperty? Collapsed { get; set; } /// @@ -34,49 +34,50 @@ public sealed class NuiWindow(NuiLayout root, NuiProperty title) /// Set x and/or y to -2.0 to position the window's top left at the mouse cursor's position of that axis
/// Set x and/or y to -3.0 to center the window on the mouse cursor's position of that axis ///
- [JsonProperty("geometry")] + [JsonPropertyName("geometry")] public NuiProperty Geometry { get; set; } = new NuiRect(-1, -1, 0, 0); /// /// Gets or sets the element ID for this window. /// - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("id")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Id { get; set; } /// /// Gets or sets whether this window can be resized. /// - [JsonProperty("resizable")] + [JsonPropertyName("resizable")] public NuiProperty Resizable { get; set; } = true; /// /// Gets or sets the root parent layout containing the window content. /// - [JsonProperty("root")] + [JsonPropertyName("root")] public NuiLayout Root { get; set; } = root; /// /// Gets or sets the title of this window. /// - [JsonProperty("title")] + [JsonPropertyName("title")] public NuiProperty Title { get; set; } = title; /// /// Gets or sets whether the background should be rendered. /// - [JsonProperty("transparent")] + [JsonPropertyName("transparent")] public NuiProperty Transparent { get; set; } = false; /// /// Gets the current serialized version of this window. /// - [JsonProperty("version")] + [JsonPropertyName("version")] public int Version { get; private set; } = 1; /// /// Set to false to disable all input. All hover, clicks and keypresses will fall through. /// - [JsonProperty("accepts_input")] + [JsonPropertyName("accepts_input")] public NuiProperty AcceptsInput { get; set; } = true; } } diff --git a/NWN.Anvil/src/main/API/Nui/NuiWindowToken.cs b/NWN.Anvil/src/main/API/Nui/NuiWindowToken.cs index d31bb39a1..31b2f4b95 100644 --- a/NWN.Anvil/src/main/API/Nui/NuiWindowToken.cs +++ b/NWN.Anvil/src/main/API/Nui/NuiWindowToken.cs @@ -107,7 +107,7 @@ public override int GetHashCode() /// The fetched data, or null if the window does not exist on the given player, or has no userdata set. public T? GetUserData() { - return JsonUtility.FromJson(NWScript.NuiGetUserData(Player.ControlledCreature, Token)); + return ((Json)NWScript.NuiGetUserData(Player.ControlledCreature, Token)).Deserialize(); } /// @@ -163,7 +163,7 @@ public void SetGroupLayout(NuiGroup group, NuiLayout newLayout) /// The type of data to store. Must be serializable to JSON. public void SetUserData(T userData) { - NWScript.NuiSetUserData(Player.ControlledCreature, Token, JsonUtility.ToJsonStructure(userData)); + NWScript.NuiSetUserData(Player.ControlledCreature, Token, Json.Serialize(userData)); } } } diff --git a/NWN.Anvil/src/main/API/Nui/ObjectToArrayConverter.cs b/NWN.Anvil/src/main/API/Nui/ObjectToArrayConverter.cs deleted file mode 100644 index 02e4ed429..000000000 --- a/NWN.Anvil/src/main/API/Nui/ObjectToArrayConverter.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; - -namespace Anvil.API -{ - // https://stackoverflow.com/questions/39461518/how-to-deserialize-an-array-of-values-with-a-fixed-schema-to-a-strongly-typed-da/39462464#39462464 - internal sealed class ObjectToArrayConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return typeof(T) == objectType; - } - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (serializer.ContractResolver.ResolveContract(objectType) is not JsonObjectContract contract) - { - throw new JsonSerializationException($"invalid type {objectType.FullName}."); - } - - if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null) - { - return null; - } - - if (reader.TokenType != JsonToken.StartArray) - { - throw new JsonSerializationException($"token {reader.TokenType} was not JsonToken.StartArray"); - } - - if (existingValue == null && contract.DefaultCreator == null) - { - return null; - } - - // Not implemented: JsonObjectContract.CreatorParameters, serialization callbacks, - existingValue ??= contract.DefaultCreator!(); - - using IEnumerator enumerator = SerializableProperties(contract).GetEnumerator(); - - while (true) - { - switch (reader.ReadToContentAndAssert().TokenType) - { - case JsonToken.EndArray: - return existingValue; - - default: - if (!enumerator.MoveNext()) - { - reader.Skip(); - break; - } - - JsonProperty property = enumerator.Current; - object? propertyValue; - // TODO: - // https://www.newtonsoft.com/json/help/html/Properties_T_Newtonsoft_Json_Serialization_JsonProperty.htm - // JsonProperty.ItemConverter, ItemIsReference, ItemReferenceLoopHandling, ItemTypeNameHandling, DefaultValue, DefaultValueHandling, ReferenceLoopHandling, Required, TypeNameHandling, ... - - if (property.PropertyType == null || property.ValueProvider == null) - { - continue; - } - - if (property.Converter != null && property.Converter.CanRead) - { - propertyValue = property.Converter.ReadJson(reader, property.PropertyType, property.ValueProvider.GetValue(existingValue), serializer); - } - else - { - propertyValue = serializer.Deserialize(reader, property.PropertyType); - } - - property.ValueProvider.SetValue(existingValue, propertyValue); - break; - } - } - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - writer.WriteStartArray(); - if (value != null) - { - Type objectType = value.GetType(); - if (serializer.ContractResolver.ResolveContract(objectType) is not JsonObjectContract contract) - { - throw new JsonSerializationException($"invalid type {objectType.FullName}."); - } - - foreach (JsonProperty property in SerializableProperties(contract)) - { - object? propertyValue = property.ValueProvider?.GetValue(value); - if (property.Converter != null && property.Converter.CanWrite) - { - property.Converter.WriteJson(writer, propertyValue, serializer); - } - else - { - serializer.Serialize(writer, propertyValue); - } - } - } - - writer.WriteEndArray(); - } - - private static IEnumerable SerializableProperties(JsonObjectContract contract) - { - return contract.Properties.Where(p => !p.Ignored && p.Readable && p.Writable); - } - } - - internal static class JsonExtensions - { - public static JsonReader MoveToContentAndAssert(this JsonReader reader) - { - if (reader == null) - { - throw new ArgumentNullException(); - } - - if (reader.TokenType == JsonToken.None) // Skip past beginning of stream. - { - reader.ReadAndAssert(); - } - - while (reader.TokenType == JsonToken.Comment) // Skip past comments. - { - reader.ReadAndAssert(); - } - - return reader; - } - - public static JsonReader ReadAndAssert(this JsonReader reader) - { - if (reader == null) - { - throw new ArgumentNullException(); - } - - if (!reader.Read()) - { - throw new JsonReaderException("Unexpected end of JSON stream."); - } - - return reader; - } - - public static JsonReader ReadToContentAndAssert(this JsonReader reader) - { - return reader.ReadAndAssert().MoveToContentAndAssert(); - } - } -} diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListArc.cs b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListArc.cs index 681b9d9bc..331ed9561 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListArc.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListArc.cs @@ -1,10 +1,9 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { public sealed class NuiDrawListArc : NuiDrawListItem { - [JsonConstructor] public NuiDrawListArc(NuiProperty color, NuiProperty fill, NuiProperty lineThickness, NuiProperty center, NuiProperty radius, NuiProperty angleMin, NuiProperty angleMax) { @@ -17,18 +16,19 @@ public NuiDrawListArc(NuiProperty color, NuiProperty fill, NuiPrope AngleMax = angleMax; } - [JsonProperty("amax")] + [JsonPropertyName("amax")] public NuiProperty AngleMax { get; set; } - [JsonProperty("amin")] + [JsonPropertyName("amin")] public NuiProperty AngleMin { get; set; } - [JsonProperty("c")] + [JsonPropertyName("c")] public NuiProperty Center { get; set; } - [JsonProperty("radius")] + [JsonPropertyName("radius")] public NuiProperty Radius { get; set; } + [JsonPropertyName("type")] public override NuiDrawListItemType Type => NuiDrawListItemType.Arc; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListCircle.cs b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListCircle.cs index 9a2223933..6286c7142 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListCircle.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListCircle.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -13,9 +13,10 @@ public NuiDrawListCircle(NuiProperty color, NuiProperty fill, NuiPr Rect = rect; } - [JsonProperty("rect")] + [JsonPropertyName("rect")] public NuiProperty Rect { get; set; } + [JsonPropertyName("type")] public override NuiDrawListItemType Type => NuiDrawListItemType.Circle; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListCurve.cs b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListCurve.cs index 765748d21..62d9c8288 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListCurve.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListCurve.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -16,18 +16,19 @@ public NuiDrawListCurve(NuiProperty color, NuiProperty lineThickne Control1 = control1; } - [JsonProperty("ctrl0")] + [JsonPropertyName("ctrl0")] public NuiProperty Control0 { get; set; } - [JsonProperty("ctrl1")] + [JsonPropertyName("ctrl1")] public NuiProperty Control1 { get; set; } - [JsonProperty("a")] + [JsonPropertyName("a")] public NuiProperty PointA { get; set; } - [JsonProperty("b")] + [JsonPropertyName("b")] public NuiProperty PointB { get; set; } + [JsonPropertyName("type")] public override NuiDrawListItemType Type => NuiDrawListItemType.Curve; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListImage.cs b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListImage.cs index 7f7763ff0..9f92e3611 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListImage.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListImage.cs @@ -1,32 +1,34 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { [method: JsonConstructor] public sealed class NuiDrawListImage(NuiProperty resRef, NuiProperty rect) : NuiDrawListItem { - [JsonProperty("image_aspect")] + [JsonPropertyName("image_aspect")] public NuiProperty Aspect { get; set; } = NuiAspect.Exact; - [JsonProperty("image_halign")] + [JsonPropertyName("image_halign")] public NuiProperty HorizontalAlign { get; set; } = NuiHAlign.Left; - [JsonProperty("rect")] + [JsonPropertyName("rect")] public NuiProperty Rect { get; set; } = rect; - [JsonProperty("image")] + [JsonPropertyName("image")] public NuiProperty ResRef { get; set; } = resRef; /// /// Optionally render a subregion of the image.
/// This property is a NuiRect (x, y, w, h) to indicate the render region inside the image. ///
- [JsonProperty("image_region", NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("image_region")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NuiProperty? ImageRegion { get; set; } + [JsonPropertyName("type")] public override NuiDrawListItemType Type => NuiDrawListItemType.Image; - [JsonProperty("image_valign")] + [JsonPropertyName("image_valign")] public NuiProperty VerticalAlign { get; set; } = NuiVAlign.Top; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListItem.cs b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListItem.cs index f297918ee..a20d806ed 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListItem.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListItem.cs @@ -1,28 +1,39 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { + [JsonPolymorphic] + [JsonDerivedType(typeof(NuiDrawListArc))] + [JsonDerivedType(typeof(NuiDrawListCircle))] + [JsonDerivedType(typeof(NuiDrawListCurve))] + [JsonDerivedType(typeof(NuiDrawListImage))] + [JsonDerivedType(typeof(NuiDrawListLine))] + [JsonDerivedType(typeof(NuiDrawListPolyLine))] + [JsonDerivedType(typeof(NuiDrawListText))] public abstract class NuiDrawListItem { - [JsonProperty("color", NullValueHandling = NullValueHandling.Include)] + [JsonPropertyName("color")] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public NuiProperty? Color { get; set; } - [JsonProperty("enabled")] + [JsonPropertyName("enabled")] public NuiProperty Enabled { get; set; } = true; - [JsonProperty("fill", NullValueHandling = NullValueHandling.Include)] + [JsonPropertyName("fill")] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public NuiProperty? Fill { get; set; } - [JsonProperty("line_thickness", NullValueHandling = NullValueHandling.Include)] + [JsonPropertyName("line_thickness")] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public NuiProperty? LineThickness { get; set; } - [JsonProperty("type")] + [JsonPropertyName("type")] public abstract NuiDrawListItemType Type { get; } - [JsonProperty("order")] + [JsonPropertyName("order")] public NuiDrawListItemOrder Order { get; set; } = NuiDrawListItemOrder.After; - [JsonProperty("render")] + [JsonPropertyName("render")] public NuiDrawListItemRender Render { get; set; } = NuiDrawListItemRender.Always; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListLine.cs b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListLine.cs index 96d445671..7ca40c7a6 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListLine.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListLine.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -14,12 +14,13 @@ public NuiDrawListLine(NuiProperty color, NuiProperty fill, NuiProp PointB = pointB; } - [JsonProperty("a")] + [JsonPropertyName("a")] public NuiProperty PointA { get; set; } - [JsonProperty("b")] + [JsonPropertyName("b")] public NuiProperty PointB { get; set; } + [JsonPropertyName("type")] public override NuiDrawListItemType Type => NuiDrawListItemType.Line; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListPolyLine.cs b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListPolyLine.cs index ec1b28f1a..a63cf5e1e 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListPolyLine.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListPolyLine.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -14,9 +14,10 @@ public NuiDrawListPolyLine(NuiProperty color, NuiProperty fill, Nui Points = points; } - [JsonProperty("points")] + [JsonPropertyName("points")] public List Points { get; set; } + [JsonPropertyName("type")] public override NuiDrawListItemType Type => NuiDrawListItemType.PolyLine; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListText.cs b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListText.cs index a5dbaa4b0..f17b8622b 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListText.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/DrawList/NuiDrawListText.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -12,12 +12,13 @@ public NuiDrawListText(NuiProperty color, NuiProperty rect, NuiP Text = text; } - [JsonProperty("rect")] + [JsonPropertyName("rect")] public NuiProperty Rect { get; set; } - [JsonProperty("text")] + [JsonPropertyName("text")] public NuiProperty Text { get; set; } + [JsonPropertyName("type")] public override NuiDrawListItemType Type => NuiDrawListItemType.Text; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiButton.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiButton.cs index 2d63fae67..c87209f5e 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiButton.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiButton.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,9 +8,10 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiButton(NuiProperty label) : NuiWidget { - [JsonProperty("label")] + [JsonPropertyName("label")] public NuiProperty Label { get; set; } = label; + [JsonPropertyName("type")] public override string Type => "button"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiButtonImage.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiButtonImage.cs index a115c1d69..fc7c0927d 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiButtonImage.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiButtonImage.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,9 +8,10 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiButtonImage(NuiProperty resRef) : NuiWidget { - [JsonProperty("label")] + [JsonPropertyName("label")] public NuiProperty ResRef { get; set; } = resRef; + [JsonPropertyName("type")] public override string Type => "button_image"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiButtonSelect.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiButtonSelect.cs index 7bd2c2db2..6d3171038 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiButtonSelect.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiButtonSelect.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -9,12 +9,13 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiButtonSelect(NuiProperty label, NuiProperty selected) : NuiWidget { - [JsonProperty("label")] + [JsonPropertyName("label")] public NuiProperty Label { get; set; } = label; - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Selected { get; set; } = selected; + [JsonPropertyName("type")] public override string Type => "button_select"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiChart.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiChart.cs index 6fdfbf38a..2ff61ba46 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiChart.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiChart.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,9 +8,10 @@ namespace Anvil.API ///
public sealed class NuiChart : NuiWidget { - [JsonProperty("value")] + [JsonPropertyName("value")] public List? ChartSlots { get; set; } + [JsonPropertyName("type")] public override string Type => "chart"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiChartSlot.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiChartSlot.cs index 146839dfc..f7062413a 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiChartSlot.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiChartSlot.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -9,16 +9,16 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiChartSlot(NuiChartType chartType, NuiProperty legend, NuiProperty color, NuiProperty> data) { - [JsonProperty("type")] + [JsonPropertyName("type")] public NuiChartType ChartType { get; set; } = chartType; - [JsonProperty("color")] + [JsonPropertyName("color")] public NuiProperty Color { get; set; } = color; - [JsonProperty("data")] + [JsonPropertyName("data")] public NuiProperty> Data { get; set; } = data; - [JsonProperty("legend")] + [JsonPropertyName("legend")] public NuiProperty Legend { get; set; } = legend; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiCheck.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiCheck.cs index d7eb08ed7..6f4ab2693 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiCheck.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiCheck.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,12 +8,13 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiCheck(NuiProperty label, NuiProperty selected) : NuiWidget { - [JsonProperty("label")] + [JsonPropertyName("label")] public NuiProperty Label { get; set; } = label; - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Selected { get; set; } = selected; + [JsonPropertyName("type")] public override string Type => "check"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiColorPicker.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiColorPicker.cs index ed6d90619..9cbaf6cd0 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiColorPicker.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiColorPicker.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,9 +8,10 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiColorPicker(NuiProperty color) : NuiWidget { - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Color { get; set; } = color; + [JsonPropertyName("type")] public override string Type => "color_picker"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiCombo.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiCombo.cs index da8ef4f71..04131c786 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiCombo.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiCombo.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,12 +8,13 @@ namespace Anvil.API ///
public sealed class NuiCombo : NuiWidget { - [JsonProperty("elements")] + [JsonPropertyName("elements")] public NuiProperty> Entries { get; set; } = new List(); - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Selected { get; set; } = 0; + [JsonPropertyName("type")] public override string Type => "combo"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiComboEntry.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiComboEntry.cs index f2c172951..c527da9c2 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiComboEntry.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiComboEntry.cs @@ -1,18 +1,14 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { /// /// A combo/list element for use in . /// - [JsonConverter(typeof(ObjectToArrayConverter))] - [method: JsonConstructor] + [JsonConverter(typeof(NuiComboEntryConverter))] public sealed class NuiComboEntry(string label, int value) { - [JsonProperty(Order = 1)] public string Label { get; set; } = label; - - [JsonProperty(Order = 2)] public int Value { get; set; } = value; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiComboEntryConverter.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiComboEntryConverter.cs new file mode 100644 index 000000000..4ff10e6f0 --- /dev/null +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiComboEntryConverter.cs @@ -0,0 +1,43 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Anvil.API +{ + internal sealed class NuiComboEntryConverter : JsonConverter + { + public override NuiComboEntry? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.StartArray) + { + throw new JsonException(); + } + + string? label = reader.GetString(); + int value = reader.GetInt32(); + + NuiComboEntry? retVal = null; + if (label != null) + { + retVal = new NuiComboEntry(label, value); + } + + reader.Read(); + if (reader.TokenType != JsonTokenType.EndArray) + { + throw new JsonException(); + } + + return retVal; + } + + public override void Write(Utf8JsonWriter writer, NuiComboEntry value, JsonSerializerOptions options) + { + writer.WriteStartArray(); + writer.WriteStringValue(value.Label); + writer.WriteNumberValue(value.Value); + writer.WriteEndArray(); + } + } +} diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiImage.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiImage.cs index cce0f1576..3f9283b2c 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiImage.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiImage.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,25 +8,26 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiImage(NuiProperty resRef) : NuiWidget { - [JsonProperty("image_halign")] + [JsonPropertyName("image_halign")] public NuiProperty HorizontalAlign { get; set; } = NuiHAlign.Left; - [JsonProperty("image_aspect")] + [JsonPropertyName("image_aspect")] public NuiProperty ImageAspect { get; set; } = NuiAspect.Exact; /// /// Optionally render only subregion of jImage.
/// This property is a NuiRect (x, y, w, h) to indicate the render region inside the image. ///
- [JsonProperty("image_region")] + [JsonPropertyName("image_region")] public NuiProperty? ImageRegion { get; set; } - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty ResRef { get; set; } = resRef; + [JsonPropertyName("type")] public override string Type => "image"; - [JsonProperty("image_valign")] + [JsonPropertyName("image_valign")] public NuiProperty VerticalAlign { get; set; } = NuiVAlign.Top; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiLabel.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiLabel.cs index fc89376d9..a3dfa90c6 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiLabel.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiLabel.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,15 +8,16 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiLabel(NuiProperty label) : NuiWidget { - [JsonProperty("text_halign")] + [JsonPropertyName("text_halign")] public NuiProperty HorizontalAlign { get; set; } = NuiHAlign.Left; - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Label { get; set; } = label; + [JsonPropertyName("type")] public override string Type => "label"; - [JsonProperty("text_valign")] + [JsonPropertyName("text_valign")] public NuiProperty VerticalAlign { get; set; } = NuiVAlign.Top; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiOptions.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiOptions.cs index fe4f0c6e8..e5af86e71 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiOptions.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiOptions.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -9,15 +9,16 @@ namespace Anvil.API /// public sealed class NuiOptions : NuiWidget { - [JsonProperty("direction")] + [JsonPropertyName("direction")] public NuiDirection Direction { get; set; } = NuiDirection.Horizontal; - [JsonProperty("elements")] + [JsonPropertyName("elements")] public List Options { get; set; } = []; - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Selection { get; set; } = -1; + [JsonPropertyName("type")] public override string Type => "options"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiProgress.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiProgress.cs index 3730d2417..f5d408600 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiProgress.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiProgress.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,12 +8,13 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiProgress(NuiProperty value) : NuiWidget { + [JsonPropertyName("type")] public override string Type => "progress"; /// /// The current value of this progress bar (0-1). /// - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Value { get; set; } = value; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiSlider.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiSlider.cs index c3628288d..ae38faf0a 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiSlider.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiSlider.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,18 +8,19 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiSlider(NuiProperty value, NuiProperty min, NuiProperty max) : NuiWidget { - [JsonProperty("max")] + [JsonPropertyName("max")] public NuiProperty Max { get; set; } = max; - [JsonProperty("min")] + [JsonPropertyName("min")] public NuiProperty Min { get; set; } = min; - [JsonProperty("step")] + [JsonPropertyName("step")] public NuiProperty Step { get; set; } = 1; + [JsonPropertyName("type")] public override string Type => "slider"; - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Value { get; set; } = value; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiSliderFloat.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiSliderFloat.cs index da0386bdc..2f6486887 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiSliderFloat.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiSliderFloat.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,18 +8,19 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiSliderFloat(NuiProperty value, NuiProperty min, NuiProperty max) : NuiWidget { - [JsonProperty("max")] + [JsonPropertyName("max")] public NuiProperty Max { get; set; } = max; - [JsonProperty("min")] + [JsonPropertyName("min")] public NuiProperty Min { get; set; } = min; - [JsonProperty("step")] + [JsonPropertyName("step")] public NuiProperty StepSize { get; set; } = 0.01f; + [JsonPropertyName("type")] public override string Type => "sliderf"; - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Value { get; set; } = value; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiSpacer.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiSpacer.cs index a8b62e872..29209b28c 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiSpacer.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiSpacer.cs @@ -1,3 +1,5 @@ +using System.Text.Json.Serialization; + namespace Anvil.API { /// @@ -6,6 +8,7 @@ namespace Anvil.API /// public sealed class NuiSpacer : NuiWidget { + [JsonPropertyName("type")] public override string Type => "spacer"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiText.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiText.cs index 31a086b00..4348fc5f8 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiText.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiText.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,15 +8,16 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiText(NuiProperty text) : NuiWidget { - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Text { get; set; } = text; - [JsonProperty("border")] + [JsonPropertyName("border")] public bool Border { get; set; } = true; - [JsonProperty("scrollbars")] + [JsonPropertyName("scrollbars")] public NuiScrollbars Scrollbars { get; set; } = NuiScrollbars.Auto; + [JsonPropertyName("type")] public override string Type => "text"; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiTextEdit.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiTextEdit.cs index f35300a0f..4a8963436 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiTextEdit.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiTextEdit.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { @@ -8,21 +8,22 @@ namespace Anvil.API [method: JsonConstructor] public sealed class NuiTextEdit(NuiProperty label, NuiProperty value, ushort maxLength, bool multiLine) : NuiWidget { - [JsonProperty("label")] + [JsonPropertyName("label")] public NuiProperty Label { get; set; } = label; - [JsonProperty("max")] + [JsonPropertyName("max")] public ushort MaxLength { get; set; } = maxLength; - [JsonProperty("multiline")] + [JsonPropertyName("multiline")] public bool MultiLine { get; set; } = multiLine; + [JsonPropertyName("type")] public override string Type => "textedit"; - [JsonProperty("value")] + [JsonPropertyName("value")] public NuiProperty Value { get; set; } = value; - [JsonProperty("wordwrap")] + [JsonPropertyName("wordwrap")] public NuiProperty WordWrap { get; set; } = true; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiToggles.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiToggles.cs index b73c93d95..336624808 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiToggles.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiToggles.cs @@ -1,16 +1,17 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Anvil.API { public sealed class NuiToggles(NuiDirection direction, List elements) : NuiWidget { + [JsonPropertyName("type")] public override string Type => "tabbar"; - [JsonProperty("direction")] + [JsonPropertyName("direction")] public NuiDirection Direction { get; set; } = direction; - [JsonProperty("elements")] + [JsonPropertyName("elements")] public List Elements { get; set; } = elements; } } diff --git a/NWN.Anvil/src/main/API/Nui/Widgets/NuiWidget.cs b/NWN.Anvil/src/main/API/Nui/Widgets/NuiWidget.cs index 57dbb2ce2..e8975d891 100644 --- a/NWN.Anvil/src/main/API/Nui/Widgets/NuiWidget.cs +++ b/NWN.Anvil/src/main/API/Nui/Widgets/NuiWidget.cs @@ -1,7 +1,27 @@ +using System.Text.Json.Serialization; + namespace Anvil.API { /// /// The abstract base for all NUI widgets - the building blocks for creating NUI windows. /// + [JsonPolymorphic] + [JsonDerivedType(typeof(NuiButton))] + [JsonDerivedType(typeof(NuiButtonImage))] + [JsonDerivedType(typeof(NuiButtonSelect))] + [JsonDerivedType(typeof(NuiChart))] + [JsonDerivedType(typeof(NuiCheck))] + [JsonDerivedType(typeof(NuiColorPicker))] + [JsonDerivedType(typeof(NuiCombo))] + [JsonDerivedType(typeof(NuiImage))] + [JsonDerivedType(typeof(NuiLabel))] + [JsonDerivedType(typeof(NuiOptions))] + [JsonDerivedType(typeof(NuiProgress))] + [JsonDerivedType(typeof(NuiSlider))] + [JsonDerivedType(typeof(NuiSliderFloat))] + [JsonDerivedType(typeof(NuiSpacer))] + [JsonDerivedType(typeof(NuiText))] + [JsonDerivedType(typeof(NuiTextEdit))] + [JsonDerivedType(typeof(NuiToggles))] public abstract class NuiWidget : NuiElement; } diff --git a/NWN.Anvil/src/main/API/Objects/NwArea.cs b/NWN.Anvil/src/main/API/Objects/NwArea.cs index 1fbfee596..1d864ab05 100644 --- a/NWN.Anvil/src/main/API/Objects/NwArea.cs +++ b/NWN.Anvil/src/main/API/Objects/NwArea.cs @@ -695,7 +695,7 @@ public void ReloadAreaBorder() /// If specified, also changes the area's tileset. Warning: only use this if you really know what you're doing, it's very easy to break things badly. public void SetTiles(List data, SettleFlags flags = SettleFlags.RecomputeLighting, string tileSet = "") { - Json tileData = JsonUtility.ToJsonStructure(data); + Json tileData = Json.Serialize(data); NWScript.SetTileJson(this, tileData, (int)flags, tileSet); } diff --git a/NWN.Anvil/src/main/API/Objects/NwPlayer.cs b/NWN.Anvil/src/main/API/Objects/NwPlayer.cs index f0afe5f03..3b7b7c3cb 100644 --- a/NWN.Anvil/src/main/API/Objects/NwPlayer.cs +++ b/NWN.Anvil/src/main/API/Objects/NwPlayer.cs @@ -1655,7 +1655,7 @@ public async Task StoreCameraFacing() /// True if the window was successfully created, otherwise false. public bool TryCreateNuiWindow(NuiWindow window, out NuiWindowToken token, string windowId = "") { - int tokenId = NWScript.NuiCreate(ControlledCreature, JsonUtility.ToJsonStructure(window), windowId); + int tokenId = NWScript.NuiCreate(ControlledCreature, Json.Serialize(window), windowId); token = tokenId != 0 ? new NuiWindowToken(this, tokenId) : NuiWindowToken.Invalid; return tokenId != 0; diff --git a/NWN.Anvil/src/main/API/Tlk/StrRef.cs b/NWN.Anvil/src/main/API/Tlk/StrRef.cs index ef4bf668c..5c6381dd4 100644 --- a/NWN.Anvil/src/main/API/Tlk/StrRef.cs +++ b/NWN.Anvil/src/main/API/Tlk/StrRef.cs @@ -1,6 +1,6 @@ +using System.Text.Json.Serialization; using Anvil.Internal; using Anvil.Services; -using Newtonsoft.Json; using NWN.Native.API; namespace Anvil.API @@ -8,8 +8,8 @@ namespace Anvil.API /// /// A talk table (tlk) string reference. /// - [method: JsonConstructor] - public readonly struct StrRef(uint stringId) + [JsonConverter(typeof(StrRefConverter))] + public readonly struct StrRef { private const uint CustomTlkOffset = 0x1000000; @@ -19,21 +19,26 @@ public readonly struct StrRef(uint stringId) /// /// Gets the index/key for this StrRef. /// - [JsonProperty("strref")] - public readonly uint Id = stringId; + public uint Id { get; } - public StrRef(int stringId) : this((uint)stringId) {} + /// + /// A talk table (tlk) string reference. + /// + public StrRef(uint id) + { + Id = id; + } + + public StrRef(int id) : this((uint)id) {} /// /// Gets the index/key for this StrRef relative to the module's custom talk table. (-16777216) /// - [JsonIgnore] public uint CustomId => Id - CustomTlkOffset; /// /// Gets or sets a string override that this StrRef should return instead of the tlk file definition. /// - [JsonIgnore] public string? Override { get => TlkTable.GetTlkOverride(this); diff --git a/NWN.Anvil/src/main/API/Tlk/StrRefConverter.cs b/NWN.Anvil/src/main/API/Tlk/StrRefConverter.cs new file mode 100644 index 000000000..f4b6d0c2f --- /dev/null +++ b/NWN.Anvil/src/main/API/Tlk/StrRefConverter.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Anvil.API +{ + internal sealed class StrRefConverter : JsonConverter + { + public override StrRef Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + CheckToken(ref reader, JsonTokenType.StartObject); + reader.Read(); + CheckToken(ref reader, JsonTokenType.PropertyName); + + string? propertyName = reader.GetString(); + if (propertyName != "strref") + { + throw new JsonException($"Expected property name 'strref', got '{propertyName}'"); + } + + reader.Read(); + StrRef retVal = new StrRef(reader.GetUInt32()); + + reader.Read(); + CheckToken(ref reader, JsonTokenType.EndObject); + + return retVal; + } + + public override void Write(Utf8JsonWriter writer, StrRef value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("strref"); + writer.WriteNumberValue(value.Id); + writer.WriteEndObject(); + } + + private void CheckToken(ref Utf8JsonReader reader, JsonTokenType tokenType) + { + if (reader.TokenType != tokenType) + { + throw new JsonException($"Expected token type '{tokenType}', got '{reader.TokenType}'"); + } + } + } +} diff --git a/NWN.Anvil/src/main/API/Utils/JsonCacheService.cs b/NWN.Anvil/src/main/API/Utils/JsonCacheService.cs new file mode 100644 index 000000000..3f94329f0 --- /dev/null +++ b/NWN.Anvil/src/main/API/Utils/JsonCacheService.cs @@ -0,0 +1,36 @@ +using System; +using System.Reflection; +using System.Text.Json; +using Anvil.Plugins; +using Anvil.Services; +using LightInject; + +namespace Anvil.API +{ + internal sealed class JsonCacheService : ICoreService + { + private static readonly Type? UpdateHandlerType = typeof(JsonSerializerOptions).Assembly.GetType("System.Text.Json.JsonSerializerOptionsUpdateHandler"); + private static readonly MethodInfo? ClearCacheMethod = UpdateHandlerType?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public); + + [Inject] + private IServiceManager ServiceManager { get; init; } = null!; + + void ICoreService.Init() + { + ServiceManager.OnContainerDispose += OnContainerDispose; + } + + void ICoreService.Load() {} + + void ICoreService.Shutdown() {} + + void ICoreService.Start() {} + + void ICoreService.Unload() {} + + private void OnContainerDispose(IServiceContainer container, Plugin? plugin, bool immediateDispose) + { + ClearCacheMethod?.Invoke(null, [null]); + } + } +} diff --git a/NWN.Anvil/src/main/API/Utils/JsonUtility.cs b/NWN.Anvil/src/main/API/Utils/JsonUtility.cs deleted file mode 100644 index a71043cf6..000000000 --- a/NWN.Anvil/src/main/API/Utils/JsonUtility.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Newtonsoft.Json; - -namespace Anvil.API -{ - /// - /// Utility methods for serializing/deserializing JSON data. - /// - public static class JsonUtility - { - /// - /// Deserializes a JSON string. - /// - /// The JSON to deserialize. - /// The type to deserialize to. - /// The deserialized object. - public static T? FromJson(string json) - { - return JsonConvert.DeserializeObject(json); - } - - /// - /// Serializes a value as JSON. - /// - /// The value to serialize. - /// The type of the value to serialize. - /// A JSON string representing the value. - public static string ToJson(T value) - { - return JsonConvert.SerializeObject(value); - } - - /// - /// Deserializes a Json game engine structure. - /// - /// The json to deserialize. - /// The type to deserialize to. - /// The deserialized object. - internal static T? FromJson(Json json) - { - return JsonConvert.DeserializeObject(json.Dump()); - } - - /// - /// Serializes a value as a JSON engine structure. - /// - /// The value to serialize. - /// The type of the value to serialize. - /// A JSON engine structure representing the value. - internal static Json ToJsonStructure(T value) - { - string serialized = ToJson(value); - return Json.Parse(serialized); - } - } -} diff --git a/NWN.Anvil/src/main/API/Variables/Local/LocalVariableStruct.cs b/NWN.Anvil/src/main/API/Variables/Local/LocalVariableStruct.cs index 57c180bdf..3b25cd7c7 100644 --- a/NWN.Anvil/src/main/API/Variables/Local/LocalVariableStruct.cs +++ b/NWN.Anvil/src/main/API/Variables/Local/LocalVariableStruct.cs @@ -14,8 +14,8 @@ public sealed class LocalVariableStruct : LocalVariable { public override T? Value { - get => HasValue ? JsonUtility.FromJson(NWScript.GetLocalJson(Object, Name)) : default; - set => NWScript.SetLocalJson(Object, Name, JsonUtility.ToJsonStructure(value)); + get => HasValue ? ((Json)NWScript.GetLocalJson(Object, Name)).Deserialize() : default; + set => NWScript.SetLocalJson(Object, Name, Json.Serialize(value)); } public override void Delete() diff --git a/NWN.Anvil/src/main/API/Variables/ObjectStorage/ObjectStorageVariableStruct.cs b/NWN.Anvil/src/main/API/Variables/ObjectStorage/ObjectStorageVariableStruct.cs index 5bf679955..043a1a9bf 100644 --- a/NWN.Anvil/src/main/API/Variables/ObjectStorage/ObjectStorageVariableStruct.cs +++ b/NWN.Anvil/src/main/API/Variables/ObjectStorage/ObjectStorageVariableStruct.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Anvil.Services; namespace Anvil.API @@ -16,12 +17,12 @@ public sealed override T? Value if (ObjectStorageService.TryGetObjectStorage(Object, out ObjectStorage? objectStorage)) { string? serialized = objectStorage.GetString(ObjectStoragePrefix, Key); - return !string.IsNullOrEmpty(serialized) ? JsonUtility.FromJson(serialized) : default; + return !string.IsNullOrEmpty(serialized) ? JsonSerializer.Deserialize(serialized) : default; } return default; } - set => ObjectStorageService.GetObjectStorage(Object).Set(ObjectStoragePrefix, Key, JsonUtility.ToJson(value), Persist); + set => ObjectStorageService.GetObjectStorage(Object).Set(ObjectStoragePrefix, Key, JsonSerializer.Serialize(value), Persist); } protected sealed override string VariableTypePrefix => "PERSTR!"; diff --git a/NWN.Anvil/src/main/Internal/Assemblies.cs b/NWN.Anvil/src/main/Internal/Assemblies.cs index 746567ab6..dead1659a 100644 --- a/NWN.Anvil/src/main/Internal/Assemblies.cs +++ b/NWN.Anvil/src/main/Internal/Assemblies.cs @@ -31,7 +31,6 @@ static Assemblies() NWNXDotNet, typeof(NLog.Logger).Assembly, typeof(LightInject.ServiceContainer).Assembly, - typeof(Newtonsoft.Json.JsonConvert).Assembly, typeof(Paket.Dependencies).Assembly, ]; diff --git a/NWN.Anvil/src/main/Services/Services/AnvilCoreServiceManager.cs b/NWN.Anvil/src/main/Services/Services/AnvilCoreServiceManager.cs index a0a878e0a..fa2609b6f 100644 --- a/NWN.Anvil/src/main/Services/Services/AnvilCoreServiceManager.cs +++ b/NWN.Anvil/src/main/Services/Services/AnvilCoreServiceManager.cs @@ -23,6 +23,7 @@ internal sealed class AnvilCoreServiceManager private readonly ResourceManager resourceManager; private readonly AnvilMessageService anvilMessageService; private readonly ObjectStorageService objectStorageService; + private readonly JsonCacheService jsonCacheService; public AnvilCoreServiceManager(IServiceContainer container) { @@ -39,6 +40,7 @@ public AnvilCoreServiceManager(IServiceContainer container) container.RegisterCoreService(); container.RegisterCoreService(); container.RegisterCoreService(); + container.RegisterCoreService(); container.Compile(); @@ -55,6 +57,7 @@ public AnvilCoreServiceManager(IServiceContainer container) hookService = container.GetInstance(); moduleLoadTracker = container.GetInstance(); objectStorageService = container.GetInstance(); + jsonCacheService = container.GetInstance(); } public void Init() @@ -73,6 +76,7 @@ public void Init() InitService(hookService); InitService(moduleLoadTracker); InitService(objectStorageService); + InitService(jsonCacheService); } public void Load() @@ -91,6 +95,7 @@ public void Load() LoadService(hookService); LoadService(moduleLoadTracker); LoadService(objectStorageService); + LoadService(jsonCacheService); } public void Start() @@ -109,11 +114,13 @@ public void Start() StartService(hookService); StartService(moduleLoadTracker); StartService(objectStorageService); + StartService(jsonCacheService); } public void Unload() { Log.Info("Unloading core services..."); + UnloadService(jsonCacheService); UnloadService(objectStorageService); UnloadService(moduleLoadTracker); UnloadService(hookService); @@ -131,6 +138,7 @@ public void Unload() public void Shutdown() { + ShutdownService(jsonCacheService); ShutdownService(objectStorageService); ShutdownService(moduleLoadTracker); ShutdownService(hookService);