diff --git a/nanoFramework.Json/key.snk b/key.snk
similarity index 100%
rename from nanoFramework.Json/key.snk
rename to key.snk
diff --git a/nanoFramework.Json.Benchmark/DeserializationBenchmarks/ReferenceTypesDeserializationBenchmark.cs b/nanoFramework.Json.Benchmark/DeserializationBenchmarks/ReferenceTypesDeserializationBenchmark.cs
index 1dedf940..f6595ab6 100644
--- a/nanoFramework.Json.Benchmark/DeserializationBenchmarks/ReferenceTypesDeserializationBenchmark.cs
+++ b/nanoFramework.Json.Benchmark/DeserializationBenchmarks/ReferenceTypesDeserializationBenchmark.cs
@@ -1,182 +1,125 @@
using nanoFramework.Benchmark;
+using System;
+using System.Collections;
using nanoFramework.Benchmark.Attributes;
using nanoFramework.Json.Benchmark.Base;
using nanoFramework.Json.Test.Shared;
-using System;
-using System.Collections;
namespace nanoFramework.Json.Benchmark.DeserializationBenchmarks
{
[IterationCount(5)]
public class ReferenceTypesDeserializationBenchmark : BaseIterationBenchmark
{
- const string testString = "TestStringToSerialize";
- const short arrayElementCount = 5;
- int[] intArray = new int[arrayElementCount];
- short[] shortArray = new short[arrayElementCount];
- private Person nestedTestClass;
- private JsonTestClassComplex complexClass;
- private JsonTestTown myTown;
- private ArrayList arrayList;
-
- [Setup]
- public void Setup()
- {
- var random = new Random();
- for (int i = 0; i < arrayElementCount; i++)
- {
- intArray[i] = random.Next();
- shortArray[i] = (short)random.Next(short.MaxValue);
- }
-
- nestedTestClass = new Person()
- {
- FirstName = "John",
- LastName = "Doe",
- Birthday = new DateTime(1988, 4, 23),
- ID = 27,
- Address = null,
- ArrayProperty = new string[] { "hello", "world" },
- Friend = new Person()
- {
- FirstName = "Bob",
- LastName = "Smith",
- Birthday = new DateTime(1983, 7, 3),
- ID = 2,
- Address = "123 Some St",
- ArrayProperty = new string[] { "hi", "planet" },
- }
- };
-
- complexClass = new JsonTestClassComplex()
- {
- aInteger = 10,
- aShort = 254,
- aByte = 0x05,
- aString = "A string",
- aFloat = 1.2345f,
- aDouble = 1.2345,
- aBoolean = true,
- Timestamp = DateTime.UtcNow,
- FixedTimestamp = new DateTime(2020, 05, 01, 09, 30, 00),
- intArray = new[] { 1, 3, 5, 7, 9 },
- shortArray = new[] { (short)1, (short)3, (short)5, (short)7, (short)9 },
- byteArray = new[] { (byte)0x22, (byte)0x23, (byte)0x24, (byte)0x25, (byte)0x26 },
- stringArray = new[] { "two", "four", "six", "eight" },
- floatArray = new[] { 1.1f, 3.3f, 5.5f, 7.7f, 9.9f },
- doubleArray = new[] { 1.12345, 3.3456, 5.56789, 7.78910, 9.910111213 },
- child1 = new JsonTestClassChild() { one = 1, two = 2, three = 3 },
- Child = new JsonTestClassChild() { one = 100, two = 200, three = 300 },
- nullObject = null,
- nanFloat = float.NaN,
- nanDouble = double.NaN,
- };
-
- myTown = new JsonTestTown
- {
- TownID = 1,
- TownName = "myTown",
- CompaniesInThisTown = new JsonTestCompany[]
- {
- new JsonTestCompany { CompanyID = 1, CompanyName = "AAA Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 2, CompanyName = "BBB Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 3, CompanyName = "CCC Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 4, CompanyName = "DDD Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 5, CompanyName = "EEE Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 6, CompanyName = "FFF Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 7, CompanyName = "GGG Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 8, CompanyName = "HHH Amalgamated Industries" }
- },
- EmployeesInThisTown = new JsonTestEmployee[]
- {
- new JsonTestEmployee
- {
- EmployeeID = 1,
- EmployeeName = "John Smith",
- CurrentEmployer = new JsonTestCompany { CompanyID = 3, CompanyName = "CCC Amalgamated Industries" },
- FormerEmployers = new JsonTestCompany[]
- {
- new JsonTestCompany { CompanyID = 2, CompanyName = "BBB Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 5, CompanyName = "EEE Amalgamated Industries" },
+ const string IntArrayJson = "[405421362,1082483948,1131707654,345242860,1111968802]";
+ const string ShortArrayJson = "[12345,25463,22546,18879,12453]";
+ const string StringJson = "some string";
+ const string ArrayListJson = "[{\"stringtest\":\"hello world\",\"nulltest\":null,\"collection\":[-1,null,24.565657576,\"blah\",false]}]";
+ const string s_AzureTwinsJsonTestPayload = @"{
+ ""deviceId"": ""nanoDeepSleep"",
+ ""etag"": ""AAAAAAAAAAc="",
+ ""deviceEtag"": ""Njc2MzYzMTQ5"",
+ ""status"": ""enabled"",
+ ""statusUpdateTime"": ""0001-01-01T00:00:00Z"",
+ ""connectionState"": ""Disconnected"",
+ ""lastActivityTime"": ""2021-06-03T05:52:41.4683112Z"",
+ ""cloudToDeviceMessageCount"": 0,
+ ""authenticationType"": ""sas"",
+ ""x509Thumbprint"": {
+ ""primaryThumbprint"": null,
+ ""secondaryThumbprint"": null
+ },
+ ""modelId"": """",
+ ""version"": 381,
+ ""properties"": {
+ ""desired"": {
+ ""TimeToSleep"": 30,
+ ""$metadata"": {
+ ""$lastUpdated"": ""2021-06-03T05:37:11.8120413Z"",
+ ""$lastUpdatedVersion"": 7,
+ ""TimeToSleep"": {
+ ""$lastUpdated"": ""2021-06-03T05:37:11.8120413Z"",
+ ""$lastUpdatedVersion"": 7
}
- },
- new JsonTestEmployee
- {
- EmployeeID = 1,
- EmployeeName = "Jim Smith",
- CurrentEmployer = new JsonTestCompany { CompanyID = 7, CompanyName = "GGG Amalgamated Industries" },
- FormerEmployers = new JsonTestCompany[]
- {
- new JsonTestCompany { CompanyID = 4, CompanyName = "DDD Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 1, CompanyName = "AAA Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 6, CompanyName = "FFF Amalgamated Industries" },
+ },
+ ""$version"": 7
+ },
+ ""reported"": {
+ ""Firmware"": ""nanoFramework"",
+ ""TimeToSleep"": 30,
+ ""$metadata"": {
+ ""$lastUpdated"": ""2021-06-03T05:52:41.1232797Z"",
+ ""Firmware"": {
+ ""$lastUpdated"": ""2021-06-03T05:52:41.1232797Z""
+ },
+ ""TimeToSleep"": {
+ ""$lastUpdated"": ""2021-06-03T05:52:41.1232797Z""
}
- }
+ },
+ ""$version"": 374
}
- };
+ },
+ ""capabilities"": {
+ ""iotEdge"": false
+ }
+ }";
- arrayList = new ArrayList()
- {
- { "testString" },
- { 42 },
- { null },
- { DateTime.UtcNow },
- { TimeSpan.FromSeconds(100) }
- };
- }
+ const string NestedClassJson = "{\"FirstName\":\"John\",\"LastName\":\"Doe\",\"ArrayProperty\":[\"hello\",\"world\"],\"Address\":null,\"Birthday\":\"1988-04-23T00:00:00.0000000Z\",\"ID\":27,\"Friend\":{\"FirstName\":\"Bob\",\"LastName\":\"Smith\",\"ArrayProperty\":[\"hi\",\"planet\"],\"Address\":\"123 Some St\",\"Birthday\":\"1983-07-03T00:00:00.0000000Z\",\"ID\":2,\"Friend\":null}}";
+ const string ComplexArrayJson = "{\"TownID\":1,\"EmployeesInThisTown\":[{\"CurrentEmployer\":{\"CompanyID\":3,\"CompanyName\":\"CCC Amalgamated Industries\"},\"EmployeeID\":1,\"FormerEmployers\":[{\"CompanyID\":2,\"CompanyName\":\"BBB Amalgamated Industries\"},{\"CompanyID\":5,\"CompanyName\":\"EEE Amalgamated Industries\"}],\"EmployeeName\":\"John Smith\"},{\"CurrentEmployer\":{\"CompanyID\":7,\"CompanyName\":\"GGG Amalgamated Industries\"},\"EmployeeID\":1,\"FormerEmployers\":[{\"CompanyID\":4,\"CompanyName\":\"DDD Amalgamated Industries\"},{\"CompanyID\":1,\"CompanyName\":\"AAA Amalgamated Industries\"},{\"CompanyID\":6,\"CompanyName\":\"FFF Amalgamated Industries\"}],\"EmployeeName\":\"Jim Smith\"}],\"TownName\":\"myTown\",\"CompaniesInThisTown\":[{\"CompanyID\":1,\"CompanyName\":\"AAA Amalgamated Industries\"},{\"CompanyID\":2,\"CompanyName\":\"BBB Amalgamated Industries\"},{\"CompanyID\":3,\"CompanyName\":\"CCC Amalgamated Industries\"},{\"CompanyID\":4,\"CompanyName\":\"DDD Amalgamated Industries\"},{\"CompanyID\":5,\"CompanyName\":\"EEE Amalgamated Industries\"},{\"CompanyID\":6,\"CompanyName\":\"FFF Amalgamated Industries\"},{\"CompanyID\":7,\"CompanyName\":\"GGG Amalgamated Industries\"},{\"CompanyID\":8,\"CompanyName\":\"HHH Amalgamated Industries\"}]}";
+
+ protected override int IterationCount => 20;
[Benchmark]
public void IntArray()
{
RunInIteration(() =>
{
- JsonConvert.SerializeObject(intArray);
+ JsonConvert.DeserializeObject(IntArrayJson, typeof(int[]));
});
}
[Benchmark]
- public void ShortArray()
+ public void ArrayList()
{
RunInIteration(() =>
{
- JsonConvert.SerializeObject(shortArray);
+ JsonConvert.DeserializeObject(ArrayListJson, typeof(ArrayList));
});
}
[Benchmark]
- public void String()
+ public void ComplexObjectAzureTwinPayload()
{
- RunInIteration(() =>
- {
- JsonConvert.SerializeObject(testString);
- });
+ JsonConvert.DeserializeObject(s_AzureTwinsJsonTestPayload, typeof(TwinPayload));
}
[Benchmark]
- public void NestedClass()
+ public void ShortArray()
{
- JsonConvert.SerializeObject(nestedTestClass);
+ RunInIteration(() =>
+ {
+ JsonConvert.DeserializeObject(ShortArrayJson, typeof(short[]));
+ });
}
[Benchmark]
- public void ComplexObject()
+ public void String()
{
- JsonConvert.SerializeObject(complexClass);
+ RunInIteration(() =>
+ {
+ JsonConvert.DeserializeObject(StringJson, typeof(string));
+ });
}
[Benchmark]
- public void ComplexArrayObject()
+ public void NestedClass()
{
- JsonConvert.SerializeObject(myTown);
+ JsonConvert.DeserializeObject(NestedClassJson, typeof(Person));
}
[Benchmark]
- public void ArrayList()
+ public void ComplexArrayObject()
{
- RunInIteration(() =>
- {
- JsonConvert.SerializeObject(arrayList);
- });
+ JsonConvert.DeserializeObject(ComplexArrayJson, typeof(JsonTestTown));
}
}
-}
\ No newline at end of file
+}
diff --git a/nanoFramework.Json.Benchmark/DeserializationBenchmarks/ValueTypesDeserializationBenchmark.cs b/nanoFramework.Json.Benchmark/DeserializationBenchmarks/ValueTypesDeserializationBenchmark.cs
index ecac85bc..dee9e84a 100644
--- a/nanoFramework.Json.Benchmark/DeserializationBenchmarks/ValueTypesDeserializationBenchmark.cs
+++ b/nanoFramework.Json.Benchmark/DeserializationBenchmarks/ValueTypesDeserializationBenchmark.cs
@@ -24,7 +24,7 @@ public void Short()
RunInIteration(() =>
{
// TODO: Return value should be of type short
- var value = (int)JsonConvert.DeserializeObject(ShortJson, typeof(short));
+ JsonConvert.DeserializeObject(ShortJson, typeof(short));
});
}
@@ -34,7 +34,7 @@ public void TimeSpanT()
RunInIteration(() =>
{
// TODO: Return value should be of type timespan
- var value = JsonConvert.DeserializeObject(TimeSpanJson, typeof(TimeSpan));
+ JsonConvert.DeserializeObject(TimeSpanJson, typeof(TimeSpan));
});
}
@@ -44,7 +44,7 @@ public void Float()
RunInIteration(() =>
{
// TODO: Return value should be of type float
- var value = (double)JsonConvert.DeserializeObject(FloatJson, typeof(float));
+ JsonConvert.DeserializeObject(FloatJson, typeof(float));
});
}
@@ -53,7 +53,7 @@ public void Double()
{
RunInIteration(() =>
{
- var value = (double)JsonConvert.DeserializeObject(DoubleJson, typeof(double));
+ JsonConvert.DeserializeObject(DoubleJson, typeof(double));
});
}
@@ -62,7 +62,7 @@ public void DateTimeT()
{
RunInIteration(() =>
{
- var value = (DateTime)JsonConvert.DeserializeObject(DateTimeJson, typeof(DateTime));
+ JsonConvert.DeserializeObject(DateTimeJson, typeof(DateTime));
});
}
@@ -72,7 +72,7 @@ public void Long()
RunInIteration(() =>
{
// TODO: Return value should be of type long
- var value = (int)JsonConvert.DeserializeObject(LongJson, typeof(long));
+ JsonConvert.DeserializeObject(LongJson, typeof(long));
});
}
@@ -88,7 +88,7 @@ public void EnumBoxed()
{
RunInIteration(() =>
{
- var value = (Hashtable)JsonConvert.DeserializeObject(BoxedEnumJson, typeof(Hashtable));
+ JsonConvert.DeserializeObject(BoxedEnumJson, typeof(Hashtable));
});
}
}
diff --git a/nanoFramework.Json.Benchmark/SerializationBenchmarks/ReferenceTypesSerializationBenchmark.cs b/nanoFramework.Json.Benchmark/SerializationBenchmarks/ReferenceTypesSerializationBenchmark.cs
index 14519196..ea11e3a1 100644
--- a/nanoFramework.Json.Benchmark/SerializationBenchmarks/ReferenceTypesSerializationBenchmark.cs
+++ b/nanoFramework.Json.Benchmark/SerializationBenchmarks/ReferenceTypesSerializationBenchmark.cs
@@ -1,103 +1,82 @@
using nanoFramework.Benchmark;
-using System;
-using System.Collections;
using nanoFramework.Benchmark.Attributes;
using nanoFramework.Json.Benchmark.Base;
using nanoFramework.Json.Test.Shared;
+using System;
+using System.Collections;
namespace nanoFramework.Json.Benchmark.SerializationBenchmarks
{
[IterationCount(5)]
public class ReferenceTypesSerializationBenchmark : BaseIterationBenchmark
{
- const string IntArrayJson = "[405421362,1082483948,1131707654,345242860,1111968802]";
- const string ShortArrayJson = "[12345,25463,22546,18879,12453]";
- const string StringJson = "some string";
- const string ArrayListJson = "[{\"stringtest\":\"hello world\",\"nulltest\":null,\"collection\":[-1,null,24.565657576,\"blah\",false]}]";
- const string s_AzureTwinsJsonTestPayload = @"{
- ""deviceId"": ""nanoDeepSleep"",
- ""etag"": ""AAAAAAAAAAc="",
- ""deviceEtag"": ""Njc2MzYzMTQ5"",
- ""status"": ""enabled"",
- ""statusUpdateTime"": ""0001-01-01T00:00:00Z"",
- ""connectionState"": ""Disconnected"",
- ""lastActivityTime"": ""2021-06-03T05:52:41.4683112Z"",
- ""cloudToDeviceMessageCount"": 0,
- ""authenticationType"": ""sas"",
- ""x509Thumbprint"": {
- ""primaryThumbprint"": null,
- ""secondaryThumbprint"": null
- },
- ""modelId"": """",
- ""version"": 381,
- ""properties"": {
- ""desired"": {
- ""TimeToSleep"": 30,
- ""$metadata"": {
- ""$lastUpdated"": ""2021-06-03T05:37:11.8120413Z"",
- ""$lastUpdatedVersion"": 7,
- ""TimeToSleep"": {
- ""$lastUpdated"": ""2021-06-03T05:37:11.8120413Z"",
- ""$lastUpdatedVersion"": 7
- }
- },
- ""$version"": 7
- },
- ""reported"": {
- ""Firmware"": ""nanoFramework"",
- ""TimeToSleep"": 30,
- ""$metadata"": {
- ""$lastUpdated"": ""2021-06-03T05:52:41.1232797Z"",
- ""Firmware"": {
- ""$lastUpdated"": ""2021-06-03T05:52:41.1232797Z""
- },
- ""TimeToSleep"": {
- ""$lastUpdated"": ""2021-06-03T05:52:41.1232797Z""
- }
- },
- ""$version"": 374
- }
- },
- ""capabilities"": {
- ""iotEdge"": false
+ const string testString = "TestStringToSerialize";
+ const short arrayElementCount = 5;
+ readonly int[] intArray = new int[arrayElementCount];
+ readonly short[] shortArray = new short[arrayElementCount];
+ private Person nestedTestClass;
+ private JsonTestClassComplex complexClass;
+ private JsonTestTown myTown;
+ private ArrayList arrayList;
+
+ [Setup]
+ public void Setup()
+ {
+ var random = new Random();
+ for (int i = 0; i < arrayElementCount; i++)
+ {
+ intArray[i] = random.Next();
+ shortArray[i] = (short)random.Next(short.MaxValue);
}
- }";
- const string NestedClassJson = "{\"FirstName\":\"John\",\"LastName\":\"Doe\",\"ArrayProperty\":[\"hello\",\"world\"],\"Address\":null,\"Birthday\":\"1988-04-23T00:00:00.0000000Z\",\"ID\":27,\"Friend\":{\"FirstName\":\"Bob\",\"LastName\":\"Smith\",\"ArrayProperty\":[\"hi\",\"planet\"],\"Address\":\"123 Some St\",\"Birthday\":\"1983-07-03T00:00:00.0000000Z\",\"ID\":2,\"Friend\":null}}";
- const string ComplexArrayJson = "{\"TownID\":1,\"EmployeesInThisTown\":[{\"CurrentEmployer\":{\"CompanyID\":3,\"CompanyName\":\"CCC Amalgamated Industries\"},\"EmployeeID\":1,\"FormerEmployers\":[{\"CompanyID\":2,\"CompanyName\":\"BBB Amalgamated Industries\"},{\"CompanyID\":5,\"CompanyName\":\"EEE Amalgamated Industries\"}],\"EmployeeName\":\"John Smith\"},{\"CurrentEmployer\":{\"CompanyID\":7,\"CompanyName\":\"GGG Amalgamated Industries\"},\"EmployeeID\":1,\"FormerEmployers\":[{\"CompanyID\":4,\"CompanyName\":\"DDD Amalgamated Industries\"},{\"CompanyID\":1,\"CompanyName\":\"AAA Amalgamated Industries\"},{\"CompanyID\":6,\"CompanyName\":\"FFF Amalgamated Industries\"}],\"EmployeeName\":\"Jim Smith\"}],\"TownName\":\"myTown\",\"CompaniesInThisTown\":[{\"CompanyID\":1,\"CompanyName\":\"AAA Amalgamated Industries\"},{\"CompanyID\":2,\"CompanyName\":\"BBB Amalgamated Industries\"},{\"CompanyID\":3,\"CompanyName\":\"CCC Amalgamated Industries\"},{\"CompanyID\":4,\"CompanyName\":\"DDD Amalgamated Industries\"},{\"CompanyID\":5,\"CompanyName\":\"EEE Amalgamated Industries\"},{\"CompanyID\":6,\"CompanyName\":\"FFF Amalgamated Industries\"},{\"CompanyID\":7,\"CompanyName\":\"GGG Amalgamated Industries\"},{\"CompanyID\":8,\"CompanyName\":\"HHH Amalgamated Industries\"}]}";
+ nestedTestClass = new Person()
+ {
+ FirstName = "John",
+ LastName = "Doe",
+ Birthday = new DateTime(1988, 4, 23),
+ ID = 27,
+ Address = null,
+ ArrayProperty = new string[] { "hello", "world" },
+ Friend = new Person()
+ {
+ FirstName = "Bob",
+ LastName = "Smith",
+ Birthday = new DateTime(1983, 7, 3),
+ ID = 2,
+ Address = "123 Some St",
+ ArrayProperty = new string[] { "hi", "planet" },
+ }
+ };
- protected override int IterationCount => 20;
+ complexClass = JsonTestClassComplex.CreateTestClass();
- [Benchmark]
- public void IntArray()
- {
- RunInIteration(() =>
+ myTown = JsonTestTown.CreateTestClass();
+
+ arrayList = new ArrayList()
{
- var dserResult = (int[])JsonConvert.DeserializeObject(IntArrayJson, typeof(int[]));
- });
+ { "testString" },
+ { 42 },
+ { null },
+ { DateTime.UtcNow },
+ { TimeSpan.FromSeconds(100) }
+ };
}
[Benchmark]
- public void ArrayList()
+ public void IntArray()
{
RunInIteration(() =>
{
- var arrayList = (ArrayList)JsonConvert.DeserializeObject(ArrayListJson, typeof(ArrayList));
+ JsonConvert.SerializeObject(intArray);
});
}
- [Benchmark]
- public void ComplexObjectAzureTwinPayload()
- {
- var twinPayload = (TwinPayload)JsonConvert.DeserializeObject(s_AzureTwinsJsonTestPayload, typeof(TwinPayload));
- }
-
[Benchmark]
public void ShortArray()
{
RunInIteration(() =>
{
- var dserResult = (short[])JsonConvert.DeserializeObject(ShortArrayJson, typeof(short[]));
+ JsonConvert.SerializeObject(shortArray);
});
}
@@ -106,22 +85,35 @@ public void String()
{
RunInIteration(() =>
{
- var dserResult = (string)JsonConvert.DeserializeObject(StringJson, typeof(string));
+ JsonConvert.SerializeObject(testString);
});
}
[Benchmark]
public void NestedClass()
{
- var desrResult = (Person)JsonConvert.DeserializeObject(NestedClassJson, typeof(Person));
+ JsonConvert.SerializeObject(nestedTestClass);
+ }
+
+ [Benchmark]
+ public void ComplexObject()
+ {
+ JsonConvert.SerializeObject(complexClass);
}
- // Sometime it may throw ++++ Exception System.InvalidCastException - CLR_E_INVALID_CAST (1) ++++
- // After re run it should work
[Benchmark]
public void ComplexArrayObject()
{
- var desrResult = (JsonTestTown)JsonConvert.DeserializeObject(ComplexArrayJson, typeof(JsonTestTown));
+ JsonConvert.SerializeObject(myTown);
+ }
+
+ [Benchmark]
+ public void ArrayList()
+ {
+ RunInIteration(() =>
+ {
+ JsonConvert.SerializeObject(arrayList);
+ });
}
}
-}
+}
\ No newline at end of file
diff --git a/nanoFramework.Json.Benchmark/nanoFramework.Json.Benchmark.nfproj b/nanoFramework.Json.Benchmark/nanoFramework.Json.Benchmark.nfproj
index b2654a3a..14f5a7d8 100644
--- a/nanoFramework.Json.Benchmark/nanoFramework.Json.Benchmark.nfproj
+++ b/nanoFramework.Json.Benchmark/nanoFramework.Json.Benchmark.nfproj
@@ -21,12 +21,12 @@
-
+
-
+
diff --git a/nanoFramework.Json.Test.Shared/JsonTestClassComplex.cs b/nanoFramework.Json.Test.Shared/JsonTestClassComplex.cs
index 1403cbb1..195438e7 100644
--- a/nanoFramework.Json.Test.Shared/JsonTestClassComplex.cs
+++ b/nanoFramework.Json.Test.Shared/JsonTestClassComplex.cs
@@ -28,5 +28,32 @@ public class JsonTestClassComplex
private string dontSerializeStr = "dontPublish";
#pragma warning restore 0414
private string dontSerialize { get; set; } = "dontPublish";
+
+ internal static JsonTestClassComplex CreateTestClass()
+ {
+ return new JsonTestClassComplex()
+ {
+ aInteger = 10,
+ aShort = 254,
+ aByte = 0x05,
+ aString = "A string",
+ aFloat = 1.2345f,
+ aDouble = 1.2345,
+ aBoolean = true,
+ Timestamp = DateTime.UtcNow,
+ FixedTimestamp = new DateTime(2020, 05, 01, 09, 30, 00),
+ intArray = new[] { 1, 3, 5, 7, 9 },
+ shortArray = new[] { (short)1, (short)3, (short)5, (short)7, (short)9 },
+ byteArray = new[] { (byte)0x22, (byte)0x23, (byte)0x24, (byte)0x25, (byte)0x26 },
+ stringArray = new[] { "two", "four", "six", "eight" },
+ floatArray = new[] { 1.1f, 3.3f, 5.5f, 7.7f, 9.9f },
+ doubleArray = new[] { 1.12345, 3.3456, 5.56789, 7.78910, 9.910111213 },
+ child1 = new JsonTestClassChild() { one = 1, two = 2, three = 3 },
+ Child = new JsonTestClassChild() { one = 100, two = 200, three = 300 },
+ nullObject = null,
+ nanFloat = float.NaN,
+ nanDouble = double.NaN,
+ };
+ }
}
}
diff --git a/nanoFramework.Json.Test.Shared/JsonTestTown.cs b/nanoFramework.Json.Test.Shared/JsonTestTown.cs
index 918c25e5..7eb31d9f 100644
--- a/nanoFramework.Json.Test.Shared/JsonTestTown.cs
+++ b/nanoFramework.Json.Test.Shared/JsonTestTown.cs
@@ -8,5 +8,51 @@ public class JsonTestTown
public string TownName { get; set; }
public JsonTestCompany[] CompaniesInThisTown { get; set; }
public JsonTestEmployee[] EmployeesInThisTown { get; set; }
+
+ internal static JsonTestTown CreateTestClass()
+ {
+ return new JsonTestTown()
+ {
+ TownID = 1,
+ TownName = "myTown",
+ CompaniesInThisTown = new JsonTestCompany[]
+ {
+ new JsonTestCompany { CompanyID = 1, CompanyName = "AAA Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 2, CompanyName = "BBB Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 3, CompanyName = "CCC Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 4, CompanyName = "DDD Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 5, CompanyName = "EEE Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 6, CompanyName = "FFF Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 7, CompanyName = "GGG Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 8, CompanyName = "HHH Amalgamated Industries" }
+ },
+ EmployeesInThisTown = new JsonTestEmployee[]
+ {
+ new JsonTestEmployee
+ {
+ EmployeeID = 1,
+ EmployeeName = "John Smith",
+ CurrentEmployer = new JsonTestCompany { CompanyID = 3, CompanyName = "CCC Amalgamated Industries" },
+ FormerEmployers = new JsonTestCompany[]
+ {
+ new JsonTestCompany { CompanyID = 2, CompanyName = "BBB Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 5, CompanyName = "EEE Amalgamated Industries" },
+ }
+ },
+ new JsonTestEmployee
+ {
+ EmployeeID = 1,
+ EmployeeName = "Jim Smith",
+ CurrentEmployer = new JsonTestCompany { CompanyID = 7, CompanyName = "GGG Amalgamated Industries" },
+ FormerEmployers = new JsonTestCompany[]
+ {
+ new JsonTestCompany { CompanyID = 4, CompanyName = "DDD Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 1, CompanyName = "AAA Amalgamated Industries" },
+ new JsonTestCompany { CompanyID = 6, CompanyName = "FFF Amalgamated Industries" },
+ }
+ }
+ }
+ };
+ }
}
}
diff --git a/nanoFramework.Json.Test/Converters/BoolConverterTests.cs b/nanoFramework.Json.Test/Converters/BoolConverterTests.cs
new file mode 100644
index 00000000..e2f30725
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/BoolConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class BoolConverterTests
+ {
+ /*[TestMethod]
+ [DataRow("true", true)]
+ [DataRow("false", false)]
+ public void ToType_ShouldReturnValidData(string value, bool expectedValue)
+ {
+ var converter = new Json.Converters.BoolConverter();
+ var convertedValue = (bool)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }*/
+
+ [TestMethod]
+ [DataRow(true, "true")]
+ [DataRow(false, "false")]
+ public void BoolConverter_ToJson_Should_ReturnValidData(bool value, string expectedValue)
+ {
+ var converter = new Json.Converters.BoolConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/ByteConverterTests.cs b/nanoFramework.Json.Test/Converters/ByteConverterTests.cs
new file mode 100644
index 00000000..ec5ad333
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/ByteConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class ByteConverterTests
+ {
+ [TestMethod]
+ [DataRow("120", (byte)120)]
+ [DataRow("42", (byte)42)]
+ public void ByteConverter_ToType_ShouldReturnValidData(string value, byte expectedValue)
+ {
+ var converter = new Json.Converters.ByteConverter();
+ var convertedValue = (byte)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow((byte)120, "120")]
+ [DataRow((byte)42, "42")]
+ public void ByteConverter_ToJson_Should_ReturnValidData(byte value, string expectedValue)
+ {
+ var converter = new Json.Converters.ByteConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/ConvertersMappingTests.cs b/nanoFramework.Json.Test/Converters/ConvertersMappingTests.cs
new file mode 100644
index 00000000..4592922b
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/ConvertersMappingTests.cs
@@ -0,0 +1,90 @@
+using nanoFramework.Json.Converters;
+using nanoFramework.TestFramework;
+using System;
+using System.Text;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class ConvertersMappingTests
+ {
+ class TestConverter : IConverter
+ {
+ public string ToJson(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public object ToType(object value)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ class TestConverter2 : IConverter
+ {
+ public string ToJson(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public object ToType(object value)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [TestMethod]
+ public void ConvertersMappingT_Add_Should_AddTypeMapping()
+ {
+ ConvertersMapping.Add(typeof(IConverter), new TestConverter());
+
+ var converter = ConvertersMapping.ConversionTable[typeof(IConverter)];
+ Assert.NotNull(converter);
+
+ if (converter.GetType() != typeof(TestConverter))
+ {
+ throw new InvalidOperationException("Invalid type returned.");
+ }
+ }
+
+ [TestMethod]
+ public void ConvertersMappingT_Remove_Should_RemoveTypeMapping()
+ {
+ ConvertersMapping.Add(typeof(TestConverter), new TestConverter());
+ ConvertersMapping.Remove(typeof(TestConverter));
+
+ var converterKeys = ConvertersMapping.ConversionTable.Keys;
+ foreach (var item in converterKeys)
+ {
+ var type = (Type)item;
+ if (type == typeof(TestConverter))
+ {
+ throw new InvalidOperationException($"After removing {nameof(TestConverter)} type, it should not be in collection.");
+ }
+ }
+ }
+
+ [TestMethod]
+ public void ConvertersMappingT_Replace_ShouldReplaceMapping()
+ {
+ ConvertersMapping.Add(typeof(TestConverter2), new TestConverter());
+ ConvertersMapping.Replace(typeof(TestConverter2), new TestConverter2());
+
+ var converter = ConvertersMapping.ConversionTable[typeof(TestConverter2)];
+ Assert.NotNull(converter);
+
+ if (converter.GetType() != typeof(TestConverter2))
+ {
+ throw new InvalidOperationException("Invalid type returned.");
+ }
+ }
+
+ [Cleanup]
+ public void Cleanup()
+ {
+ ConvertersMapping.Remove(typeof(IConverter));
+ ConvertersMapping.Remove(typeof(TestConverter2));
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/DoubleConverterTests.cs b/nanoFramework.Json.Test/Converters/DoubleConverterTests.cs
new file mode 100644
index 00000000..e88e0195
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/DoubleConverterTests.cs
@@ -0,0 +1,32 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class DoubleConverterTests
+ {
+ [TestMethod]
+ [DataRow("120.0", 120.0)]
+ [DataRow("42.5", 42.5)]
+ public void DoubleConverter_ToType_ShouldReturnValidData(string value, double expectedValue)
+ {
+ var converter = new Json.Converters.DoubleConverter();
+ var convertedValue = (double)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow(120.5, "120.5")]
+ [DataRow(42.5, "42.5")]
+ [DataRow(double.NaN, "null")]
+ public void DoubleConverter_ToJson_Should_ReturnValidData(double value, string expectedValue)
+ {
+ var converter = new Json.Converters.DoubleConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/FloatConverterTests.cs b/nanoFramework.Json.Test/Converters/FloatConverterTests.cs
new file mode 100644
index 00000000..4ff47941
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/FloatConverterTests.cs
@@ -0,0 +1,32 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class FloatConverterTests
+ {
+ [TestMethod]
+ [DataRow("120.0", 120.0f)]
+ [DataRow("42.5", 42.5f)]
+ public void FloatConverter_ToType_ShouldReturnValidData(string value, float expectedValue)
+ {
+ var converter = new Json.Converters.FloatConverter();
+ var convertedValue = (float)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow(120.5f, "120.5")]
+ [DataRow(42.5f, "42.5")]
+ [DataRow(float.NaN, "null")]
+ public void FloatConverter_ToJson_Should_ReturnValidData(float value, string expectedValue)
+ {
+ var converter = new Json.Converters.FloatConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/IntConverterTests.cs b/nanoFramework.Json.Test/Converters/IntConverterTests.cs
new file mode 100644
index 00000000..db7b93eb
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/IntConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class IntConverterTests
+ {
+ [TestMethod]
+ [DataRow("120", 120)]
+ [DataRow("45", 45)]
+ public void IntConverter_ToType_ShouldReturnValidData(string value, int expectedValue)
+ {
+ var converter = new Json.Converters.IntConverter();
+ var convertedValue = (int)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow(120, "120")]
+ [DataRow(45, "45")]
+ public void IntConverter_ToJson_Should_ReturnValidData(int value, string expectedValue)
+ {
+ var converter = new Json.Converters.IntConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/LongConverterTests.cs b/nanoFramework.Json.Test/Converters/LongConverterTests.cs
new file mode 100644
index 00000000..fe3b8f63
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/LongConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class LongConverterTests
+ {
+ [TestMethod]
+ [DataRow("120", (long)120)]
+ [DataRow("45", (long)45)]
+ public void LongConverter_ToType_ShouldReturnValidData(string value, long expectedValue)
+ {
+ var converter = new Json.Converters.LongConverter();
+ var convertedValue = (long)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow((long)120, "120")]
+ [DataRow((long)45, "45")]
+ public void LongConverter_ToJson_Should_ReturnValidData(long value, string expectedValue)
+ {
+ var converter = new Json.Converters.LongConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/SByteConverterTests.cs b/nanoFramework.Json.Test/Converters/SByteConverterTests.cs
new file mode 100644
index 00000000..75f12a83
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/SByteConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class SByteConverterTests
+ {
+ [TestMethod]
+ [DataRow("120", (sbyte)120)]
+ [DataRow("42", (sbyte)42)]
+ public void SByteConverter_ToType_ShouldReturnValidData(string value, sbyte expectedValue)
+ {
+ var converter = new Json.Converters.SByteConverter();
+ var convertedValue = (sbyte)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow((sbyte)120, "120")]
+ [DataRow((sbyte)42, "42")]
+ public void SByteConverter_ToJson_Should_ReturnValidData(sbyte value, string expectedValue)
+ {
+ var converter = new Json.Converters.SByteConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/ShortConverterTests.cs b/nanoFramework.Json.Test/Converters/ShortConverterTests.cs
new file mode 100644
index 00000000..da88bd4a
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/ShortConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class ShortConverterTests
+ {
+ [TestMethod]
+ [DataRow("120", (short)120)]
+ [DataRow("45", (short)45)]
+ public void ShortConverter_ToType_ShouldReturnValidData(string value, short expectedValue)
+ {
+ var converter = new Json.Converters.ShortConverter();
+ var convertedValue = (short)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow((short)120, "120")]
+ [DataRow((short)45, "45")]
+ public void ShortConverter_ToJson_Should_ReturnValidData(short value, string expectedValue)
+ {
+ var converter = new Json.Converters.ShortConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/StringConverterTests.cs b/nanoFramework.Json.Test/Converters/StringConverterTests.cs
new file mode 100644
index 00000000..a1a1e36c
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/StringConverterTests.cs
@@ -0,0 +1,29 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class StringConverterTests
+ {
+ [TestMethod]
+ [DataRow("\"TestJson\"", "TestJson")]
+ public void StringConverter_ToType_ShouldReturnValidData(string value, string expectedValue)
+ {
+ var converter = new Json.Converters.StringConverter();
+ var convertedValue = (string)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow("TestJson", "\"TestJson\"")]
+ public void StringConverter_ToJson_Should_ReturnValidData(string value, string expectedValue)
+ {
+ var converter = new Json.Converters.StringConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/TimeSpanConverterTests.cs b/nanoFramework.Json.Test/Converters/TimeSpanConverterTests.cs
new file mode 100644
index 00000000..2f8d992e
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/TimeSpanConverterTests.cs
@@ -0,0 +1,30 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class TimeSpanConverterTests
+ {
+ [TestMethod]
+ [DataRow("10:00:00", 10)]
+ public void TimeSpanConverter_ToType_ShouldReturnValidData(string value, int expectedValueHours)
+ {
+ var converter = new Json.Converters.TimeSpanConverter();
+ var convertedValue = (TimeSpan)converter.ToType(value);
+
+ var expectedTimeSpanValue = TimeSpan.FromHours(expectedValueHours);
+ Assert.Equal(expectedTimeSpanValue.Ticks, convertedValue.Ticks);
+ }
+
+ [TestMethod]
+ [DataRow(10, "\"10:00:00\"")]
+ public void TimeSpanConverter_ToJson_Should_ReturnValidData(int valueHours, string expectedValue)
+ {
+ var converter = new Json.Converters.TimeSpanConverter();
+ var convertedValue = converter.ToJson(TimeSpan.FromHours(valueHours));
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/UIntConverterTests.cs b/nanoFramework.Json.Test/Converters/UIntConverterTests.cs
new file mode 100644
index 00000000..c25c2b6b
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/UIntConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class UIntConverterTests
+ {
+ [TestMethod]
+ [DataRow("120", (uint)120)]
+ [DataRow("45", (uint)45)]
+ public void UIntConverter_ToType_ShouldReturnValidData(string value, uint expectedValue)
+ {
+ var converter = new Json.Converters.UIntConverter();
+ var convertedValue = (uint)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow((uint)120, "120")]
+ [DataRow((uint)45, "45")]
+ public void UIntConverter_ToJson_Should_ReturnValidData(uint value, string expectedValue)
+ {
+ var converter = new Json.Converters.UIntConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/ULongConverterTests.cs b/nanoFramework.Json.Test/Converters/ULongConverterTests.cs
new file mode 100644
index 00000000..1a7d2d1f
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/ULongConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class ULongConverterTests
+ {
+ [TestMethod]
+ [DataRow("120", (ulong)120)]
+ [DataRow("45", (ulong)45)]
+ public void ULongConverter_ToType_ShouldReturnValidData(string value, ulong expectedValue)
+ {
+ var converter = new Json.Converters.ULongConverter();
+ var convertedValue = (ulong)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow((ulong)120, "120")]
+ [DataRow((ulong)45, "45")]
+ public void ULongConverter_ToJson_Should_ReturnValidData(ulong value, string expectedValue)
+ {
+ var converter = new Json.Converters.ULongConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/Converters/UShortConverterTests.cs b/nanoFramework.Json.Test/Converters/UShortConverterTests.cs
new file mode 100644
index 00000000..19343e7a
--- /dev/null
+++ b/nanoFramework.Json.Test/Converters/UShortConverterTests.cs
@@ -0,0 +1,31 @@
+using nanoFramework.TestFramework;
+using System;
+
+namespace nanoFramework.Json.Test.Converters
+{
+ [TestClass]
+ public class UShortConverterTests
+ {
+ [TestMethod]
+ [DataRow("120", (ushort)120)]
+ [DataRow("45", (ushort)45)]
+ public void UShortConverter_ToType_ShouldReturnValidData(string value, ushort expectedValue)
+ {
+ var converter = new Json.Converters.UShortConverter();
+ var convertedValue = (ushort)converter.ToType(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+
+ [TestMethod]
+ [DataRow((ushort)120, "120")]
+ [DataRow((ushort)45, "45")]
+ public void UShortConverter_ToJson_Should_ReturnValidData(ushort value, string expectedValue)
+ {
+ var converter = new Json.Converters.UShortConverter();
+ var convertedValue = converter.ToJson(value);
+
+ Assert.Equal(expectedValue, convertedValue);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/JsonCustomTypeTests.cs b/nanoFramework.Json.Test/JsonCustomTypeTests.cs
new file mode 100644
index 00000000..2fd1dc8e
--- /dev/null
+++ b/nanoFramework.Json.Test/JsonCustomTypeTests.cs
@@ -0,0 +1,60 @@
+using nanoFramework.Json.Converters;
+using nanoFramework.TestFramework;
+using System;
+using System.Text;
+
+namespace nanoFramework.Json.Test
+{
+ [TestClass]
+ public class JsonCustomTypeTests
+ {
+ private class TestObject
+ {
+ public int Value { get; set; }
+ }
+
+
+ private class CustomConverter : IConverter
+ {
+ public string ToJson(object value)
+ {
+ return "123";
+ }
+
+ public object ToType(object value)
+ {
+ return new TestObject() { Value = 321 };
+ }
+ }
+
+ [Setup]
+ public void Setup()
+ {
+ ConvertersMapping.Add(typeof(TestObject), new CustomConverter());
+ }
+
+ [Cleanup]
+ public void CleanUp()
+ {
+ ConvertersMapping.Remove(typeof(TestObject));
+ }
+
+ [TestMethod]
+ public void CustomMapping_Should_SerializeToGivenValue()
+ {
+ var obj = new TestObject() { Value = 5 };
+
+ var value = JsonConvert.SerializeObject(obj);
+
+ Assert.Equal(value, "123");
+ }
+
+ [TestMethod]
+ public void CustomMapping_Should_DeserializeToGivenValue()
+ {
+ var obj = (TestObject)JsonConvert.DeserializeObject("{\"TestObject\" : \"whatever\"}", typeof(TestObject));
+
+ Assert.Equal(obj.Value, 321);
+ }
+ }
+}
diff --git a/nanoFramework.Json.Test/JsonUnitTests.cs b/nanoFramework.Json.Test/JsonUnitTests.cs
index 91dcd9ab..222bb0a5 100644
--- a/nanoFramework.Json.Test/JsonUnitTests.cs
+++ b/nanoFramework.Json.Test/JsonUnitTests.cs
@@ -31,48 +31,7 @@ public void Can_serialize_and_deserialize_arrays_of_class_objects()
{
OutputHelper.WriteLine("Can_serialize_and_deserialize_arrays_of_class_objects() - Starting test...");
- JsonTestTown myTown = new JsonTestTown
- {
- TownID = 1,
- TownName = "myTown",
- CompaniesInThisTown = new JsonTestCompany[]
- {
- new JsonTestCompany { CompanyID = 1, CompanyName = "AAA Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 2, CompanyName = "BBB Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 3, CompanyName = "CCC Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 4, CompanyName = "DDD Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 5, CompanyName = "EEE Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 6, CompanyName = "FFF Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 7, CompanyName = "GGG Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 8, CompanyName = "HHH Amalgamated Industries" }
- },
- EmployeesInThisTown = new JsonTestEmployee[]
- {
- new JsonTestEmployee
- {
- EmployeeID = 1,
- EmployeeName = "John Smith",
- CurrentEmployer = new JsonTestCompany { CompanyID = 3, CompanyName = "CCC Amalgamated Industries" },
- FormerEmployers = new JsonTestCompany[]
- {
- new JsonTestCompany { CompanyID = 2, CompanyName = "BBB Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 5, CompanyName = "EEE Amalgamated Industries" },
- }
- },
- new JsonTestEmployee
- {
- EmployeeID = 1,
- EmployeeName = "Jim Smith",
- CurrentEmployer = new JsonTestCompany { CompanyID = 7, CompanyName = "GGG Amalgamated Industries" },
- FormerEmployers = new JsonTestCompany[]
- {
- new JsonTestCompany { CompanyID = 4, CompanyName = "DDD Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 1, CompanyName = "AAA Amalgamated Industries" },
- new JsonTestCompany { CompanyID = 6, CompanyName = "FFF Amalgamated Industries" },
- }
- }
- }
- };
+ JsonTestTown myTown = JsonTestTown.CreateTestClass();
var result = JsonConvert.SerializeObject(myTown);
JsonTestTown dserResult = (JsonTestTown)JsonConvert.DeserializeObject(result, typeof(JsonTestTown));
@@ -376,14 +335,14 @@ public void DeserialzieInvalidTimeSpan_Should_ThrowInvalidCaseException()
try
{
// The method should throw InvalidCaseException as each strArr has at least one invalid value for TimeSpan
- var _ = (JsonTestClassTimeSpan)JsonConvert.DeserializeObject(strArr[i], typeof(JsonTestClassTimeSpan));
+ JsonConvert.DeserializeObject(strArr[i], typeof(JsonTestClassTimeSpan));
// If the method above haven't throw InvalidCastException then the test should fail
- throw new Exception($"Should throw exception {nameof(InvalidCastException)}.");
+ throw new InvalidOperationException($"Should throw exception {nameof(InvalidCastException)}.");
}
catch (InvalidCastException)
{
-
+ // Deserialization should throw exception and test should not fail.
}
}
@@ -451,29 +410,7 @@ public void Can_serialize_and_deserialize_escaped_string()
public void Can_serialize_and_deserialize_complex_object()
{
OutputHelper.WriteLine("Can_serialize_and_deserialize_complex_object() - Starting test...");
- var test = new JsonTestClassComplex()
- {
- aInteger = 10,
- aShort = 254,
- aByte = 0x05,
- aString = "A string",
- aFloat = 1.2345f,
- aDouble = 1.2345,
- aBoolean = true,
- Timestamp = DateTime.UtcNow,
- FixedTimestamp = new DateTime(2020, 05, 01, 09, 30, 00),
- intArray = new[] { 1, 3, 5, 7, 9 },
- shortArray = new[] { (short)1, (short)3, (short)5, (short)7, (short)9 },
- byteArray = new[] { (byte)0x22, (byte)0x23, (byte)0x24, (byte)0x25, (byte)0x26 },
- stringArray = new[] { "two", "four", "six", "eight" },
- floatArray = new[] { 1.1f, 3.3f, 5.5f, 7.7f, 9.9f },
- doubleArray = new[] { 1.12345, 3.3456, 5.56789, 7.78910, 9.910111213 },
- child1 = new JsonTestClassChild() { one = 1, two = 2, three = 3 },
- Child = new JsonTestClassChild() { one = 100, two = 200, three = 300 },
- nullObject = null,
- nanFloat = float.NaN,
- nanDouble = double.NaN,
- };
+ var test = JsonTestClassComplex.CreateTestClass();
var result = JsonConvert.SerializeObject(test);
var dserResult = (JsonTestClassComplex)JsonConvert.DeserializeObject(result, typeof(JsonTestClassComplex));
@@ -568,7 +505,7 @@ public void Can_serialize_and_deserialize_float()
OutputHelper.WriteLine("Starting float Object Test...");
var test = new JsonTestClassFloat()
{
- aFloat = 2567.454f, //TODO Deserialized float fails when number is greater than 3-4 DP with an extra `.` at the end.
+ aFloat = 2567.454f, //BUG: Deserialized float fails when number is greater than 3-4 DP with an extra `.` at the end.
};
var result = JsonConvert.SerializeObject(test);
@@ -576,7 +513,7 @@ public void Can_serialize_and_deserialize_float()
OutputHelper.WriteLine($"After Type deserialization: {dserResult}");
- Assert.Equal(result, "{\"aFloat\":" + test.aFloat + "}", "Serialized float result is equal"); //TODO: better str handling!
+ Assert.Equal(result, "{\"aFloat\":" + test.aFloat + "}", "Serialized float result is equal");
Assert.Equal(test.aFloat, dserResult.aFloat, "Deserialized float Result is Equal");
OutputHelper.WriteLine("float Object Test Test succeeded");
@@ -618,7 +555,7 @@ public void Can_serialize_and_deserialize_double()
OutputHelper.WriteLine($"After Type deserialization: {dserResult}");
- Assert.Equal(result, "{\"aDouble\":123.45669999}", "Serialized double result is a double"); //TODO: possible conversion issue (but can happen with conversions)
+ Assert.Equal(result, "{\"aDouble\":123.45669999}", "Serialized double result is a double");
OutputHelper.WriteLine("double Object Test Test succeeded");
OutputHelper.WriteLine("");
@@ -839,7 +776,6 @@ public void CanDeserializeAzureTwinProperties_04()
Assert.NotNull(twinPayload, "Deserialization returned a null object");
Assert.Equal((string)twinPayload["authenticationType"], "sas", "authenticationType doesn't match");
- //Assert.Equal(((DateTime)twinPayload["statusUpdateTime"]).Ticks, DateTime.MinValue.Ticks, "statusUpdateTime doesn't match");
Assert.Equal((int)twinPayload["cloudToDeviceMessageCount"], 0, "cloudToDeviceMessageCount doesn't match");
Assert.Equal(((Hashtable)twinPayload["x509Thumbprint"]).Count, 2, "x509Thumbprint collection count doesn't match");
Assert.Equal((int)twinPayload["version"], 381, "version doesn't match");
@@ -1139,11 +1075,11 @@ public void DeserializeSingleTypesClassDeserialization()
Assert.Equal((short)1234, deser.OneInt16, "Int16");
Assert.Equal((ushort)5678, deser.OneUInt16, "UInt16");
Assert.Equal(-789012, deser.OneInt32, "Int32");
- Assert.Equal((uint)78912, deser.OneUInt32, "UInt32");
- Assert.Equal((long)-1234567, deser.OneInt64, "Int64");
- Assert.Equal((ulong)1234567, deser.OneUInt64, "UInt64");
+ Assert.Equal(78912, deser.OneUInt32, "UInt32");
+ Assert.Equal(-1234567, deser.OneInt64, "Int64");
+ Assert.Equal(1234567, deser.OneUInt64, "UInt64");
Assert.Equal((float)34.45, deser.OneSingle, "Single");
- Assert.Equal((double)45678.23, deser.OneDouble, "Double");
+ Assert.Equal(45678.23, deser.OneDouble, "Double");
Assert.True(deser.OneBoolean, "Boolean true");
Assert.False(deser.TwoBoolean, "Boolean false");
}
@@ -1183,9 +1119,9 @@ public void LongMaxValue()
var serInt32 = JsonConvert.SerializeObject(singleInt32);
var deserUInt64 = JsonConvert.DeserializeObject(serUInt64, typeof(SingleTypesClassDeserialization)) as SingleTypesClassDeserialization;
- var deserInt64 = JsonConvert.DeserializeObject(serInt64, typeof(SingleTypesClassDeserialization)) as SingleTypesClassDeserialization;
- var deserUInt32 = JsonConvert.DeserializeObject(serUInt32, typeof(SingleTypesClassDeserialization)) as SingleTypesClassDeserialization;
- var deserInt32 = JsonConvert.DeserializeObject(serInt32, typeof(SingleTypesClassDeserialization)) as SingleTypesClassDeserialization;
+ JsonConvert.DeserializeObject(serInt64, typeof(SingleTypesClassDeserialization));
+ JsonConvert.DeserializeObject(serUInt32, typeof(SingleTypesClassDeserialization));
+ JsonConvert.DeserializeObject(serInt32, typeof(SingleTypesClassDeserialization));
Assert.Equal(deserUInt64.OneUInt64, singleUInt64.OneUInt64);
Assert.Equal(deserUInt64.OneInt64, singleUInt64.OneInt64);
@@ -1206,10 +1142,6 @@ public void CompleHashtableArraysList()
[TestMethod]
public void SerializeCosmosDbObject_01()
{
- // TODO need to fix ToString() from string with " inside
- Assert.SkipTest("Skipping this test for now");
-
-
var valueAsJsonString = @"{""_count"":1,""Databases"":[{""_users"":""users/"",""_ts"":1644173816,""id"":""HomeAutomation"",""_rid"":""MfAzAA=="",""_colls"":""colls/"",""_etag"":""\""000020002-0000-0a00-0000-620019f80000\"""",""_self"":""dbs/MFzAA==/""}],""_rid"":null}";
CosmosDbDatabaseList dbObject = new CosmosDbDatabaseList();
diff --git a/nanoFramework.Json.Test/nanoFramework.Json.Test.nfproj b/nanoFramework.Json.Test/nanoFramework.Json.Test.nfproj
index c8e9eedc..9337471c 100644
--- a/nanoFramework.Json.Test/nanoFramework.Json.Test.nfproj
+++ b/nanoFramework.Json.Test/nanoFramework.Json.Test.nfproj
@@ -1,8 +1,5 @@
-
-
-
-
+
$(MSBuildExtensionsPath)\nanoFramework\v1.0\
@@ -24,8 +21,32 @@
true
true
+
+ true
+
+
+ ..\key.snk
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -59,7 +80,6 @@
-
diff --git a/nanoFramework.Json/Converters/BoolConverter.cs b/nanoFramework.Json/Converters/BoolConverter.cs
new file mode 100644
index 00000000..d62b2014
--- /dev/null
+++ b/nanoFramework.Json/Converters/BoolConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.ComponentModel;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class BoolConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return (bool)value ? "true" : "false";
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/ByteConverter.cs b/nanoFramework.Json/Converters/ByteConverter.cs
new file mode 100644
index 00000000..6ff163df
--- /dev/null
+++ b/nanoFramework.Json/Converters/ByteConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.ComponentModel;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class ByteConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToByte(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/CharConverter.cs b/nanoFramework.Json/Converters/CharConverter.cs
new file mode 100644
index 00000000..c4a0282d
--- /dev/null
+++ b/nanoFramework.Json/Converters/CharConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Text;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class CharConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return "\"" + value.ToString() + "\"";
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return value.ToString()[0];
+ }
+ }
+}
diff --git a/nanoFramework.Json/Converters/ConvertersMapping.cs b/nanoFramework.Json/Converters/ConvertersMapping.cs
new file mode 100644
index 00000000..d2a57e5c
--- /dev/null
+++ b/nanoFramework.Json/Converters/ConvertersMapping.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections;
+
+namespace nanoFramework.Json.Converters
+{
+ ///
+ /// Contains all converters for JSON.
+ ///
+ public static class ConvertersMapping
+ {
+ internal static readonly Hashtable ConversionTable = new Hashtable()
+ {
+ { typeof(short), new ShortConverter() },
+ { typeof(ushort), new UShortConverter() },
+ { typeof(int), new IntConverter() },
+ { typeof(uint), new UIntConverter() },
+ { typeof(long), new LongConverter() },
+ { typeof(ulong), new ULongConverter() },
+ { typeof(byte), new ByteConverter() },
+ { typeof(sbyte), new SByteConverter() },
+ { typeof(float), new FloatConverter()},
+ { typeof(double), new DoubleConverter() },
+ { typeof(bool), new BoolConverter() },
+ { typeof(string), new StringConverter() },
+ { typeof(TimeSpan), new TimeSpanConverter() },
+ { typeof(DateTime), new DateTimeConverter() },
+ { typeof(char), new CharConverter() },
+ { typeof(Guid), new GuidConverter() },
+ { typeof(DictionaryEntry), new DictionaryEntryConverter() }
+ };
+
+ ///
+ /// Adds new converter to collection to support more types.
+ ///
+ /// Type of object.
+ /// Converter instance which will be used to convert
+ public static void Add(Type type, IConverter converter)
+ {
+ ConversionTable.Add(type, converter);
+ }
+
+ ///
+ /// Remove existing type converter.
+ ///
+ /// Type of object.
+ public static void Remove(Type type)
+ {
+ ConversionTable.Remove(type);
+ }
+
+ ///
+ /// Remove and then adds converter for given type.
+ ///
+ /// Type of object.
+ /// Converter instance which will be used to convert
+ public static void Replace(Type type, IConverter converter)
+ {
+ ConversionTable.Remove(type);
+ ConversionTable.Add(type, converter);
+ }
+ }
+}
diff --git a/nanoFramework.Json/Converters/DateTimeConverter.cs b/nanoFramework.Json/Converters/DateTimeConverter.cs
new file mode 100644
index 00000000..b609d9ad
--- /dev/null
+++ b/nanoFramework.Json/Converters/DateTimeConverter.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Text;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class DateTimeConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return "\"" + DateTimeExtensions.ToIso8601((DateTime)value) + "\"";
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ // Not sure hwo this one should work
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/nanoFramework.Json/Converters/DictionaryEntryConverter.cs b/nanoFramework.Json/Converters/DictionaryEntryConverter.cs
new file mode 100644
index 00000000..b3609f6d
--- /dev/null
+++ b/nanoFramework.Json/Converters/DictionaryEntryConverter.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections;
+using System.Text;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class DictionaryEntryConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ Hashtable hashtable = new();
+
+ DictionaryEntry dic = (DictionaryEntry)value;
+ DictionaryEntry entry = dic;
+ hashtable.Add(entry.Key, entry.Value);
+
+ return JsonSerializer.SerializeIDictionary(hashtable);
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/nanoFramework.Json/Converters/DoubleConverter.cs b/nanoFramework.Json/Converters/DoubleConverter.cs
new file mode 100644
index 00000000..869226e3
--- /dev/null
+++ b/nanoFramework.Json/Converters/DoubleConverter.cs
@@ -0,0 +1,29 @@
+using System;
+using System.ComponentModel;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class DoubleConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ if (double.IsNaN((double)value))
+ {
+ return "null";
+ }
+
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToDouble(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/FloatConverter.cs b/nanoFramework.Json/Converters/FloatConverter.cs
new file mode 100644
index 00000000..769f4a38
--- /dev/null
+++ b/nanoFramework.Json/Converters/FloatConverter.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class FloatConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ if (float.IsNaN((float)value))
+ {
+ return "null";
+ }
+
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToSingle(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/GuidConverter.cs b/nanoFramework.Json/Converters/GuidConverter.cs
new file mode 100644
index 00000000..1b9e897e
--- /dev/null
+++ b/nanoFramework.Json/Converters/GuidConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Text;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class GuidConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return "\"" + value.ToString() + "\"";
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return new Guid(value.ToString());
+ }
+ }
+}
diff --git a/nanoFramework.Json/Converters/IConverter.cs b/nanoFramework.Json/Converters/IConverter.cs
new file mode 100644
index 00000000..e3717d11
--- /dev/null
+++ b/nanoFramework.Json/Converters/IConverter.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Text;
+
+namespace nanoFramework.Json.Converters
+{
+ ///
+ /// Interface for all JSON converters.
+ ///
+ public interface IConverter
+ {
+ ///
+ /// Converts JSON string to object.
+ ///
+ /// JSON value to convert from.
+ /// Object converted to type.
+ object ToType(object value);
+
+ ///
+ /// Converts object into JSON string.
+ ///
+ /// Value to convert from.
+ /// String with JSON value.
+ string ToJson(object value);
+ }
+}
diff --git a/nanoFramework.Json/Converters/IntConverter.cs b/nanoFramework.Json/Converters/IntConverter.cs
new file mode 100644
index 00000000..9f0687bd
--- /dev/null
+++ b/nanoFramework.Json/Converters/IntConverter.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class IntConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToInt32(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/LongConverter.cs b/nanoFramework.Json/Converters/LongConverter.cs
new file mode 100644
index 00000000..73c59788
--- /dev/null
+++ b/nanoFramework.Json/Converters/LongConverter.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class LongConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToInt64(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/SByteConverter.cs b/nanoFramework.Json/Converters/SByteConverter.cs
new file mode 100644
index 00000000..53bb415a
--- /dev/null
+++ b/nanoFramework.Json/Converters/SByteConverter.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class SByteConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToSByte(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/ShortConverter.cs b/nanoFramework.Json/Converters/ShortConverter.cs
new file mode 100644
index 00000000..45d653ff
--- /dev/null
+++ b/nanoFramework.Json/Converters/ShortConverter.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class ShortConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToInt16(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/StringConverter.cs b/nanoFramework.Json/Converters/StringConverter.cs
new file mode 100644
index 00000000..f67787f5
--- /dev/null
+++ b/nanoFramework.Json/Converters/StringConverter.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections;
+using System.Text;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class StringConverter : IConverter
+ {
+ internal static readonly Hashtable EscapableCharactersMapping = new Hashtable()
+ {
+ {'\n', 'n'},
+ {'\r', 'r'},
+ {'\"', '"' }
+ };
+
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return "\"" + SerializeString((string)value) + "\"";
+ }
+
+ internal static string SerializeString(string str)
+ {
+ // If the string is just fine (most are) then make a quick exit for improved performance
+ if (!StringContainsCharactersToEscape(str, false))
+ {
+ return str;
+ }
+
+ // Build a new string
+ // we know there is at least 1 char to escape
+ StringBuilder result = new(str.Length + 1);
+
+ foreach (char ch in str)
+ {
+ var charToAppend = ch;
+ if (CheckIfCharIsRequiresEscape(charToAppend))
+ {
+ result.Append('\\');
+ charToAppend = (char)EscapableCharactersMapping[charToAppend];
+ }
+
+ result.Append(charToAppend);
+ }
+
+ return result.ToString();
+ }
+
+ internal static bool CheckIfCharIsRequiresEscape(char chr)
+ {
+ foreach (var item in EscapableCharactersMapping.Keys)
+ {
+ if ((char)item == chr)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ internal static bool StringContainsCharactersToEscape(string str, bool deserializing)
+ {
+ foreach (var item in EscapableCharactersMapping.Keys)
+ {
+ var charToCheck = deserializing ? $"\\{EscapableCharactersMapping[item]}" : item.ToString();
+ if (str.IndexOf(charToCheck) >= 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ var sourceString = value.ToString();
+ //String by default has escaped \" at beggining and end, just remove them
+ var resultString = sourceString.Substring(1, sourceString.Length - 2);
+ if (StringContainsCharactersToEscape(resultString, true))
+ {
+ var newString = new StringBuilder();
+ //Last character can not be escaped, because it's last one
+ for (int i = 0; i < resultString.Length - 1; i++)
+ {
+ var curChar = resultString[i];
+ var nextChar = resultString[i + 1];
+
+ if (curChar == '\\')
+ {
+ var charToAppend = GetEscapableCharKeyBasedOnValue(nextChar);
+ newString.Append(charToAppend);
+ i++;
+ continue;
+ }
+ newString.Append(curChar);
+ }
+ //Append last character skkiped by loop
+ newString.Append(resultString[resultString.Length - 1]);
+ return newString.ToString();
+ }
+ return resultString;
+ }
+
+ private static char GetEscapableCharKeyBasedOnValue(char inputChar)
+ {
+ foreach (var item in EscapableCharactersMapping.Keys)
+ {
+ var value = (char)EscapableCharactersMapping[item];
+ if (value == inputChar)
+ {
+ return (char)item;
+ }
+ }
+ // in case inputChar is not supported
+ throw new InvalidOperationException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/TimeSpanConverter.cs b/nanoFramework.Json/Converters/TimeSpanConverter.cs
new file mode 100644
index 00000000..1d635312
--- /dev/null
+++ b/nanoFramework.Json/Converters/TimeSpanConverter.cs
@@ -0,0 +1,161 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class TimeSpanConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return "\"" + value.ToString() + "\"";
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return ConvertFromString(value.ToString());
+ }
+
+ ///
+ /// Try converting a string value to a .
+ ///
+ /// to convert.
+ /// if conversion was successful. otherwise.
+ internal static TimeSpan ConvertFromString(string value)
+ {
+ // split string value with all possible separators
+ // format is: -ddddd.HH:mm:ss.fffffff
+ var timeSpanBits = value.Split(':', '.');
+
+ // sanity check
+ if (timeSpanBits.Length == 0)
+ {
+ return TimeSpan.Zero;
+ }
+
+ // figure out where the separators are
+ int indexOfFirstDot = value.IndexOf('.');
+ int indexOfSecondDot = indexOfFirstDot > -1 ? value.IndexOf('.', indexOfFirstDot + 1) : -1;
+ int indexOfFirstColon = value.IndexOf(':');
+ int indexOfSecondColon = indexOfFirstColon > -1 ? value.IndexOf(':', indexOfFirstColon + 1) : -1;
+
+ // sanity check for separators: all have to be ahead of string start
+ if (SeparatorCheck(timeSpanBits, indexOfFirstDot, indexOfSecondDot, indexOfFirstColon, indexOfSecondColon))
+ {
+ throw new InvalidCastException();
+ }
+
+ // to have days, it has to have something before the 1st dot, or just have a single component
+ bool hasDays = (indexOfFirstDot > 0 && indexOfFirstDot < indexOfFirstColon) || timeSpanBits.Length == 1;
+ bool hasTicks = hasDays ? indexOfSecondDot > indexOfFirstDot : indexOfFirstDot > -1;
+ bool hasHours = indexOfFirstColon > 0;
+ bool hasMinutes = hasHours && indexOfFirstColon > -1;
+ bool hasSeconds = hasMinutes && indexOfSecondColon > -1;
+
+ // sanity check for ticks without other time components
+ if (hasTicks && !hasHours)
+ {
+ throw new InvalidCastException();
+ }
+
+ // let the parsing start!
+ int days = 0;
+ if (hasDays
+ && !int.TryParse(timeSpanBits[0], out days))
+ {
+ throw new InvalidCastException();
+ }
+
+ // bump the index if days component is present
+ int processIndex = hasDays ? 1 : 0;
+
+ var hours = ParseValueFromString(hasHours, timeSpanBits, ref processIndex);
+ var minutes = ParseValueFromString(hasMinutes, timeSpanBits, ref processIndex);
+ var seconds = ParseValueFromString(hasSeconds, timeSpanBits, ref processIndex);
+ var ticks = HandleTicks(timeSpanBits, hasTicks, processIndex);
+
+ // sanity check for valid ranges
+ if (IsInvalidTimeSpan(hours, minutes, seconds))
+ {
+ throw new InvalidCastException();
+ }
+
+ // we should have everything now
+ return new TimeSpan(ticks).Add(new TimeSpan(days, hours, minutes, seconds, 0));
+ }
+
+ private static int HandleTicks(string[] timeSpanBits, bool hasTicks, int processIndex)
+ {
+ if (!hasTicks || processIndex > timeSpanBits.Length)
+ {
+ return 0;
+ }
+
+ if (!int.TryParse(timeSpanBits[processIndex], out var ticks))
+ {
+ throw new InvalidCastException();
+ }
+
+ // if ticks are under 999, that's milliseconds
+ if (ticks < 1_000)
+ {
+ ticks *= 10_000;
+ }
+
+ return ticks;
+ }
+
+ private static bool SeparatorCheck(string[] timeSpanBits, int indexOfFirstDot, int indexOfSecondDot, int indexOfFirstColon, int indexOfSecondColon)
+ {
+ return timeSpanBits.Length > 1
+ && indexOfFirstDot <= 0
+ && indexOfSecondDot <= 0
+ && indexOfFirstColon <= 0
+ && indexOfSecondColon <= 0;
+ }
+
+ private static int ParseValueFromString(bool hasValue,string[] timeSpanBits, ref int processIndex)
+ {
+ if (!hasValue)
+ {
+ return 0;
+ }
+
+ if (processIndex > timeSpanBits.Length)
+ {
+ return 0;
+ }
+
+ if (!int.TryParse(timeSpanBits[processIndex++], out var value))
+ {
+ throw new InvalidCastException();
+ }
+
+ return value;
+ }
+
+ private static bool IsInvalidTimeSpan(int hour, int minutes, int seconds)
+ {
+ if (hour < 0 || hour >= 24)
+ {
+ return true;
+ }
+
+ if (minutes < 0 || minutes >= 60)
+ {
+ return true;
+ }
+
+ if (seconds < 0 || seconds >= 60)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/UIntConverter.cs b/nanoFramework.Json/Converters/UIntConverter.cs
new file mode 100644
index 00000000..8ea0de14
--- /dev/null
+++ b/nanoFramework.Json/Converters/UIntConverter.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class UIntConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToUInt32(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/ULongConverter.cs b/nanoFramework.Json/Converters/ULongConverter.cs
new file mode 100644
index 00000000..5d756f60
--- /dev/null
+++ b/nanoFramework.Json/Converters/ULongConverter.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class ULongConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToUInt64(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Converters/UShortConverter.cs b/nanoFramework.Json/Converters/UShortConverter.cs
new file mode 100644
index 00000000..13d9e618
--- /dev/null
+++ b/nanoFramework.Json/Converters/UShortConverter.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace nanoFramework.Json.Converters
+{
+ internal sealed class UShortConverter : IConverter
+ {
+ ///
+ ///
+ ///
+ public string ToJson(object value)
+ {
+ return value.ToString();
+ }
+
+ ///
+ ///
+ ///
+ public object ToType(object value)
+ {
+ return Convert.ToUInt16(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/JsonConvert.cs b/nanoFramework.Json/JsonConvert.cs
index 9f187dcb..1b428daf 100644
--- a/nanoFramework.Json/JsonConvert.cs
+++ b/nanoFramework.Json/JsonConvert.cs
@@ -5,6 +5,7 @@
//
using nanoFramework.Json;
+using nanoFramework.Json.Converters;
using System;
using System.Collections;
using System.IO;
@@ -51,62 +52,14 @@ public static object DeserializeObject(string sourceString, Type type)
{
if (type == typeof(string))
{
- return DeserializeStringObject(sourceString);
+ var stringConverter = (IConverter)ConvertersMapping.ConversionTable[typeof(string)];
+ return stringConverter.ToType(sourceString);
}
var dserResult = Deserialize(sourceString);
return PopulateObject((JsonToken)dserResult, type, "/");
}
- private static char GetEscapableCharKeyBasedOnValue(char inputChar)
- {
- foreach (var item in JsonSerializer.EscapableCharactersMapping.Keys)
- {
- var value = (char)JsonSerializer.EscapableCharactersMapping[item];
- if (value == inputChar)
- {
- return (char)item;
- }
- }
-
- // in case inputChar is not supported
- throw new InvalidOperationException();
- }
-
- private static string DeserializeStringObject(string sourceString)
- {
- //String by default has escaped \" at beggining and end, just remove them
- var resultString = sourceString.Substring(1, sourceString.Length - 2);
-
- if (JsonSerializer.StringContainsCharactersToEscape(resultString, true))
- {
- var newString = string.Empty;
-
- //Last character can not be escaped, because it's last one
- for (int i = 0; i < resultString.Length - 1; i++)
- {
- var curChar = resultString[i];
- var nextChar = resultString[i + 1];
-
- if (curChar == '\\')
- {
- var charToAppend = GetEscapableCharKeyBasedOnValue(nextChar);
- newString += charToAppend;
- i++;
- continue;
- }
-
- newString += curChar;
- }
-
- //Append last character skkiped by loop
- newString += resultString[resultString.Length - 1];
- return newString.ToString();
- }
-
- return resultString;
- }
-
#if NANOFRAMEWORK_1_0
///
@@ -151,11 +104,10 @@ private static object Deserialize(StreamReader dr)
}
#endif
-
- private static object ConvertToType(Type sourceType, Type targetType, object value)
+ internal static object ConvertToType(Type sourceType, Type targetType, object value)
{
// No need to convert if values matches
- if (sourceType.Name == targetType.Name)
+ if (sourceType == targetType)
{
return value;
}
@@ -165,50 +117,12 @@ private static object ConvertToType(Type sourceType, Type targetType, object val
return ConvertToType(sourceType, targetType.GetElementType(), value);
}
- switch (targetType.Name)
+ if (ConvertersMapping.ConversionTable.Contains(targetType))
{
- case nameof(Int16):
- return Convert.ToInt16(value.ToString());
-
- case nameof(UInt16):
- return Convert.ToUInt16(value.ToString());
-
- case nameof(Int32):
- return Convert.ToInt32(value.ToString());
-
- case nameof(UInt32):
- return Convert.ToUInt32(value.ToString());
-
- case nameof(Int64):
- return Convert.ToInt64(value.ToString());
-
- case nameof(UInt64):
- return Convert.ToUInt64(value.ToString());
-
- case nameof(Byte):
- return Convert.ToByte(value.ToString());
-
- case nameof(SByte):
- return Convert.ToSByte(value.ToString());
-
- case nameof(Single):
- return Convert.ToSingle(value.ToString());
-
- case nameof(Double):
- return Convert.ToDouble(value.ToString());
-
- case nameof(Boolean):
- return Convert.ToBoolean(Convert.ToByte(value.ToString()));
-
- case nameof(String):
- return value.ToString();
-
- case nameof(TimeSpan):
- return TimeSpanExtensions.TryConvertFromString(value.ToString());
-
- default:
- return value;
+ return ((IConverter)ConvertersMapping.ConversionTable[targetType]).ToType(value);
}
+
+ return value;
}
private static object PopulateObject(JsonToken rootToken, Type rootType, string rootPath)
@@ -229,8 +143,6 @@ private static object PopulateObject(JsonToken rootToken, Type rootType, string
if (rootElementType == null
&& rootType.FullName == "System.Collections.Hashtable")
{
- rootElementType = rootType;
-
Hashtable rootInstanceHashtable = new Hashtable();
foreach (var m in rootObject.Members)
@@ -295,9 +207,11 @@ private static object PopulateObject(JsonToken rootToken, Type rootType, string
return rootArrayList;
}
- // This is the object that gets populated and returned
- // Create rootInstance from the rootType's constructor
- object rootInstance = null;
+ if (ConvertersMapping.ConversionTable.Contains(rootType))
+ {
+ var converter = (IConverter)ConvertersMapping.ConversionTable[rootType];
+ return converter.ToType(rootObject);
+ }
// Empty array of Types - GetConstructor didn't work unless given an empty array of Type[]
Type[] types = { };
@@ -310,7 +224,9 @@ private static object PopulateObject(JsonToken rootToken, Type rootType, string
throw new DeserializationException();
}
- rootInstance = ci.Invoke(null);
+ // This is the object that gets populated and returned
+ // Create rootInstance from the rootType's constructor
+ var rootInstance = ci.Invoke(null);
// If we haven't successfully created rootInstance, bail out
if (rootInstance == null)
diff --git a/nanoFramework.Json/JsonSerializer.cs b/nanoFramework.Json/JsonSerializer.cs
index 67f6ed4b..00ee00e6 100644
--- a/nanoFramework.Json/JsonSerializer.cs
+++ b/nanoFramework.Json/JsonSerializer.cs
@@ -4,10 +4,10 @@
// See LICENSE file in the project root for full license information.
//
+using nanoFramework.Json.Converters;
using System;
using System.Collections;
using System.Reflection;
-using System.Text;
namespace nanoFramework.Json
{
@@ -16,20 +16,14 @@ namespace nanoFramework.Json
///
public class JsonSerializer
{
- internal static Hashtable EscapableCharactersMapping = new Hashtable()
- {
- {'\n', 'n'},
- {'\r', 'r'},
- {'\"', '"' }
- };
-
///
/// Convert an object to a JSON string.
///
/// The value to convert. Supported types are: , , , , , , , , , , , , , , , , and .
+ /// Is the object top in hierarchy. Default true.
/// The JSON object as a string or null when the value type is not supported.
/// For objects, only internal properties with getters are converted.
- internal static string SerializeObject(object o, bool topObject = true)
+ public static string SerializeObject(object o, bool topObject = true)
{
if (o == null)
{
@@ -45,46 +39,10 @@ internal static string SerializeObject(object o, bool topObject = true)
return $"[{SerializeObject(o, false)}]";
}
- switch (type.Name)
+ if (ConvertersMapping.ConversionTable.Contains(type))
{
- case "Boolean":
- return (bool)o ? "true" : "false";
-
- case "TimeSpan":
- case "Char":
- case "Guid":
- return "\"" + o.ToString() + "\"";
- case "String":
- return "\"" + SerializeString((string)o) + "\"";
-
- case "Single":
- if (float.IsNaN((float)o))
- {
- return "null";
- }
- return o.ToString();
-
- case "Double":
- if (double.IsNaN((double)o))
- {
- return "null";
- }
- return o.ToString();
-
- case "Decimal":
- case "Float":
- case "Byte":
- case "SByte":
- case "Int16":
- case "UInt16":
- case "Int32":
- case "UInt32":
- case "Int64":
- case "UInt64":
- return o.ToString();
-
- case "DateTime":
- return "\"" + DateTimeExtensions.ToIso8601((DateTime)o) + "\"";
+ var converter = (IConverter)ConvertersMapping.ConversionTable[type];
+ return converter.ToJson(o);
}
if (type.IsEnum)
@@ -104,64 +62,65 @@ internal static string SerializeObject(object o, bool topObject = true)
return SerializeIEnumerable(enumerable);
}
- if (type == typeof(DictionaryEntry))
+ if (type.IsClass)
{
- Hashtable hashtable = new();
-
- if (o is DictionaryEntry)
- {
- DictionaryEntry dic = (DictionaryEntry)o;
- DictionaryEntry entry = dic;
- hashtable.Add(entry.Key, entry.Value);
- }
-
- return SerializeIDictionary(hashtable);
+ return SerializeClass(o, type);
}
- if (type.IsClass)
- {
- Hashtable hashtable = new Hashtable();
+ return null;
+ }
- // Iterate through all of the methods, looking for internal GET properties
- MethodInfo[] methods = type.GetMethods();
+ private static string SerializeClass(object o, Type type)
+ {
+ Hashtable hashtable = new Hashtable();
+
+ // Iterate through all of the methods, looking for internal GET properties
+ MethodInfo[] methods = type.GetMethods();
- foreach (MethodInfo method in methods)
+ foreach (MethodInfo method in methods)
+ {
+ if (!ShouldSerializeMethod(method))
{
- // We care only about property getters when serializing
- if (!method.Name.StartsWith("get_"))
- {
- continue;
- }
+ continue;
+ }
- // Ignore abstract and virtual objects
- if (method.IsAbstract)
- {
- continue;
- }
+ object returnObject = method.Invoke(o, null);
+ hashtable.Add(method.Name.Substring(4), returnObject);
+ }
- // Ignore delegates and MethodInfos
- if ((method.ReturnType == typeof(Delegate)) ||
- (method.ReturnType == typeof(MulticastDelegate)) ||
- (method.ReturnType == typeof(MethodInfo)))
- {
- continue;
- }
+ return SerializeIDictionary(hashtable);
+ }
- // Ditto for DeclaringType
- if ((method.DeclaringType == typeof(Delegate)) ||
- (method.DeclaringType == typeof(MulticastDelegate)))
- {
- continue;
- }
+ private static bool ShouldSerializeMethod(MethodInfo method)
+ {
+ // We care only about property getters when serializing
+ if (!method.Name.StartsWith("get_"))
+ {
+ return false;
+ }
- object returnObject = method.Invoke(o, null);
- hashtable.Add(method.Name.Substring(4), returnObject);
- }
+ // Ignore abstract and virtual objects
+ if (method.IsAbstract)
+ {
+ return false;
+ }
- return SerializeIDictionary(hashtable);
+ // Ignore delegates and MethodInfos
+ if ((method.ReturnType == typeof(Delegate)) ||
+ (method.ReturnType == typeof(MulticastDelegate)) ||
+ (method.ReturnType == typeof(MethodInfo)))
+ {
+ return false;
}
- return null;
+ // Ditto for DeclaringType
+ if ((method.DeclaringType == typeof(Delegate)) ||
+ (method.DeclaringType == typeof(MulticastDelegate)))
+ {
+ return false;
+ }
+
+ return true;
}
///
@@ -212,64 +171,5 @@ internal static string SerializeIDictionary(IDictionary dictionary)
return result;
}
-
- internal static bool StringContainsCharactersToEscape(string str, bool deserializing)
- {
- foreach (var item in EscapableCharactersMapping.Keys)
- {
- var charToCheck = deserializing ? $"\\{EscapableCharactersMapping[item]}" : item.ToString();
- if (str.IndexOf(charToCheck) > 0)
- {
- return true;
- }
- }
-
- return false;
- }
-
- internal static bool CheckIfCharIsRequiresEscape(char chr)
- {
- foreach (var item in EscapableCharactersMapping.Keys)
- {
- if ((char)item == chr)
- {
- return true;
- }
- }
-
- return false;
- }
-
- ///
- /// Safely serialize a String into a JSON string value, escaping all backslash and quote characters.
- ///
- /// The string to serialize.
- /// The serialized JSON string.
- protected static string SerializeString(string str)
- {
- // If the string is just fine (most are) then make a quick exit for improved performance
- if (!StringContainsCharactersToEscape(str, false))
- {
- return str;
- }
-
- // Build a new string
- // we know there is at least 1 char to escape
- StringBuilder result = new(str.Length + 1);
-
- foreach (char ch in str)
- {
- var charToAppend = ch;
- if (CheckIfCharIsRequiresEscape(charToAppend))
- {
- result.Append('\\');
- charToAppend = (char)EscapableCharactersMapping[charToAppend];
- }
-
- result.Append(charToAppend);
- }
-
- return result.ToString();
- }
}
-}
+}
\ No newline at end of file
diff --git a/nanoFramework.Json/Properties/AssemblyInfo.cs b/nanoFramework.Json/Properties/AssemblyInfo.cs
index 79c19614..9792a154 100644
--- a/nanoFramework.Json/Properties/AssemblyInfo.cs
+++ b/nanoFramework.Json/Properties/AssemblyInfo.cs
@@ -16,3 +16,9 @@
// update this whenever the native assembly signature changes //
[assembly: AssemblyNativeVersion("0.0.0.0")]
/////////////////////////////////////////////////////////////////
+
+[assembly: InternalsVisibleTo("NFUnitTest, PublicKey="+ "00240000048000009400000006020000002400005253413100040000010001001120aa3e809b3d" +
+"a4f65e1b1f65c0a3a1bf6335c39860ca41acb3c48de278c6b63c5df38239ec1f2e32d58cb897c8" +
+"c174a5f8e78a9c0b6087d3aef373d7d0f3d9be67700fc2a5a38de1fb71b5b6f6046d841ff35abe" +
+"e2e0b0840a6291a312be184eb311baff5fef0ff6895b9a5f2253aed32fb06b819134f6bb9d5314" +
+"88a87ea2")]
\ No newline at end of file
diff --git a/nanoFramework.Json/TimeExtensions.cs b/nanoFramework.Json/TimeExtensions.cs
index a90bf966..30ebe101 100644
--- a/nanoFramework.Json/TimeExtensions.cs
+++ b/nanoFramework.Json/TimeExtensions.cs
@@ -129,14 +129,7 @@ public static string ToIso8601(DateTime dt)
///
private static bool IsNumeric(string str)
{
- foreach (char c in str)
- {
- if (!((c >= '0') && (c <= '9')))
- {
- return false;
- }
- }
- return true;
+ return int.TryParse(str, out int _);
}
///
@@ -213,120 +206,4 @@ internal static bool ConvertFromString(string value, out DateTime dateTime)
return dateTime != DateTime.MaxValue;
}
}
-
- internal static class TimeSpanExtensions
- {
- ///
- /// Try converting a string value to a .
- ///
- /// to convert.
- /// converted from .
- /// if conversion was successful. otherwise.
- internal static TimeSpan TryConvertFromString(string value)
- {
- // split string value with all possible separators
- // format is: -ddddd.HH:mm:ss.fffffff
- var timeSpanBits = value.Split(':', '.');
-
- // sanity check
- if (timeSpanBits.Length == 0)
- {
- return TimeSpan.Zero;
- }
-
- int days = 0;
- int ticks = 0;
- int hours = 0;
- int minutes = 0;
- int seconds = 0;
-
- // figure out where the separators are
- int indexOfFirstDot = value.IndexOf('.');
- int indexOfSecondDot = indexOfFirstDot > -1 ? value.IndexOf('.', indexOfFirstDot + 1) : -1;
- int indexOfFirstColon = value.IndexOf(':');
- int indexOfSecondColon = indexOfFirstColon > -1 ? value.IndexOf(':', indexOfFirstColon + 1) : -1;
-
- // sanity check for separators: all have to be ahead of string start
- if (timeSpanBits.Length > 1
- && indexOfFirstDot <= 0
- && indexOfSecondDot <= 0
- && indexOfFirstColon <= 0
- && indexOfSecondColon <= 0)
- {
- throw new InvalidCastException();
- }
-
- // to have days, it has to have something before the 1st dot, or just have a single component
- bool hasDays = (indexOfFirstDot > 0 && indexOfFirstDot < indexOfFirstColon) || timeSpanBits.Length == 1;
- bool hasTicks = hasDays ? indexOfSecondDot > indexOfFirstDot : indexOfFirstDot > -1;
- bool hasHours = indexOfFirstColon > 0;
- bool hasMinutes = hasHours && indexOfFirstColon > -1;
- bool hasSeconds = hasMinutes && indexOfSecondColon > -1;
-
- // sanity check for ticks without other time components
- if (hasTicks && !hasHours)
- {
- throw new InvalidCastException();
- }
-
- // let the parsing start!
- if (hasDays
- && !int.TryParse(timeSpanBits[0], out days))
- {
- throw new InvalidCastException();
- }
-
- // bump the index if days component is present
- int processIndex = hasDays ? 1 : 0;
-
- if (hasHours && processIndex <= timeSpanBits.Length)
- {
- if (!int.TryParse(timeSpanBits[processIndex++], out hours))
- {
- throw new InvalidCastException();
- }
- }
-
- if (hasMinutes && processIndex <= timeSpanBits.Length)
- {
- if (!int.TryParse(timeSpanBits[processIndex++], out minutes))
- {
- throw new InvalidCastException();
- }
- }
-
- if (hasSeconds && processIndex <= timeSpanBits.Length)
- {
- if (!int.TryParse(timeSpanBits[processIndex++], out seconds))
- {
- throw new InvalidCastException();
- }
- }
-
- if (hasTicks && processIndex <= timeSpanBits.Length)
- {
- if (!int.TryParse(timeSpanBits[processIndex], out ticks))
- {
- throw new InvalidCastException();
- }
-
- // if ticks are under 999, that's milliseconds
- if (ticks < 1_000)
- {
- ticks *= 10_000;
- }
- }
-
- // sanity check for valid ranges
- if ((hours >= 0 && hours < 24)
- && (minutes >= 0 && minutes < 60)
- && (seconds >= 0 && seconds < 60))
- {
- // we should have everything now
- return new TimeSpan(ticks).Add(new TimeSpan(days, hours, minutes, seconds, 0));
- }
-
- throw new InvalidCastException();
- }
- }
}
diff --git a/nanoFramework.Json/nanoFramework.Json.nfproj b/nanoFramework.Json/nanoFramework.Json.nfproj
index 84ce400f..16f48a14 100644
--- a/nanoFramework.Json/nanoFramework.Json.nfproj
+++ b/nanoFramework.Json/nanoFramework.Json.nfproj
@@ -24,13 +24,32 @@
true
- key.snk
+ ..\key.snk
false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -45,7 +64,7 @@
-
+