--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+using System.Text.Json.Serialization;
+using Xunit;
+
+namespace System.Text.Json.Tests
+{
+ internal class Person
+ {
+ public string Name { get; set; }
+
+ public DateTime BirthDate { get; set; }
+
+ public DateTime LastModified { get; set; }
+
+ [JsonIgnore]
+ public string Department { get; set; }
+ }
+
+ internal class Product
+ {
+ public string Name { get; set; }
+ public DateTime ExpiryDate { get; set;}
+ public decimal Price { get; set; }
+ public string[] Sizes { get; set; }
+ }
+
+ public class CamelCaseTests
+ {
+ private static readonly JsonSerializerOptions s_camelCaseAndIndentedOption = new JsonSerializerOptions
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
+ WriteIndented = true,
+ };
+
+ [Fact]
+ public void JsonSerializerCamelCaseSettings()
+ {
+ Person person = new Person();
+ person.BirthDate = new DateTime(2000, 11, 20, 23, 55, 44, DateTimeKind.Utc);
+ person.LastModified = new DateTime(2000, 11, 20, 23, 55, 44, DateTimeKind.Utc);
+ person.Name = "Name!";
+
+ string json = JsonSerializer.ToString(person, s_camelCaseAndIndentedOption);
+
+ Assert.Equal(@"{
+ ""name"": ""Name!"",
+ ""birthDate"": ""2000-11-20T23:55:44Z"",
+ ""lastModified"": ""2000-11-20T23:55:44Z""
+}", json);
+
+ Person deserializedPerson = JsonSerializer.Parse<Person>(json, s_camelCaseAndIndentedOption);
+
+ Assert.Equal(person.BirthDate, deserializedPerson.BirthDate);
+ Assert.Equal(person.LastModified, deserializedPerson.LastModified);
+ Assert.Equal(person.Name, deserializedPerson.Name);
+
+ json = JsonSerializer.ToString(person, new JsonSerializerOptions { WriteIndented = true });
+ Assert.Equal(@"{
+ ""Name"": ""Name!"",
+ ""BirthDate"": ""2000-11-20T23:55:44Z"",
+ ""LastModified"": ""2000-11-20T23:55:44Z""
+}", json);
+ }
+
+ [Fact]
+ public void BlogPostExample()
+ {
+ Product product = new Product
+ {
+ ExpiryDate = new DateTime(2010, 12, 20, 18, 1, 0, DateTimeKind.Utc),
+ Name = "Widget",
+ Price = 9.99m,
+ Sizes = new[] { "Small", "Medium", "Large" }
+ };
+
+ string json = JsonSerializer.ToString(product, s_camelCaseAndIndentedOption);
+
+ Assert.Equal(@"{
+ ""name"": ""Widget"",
+ ""expiryDate"": ""2010-12-20T18:01:00Z"",
+ ""price"": 9.99,
+ ""sizes"": [
+ ""Small"",
+ ""Medium"",
+ ""Large""
+ ]
+}", json);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+using System.Collections.Generic;
+using Xunit;
+using System.Text.Json.Serialization;
+
+namespace System.Text.Json.Tests
+{
+ public class CustomObjectConverterTests
+ {
+ [Fact]
+ public void SerializeAndConvertNullValue()
+ {
+ NullInterfaceTestClass initial = new NullInterfaceTestClass
+ {
+ Company = "Company!",
+ DecimalRange = new Range<decimal> { First = 0, Last = 1 },
+ Id = new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
+ IntRange = new Range<int> { First = int.MinValue, Last = int.MaxValue },
+ Year = 2010,
+ NullDecimalRange = null
+ };
+
+ string json = JsonSerializer.ToString(initial, new JsonSerializerOptions { WriteIndented = true });
+
+ Assert.Equal(@"{
+ ""Id"": ""00000001-0002-0003-0405-060708090a0b"",
+ ""Year"": 2010,
+ ""Company"": ""Company!"",
+ ""DecimalRange"": {
+ ""First"": 0,
+ ""Last"": 1
+ },
+ ""IntRange"": {
+ ""First"": -2147483648,
+ ""Last"": 2147483647
+ },
+ ""NullDecimalRange"": null
+}", json);
+ }
+
+ [Fact]
+ public void DeserializeAndConvertNullValue()
+ {
+ string json = @"{
+ ""Id"": ""00000001-0002-0003-0405-060708090a0b"",
+ ""Year"": 2010,
+ ""Company"": ""Company!"",
+ ""DecimalRange"": {
+ ""First"": 0,
+ ""Last"": 1
+ },
+ ""IntRange"": {
+ ""First"": -2147483648,
+ ""Last"": 2147483647
+ },
+ ""NullDecimalRange"": null
+}";
+
+ JsonSerializer.ToString(json, new JsonSerializerOptions { WriteIndented = true });
+
+ NullInterfaceTestClass deserialized = JsonSerializer.Parse<NullInterfaceTestClass>(json);
+
+ Assert.Equal("Company!", deserialized.Company);
+ Assert.Equal(new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), deserialized.Id);
+ Assert.Equal(0, deserialized.DecimalRange.First);
+ Assert.Equal(1, deserialized.DecimalRange.Last);
+ Assert.Equal(int.MinValue, deserialized.IntRange.First);
+ Assert.Equal(int.MaxValue, deserialized.IntRange.Last);
+ Assert.Equal(null, deserialized.NullDecimalRange);
+ Assert.Equal(2010, deserialized.Year);
+ }
+
+ [Fact]
+ public void DeserializeByteArrayFromJsonArray()
+ {
+ string json = @"{
+ ""ByteArray"": ""AAECAw=="",
+ ""NullByteArray"": null
+}";
+
+ ByteArrayClass c = JsonSerializer.Parse<ByteArrayClass>(json);
+ Assert.NotNull(c.ByteArray);
+ Assert.Equal(4, c.ByteArray.Length);
+ Assert.Equal(new byte[] { 0, 1, 2, 3 }, c.ByteArray);
+ }
+
+ [Fact]
+ public void SerializeByteArrayClass()
+ {
+ ByteArrayClass byteArrayClass = new ByteArrayClass();
+ byteArrayClass.ByteArray = s_testData;
+ byteArrayClass.NullByteArray = null;
+
+ string json = JsonSerializer.ToString(byteArrayClass, new JsonSerializerOptions { WriteIndented = true });
+
+ Assert.Equal(@"{
+ ""ByteArray"": ""VGhpcyBpcyBzb21lIHRlc3QgZGF0YSEhIQ=="",
+ ""NullByteArray"": null
+}", json);
+ }
+
+ [Fact]
+ public void DeserializeByteArrayClass()
+ {
+ string json = @"{
+ ""ByteArray"": ""VGhpcyBpcyBzb21lIHRlc3QgZGF0YSEhIQ=="",
+ ""NullByteArray"": null
+}";
+
+ ByteArrayClass byteArrayClass = JsonSerializer.Parse<ByteArrayClass>(json);
+
+ Assert.Equal(s_testData, byteArrayClass.ByteArray);
+ Assert.Equal(null, byteArrayClass.NullByteArray);
+ }
+
+ private static readonly byte[] s_testData = Encoding.UTF8.GetBytes("This is some test data!!!");
+
+ [Fact]
+ public void AssertShouldSerializeTest()
+ {
+ MyClass myClass = new MyClass
+ {
+ Value = "Foo",
+ Thing = new MyThing { Number = 456, }
+ };
+ string json = JsonSerializer.ToString(myClass);
+
+ const string expected = @"{""Value"":""Foo"",""Thing"":{""Number"":456}}";
+ Assert.Equal(expected, json);
+ }
+
+ [Fact]
+ public void AssertDoesNotDeserializeInterface()
+ {
+ const string json = @"{
+""Value"": ""A value"",
+""Thing"": {
+""Number"": 123
+}
+}";
+ NotSupportedException e = Assert.Throws<NotSupportedException>(() =>
+ {
+ JsonSerializer.Parse<List<MyClass>>(json);
+ });
+ Assert.Equal("Deserialization of interface types is not supported. Type 'System.Text.Json.Tests.IThing'", e.Message);
+ }
+ }
+
+ internal class Range<T>
+ {
+ public T First { get; set; }
+ public T Last { get; set; }
+ }
+
+ internal class NullInterfaceTestClass
+ {
+ public virtual Guid Id { get; set; }
+ public virtual int Year { get; set; }
+ public virtual string Company { get; set; }
+ public virtual Range<decimal> DecimalRange { get; set; }
+ public virtual Range<int> IntRange { get; set; }
+ public virtual Range<decimal> NullDecimalRange { get; set; }
+ }
+
+ internal class MyClass
+ {
+ public string Value { get; set; }
+
+ public IThing Thing { get; set; }
+ }
+
+ internal interface IThing
+ {
+ int Number { get; set; }
+ }
+
+ internal class MyThing : IThing
+ {
+ public int Number { get; set; }
+ }
+
+ internal class ByteArrayClass
+ {
+ public byte[] ByteArray { get; set; }
+ public byte[] NullByteArray { get; set; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+using System.Globalization;
+using Xunit;
+using System.Text.Json.Serialization;
+
+namespace System.Text.Json.Tests
+{
+ public class DateTimeConverterTests
+ {
+ internal static string GetUtcOffsetText(DateTime d)
+ {
+ TimeSpan utcOffset = TimeZoneInfo.Local.GetUtcOffset(d);
+
+ return utcOffset.Hours.ToString("+00;-00", CultureInfo.InvariantCulture) + ":" + utcOffset.Minutes.ToString("00;00", CultureInfo.InvariantCulture);
+ }
+
+ [Fact]
+ public void SerializeDateTime()
+ {
+ DateTime d = new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Utc);
+ string result;
+
+ result = JsonSerializer.ToString(d);
+ Assert.Equal(@"""2000-12-15T22:11:03.055Z""", result);
+
+ Assert.Equal(d, JsonSerializer.Parse<DateTime>(result));
+
+ d = new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Local);
+ result = JsonSerializer.ToString(d);
+ Assert.Equal(@"""2000-12-15T22:11:03.055" + GetUtcOffsetText(d) + @"""", result);
+ }
+
+ [Fact]
+ public void SerializeDateTimeOffset()
+ {
+ DateTimeOffset d = new DateTimeOffset(2000, 12, 15, 22, 11, 3, 55, TimeSpan.Zero);
+ string result;
+
+ result = JsonSerializer.ToString(d);
+ Assert.Equal(@"""2000-12-15T22:11:03.055+00:00""", result);
+
+ Assert.Equal(d, JsonSerializer.Parse<DateTimeOffset>(result));
+ }
+
+ [Fact]
+ public void DeserializeDateTimeOffset()
+ {
+ // Intentionally use an offset that is unlikely in the real world,
+ // so the test will be accurate regardless of the local time zone setting.
+ TimeSpan offset = new TimeSpan(2, 15, 0);
+ DateTimeOffset dto = new DateTimeOffset(2014, 1, 1, 0, 0, 0, 0, offset);
+
+ DateTimeOffset test = JsonSerializer.Parse<DateTimeOffset>("\"2014-01-01T00:00:00+02:15\"");
+
+ Assert.Equal(dto, test);
+ Assert.Equal(dto.ToString("o"), test.ToString("o"));
+ }
+
+ [Fact]
+ public void NullableSerializeUTC()
+ {
+ NullableDateTimeTestClass c = new NullableDateTimeTestClass();
+ c.DateTimeField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime();
+ c.DateTimeOffsetField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime();
+ c.PreField = "Pre";
+ c.PostField = "Post";
+ string json = JsonSerializer.ToString(c);
+
+ NullableDateTimeTestClass newOne = JsonSerializer.Parse<NullableDateTimeTestClass>(json);
+ Assert.Equal(newOne.DateTimeField, c.DateTimeField);
+ Assert.Equal(newOne.DateTimeOffsetField, c.DateTimeOffsetField);
+ Assert.Equal(newOne.PostField, c.PostField);
+ Assert.Equal(newOne.PreField, c.PreField);
+
+ c.DateTimeField = null;
+ c.DateTimeOffsetField = null;
+ c.PreField = "Pre";
+ c.PostField = "Post";
+ json = JsonSerializer.ToString(c);
+ Assert.Equal(@"{""PreField"":""Pre"",""DateTimeField"":null,""DateTimeOffsetField"":null,""PostField"":""Post""}", json);
+ }
+
+ [Fact]
+ public void SerializeUTC()
+ {
+ DateTimeTestClass c = new DateTimeTestClass();
+ c.DateTimeField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime();
+ c.DateTimeOffsetField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime();
+ c.PreField = "Pre";
+ c.PostField = "Post";
+ string json = JsonSerializer.ToString(c);
+
+ NullableDateTimeTestClass newOne = JsonSerializer.Parse<NullableDateTimeTestClass>(json);
+ Assert.Equal(newOne.DateTimeField, c.DateTimeField);
+ Assert.Equal(newOne.DateTimeOffsetField, c.DateTimeOffsetField);
+ Assert.Equal(newOne.PostField, c.PostField);
+ Assert.Equal(newOne.PreField, c.PreField);
+
+ //test the other edge case too (start of a year)
+ c.DateTimeField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime();
+ c.DateTimeOffsetField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime();
+ c.PreField = "Pre";
+ c.PostField = "Post";
+ json = JsonSerializer.ToString(c);
+
+ newOne = JsonSerializer.Parse<NullableDateTimeTestClass>(json);
+ Assert.Equal(newOne.DateTimeField, c.DateTimeField);
+ Assert.Equal(newOne.DateTimeOffsetField, c.DateTimeOffsetField);
+ Assert.Equal(newOne.PostField, c.PostField);
+ Assert.Equal(newOne.PreField, c.PreField);
+ }
+
+ [Fact]
+ public void BlogCodeSample()
+ {
+ Person p = new Person
+ {
+ Name = "Keith",
+ BirthDate = new DateTime(1980, 3, 8),
+ LastModified = new DateTime(2009, 4, 12, 20, 44, 55),
+ };
+
+ string jsonText = JsonSerializer.ToString(p, new JsonSerializerOptions { IgnoreNullValues = true});
+
+ Assert.Equal(@"{""Name"":""Keith"",""BirthDate"":""1980-03-08T00:00:00"",""LastModified"":""2009-04-12T20:44:55""}", jsonText);
+ }
+ }
+
+ internal class DateTimeTestClass
+ {
+ public string PreField { get; set; }
+
+ public DateTime DateTimeField { get; set; }
+
+ public DateTimeOffset DateTimeOffsetField { get; set; }
+ public string PostField { get; set; }
+ }
+
+ internal class NullableDateTimeTestClass
+ {
+ public string PreField { get; set; }
+ public DateTime? DateTimeField { get; set; }
+ public DateTimeOffset? DateTimeOffsetField { get; set; }
+ public string PostField { get; set; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using Xunit;
+using System.Text.Json.Serialization;
+
+namespace System.Text.Json.Tests
+{
+ public class EnumConverterTests
+ {
+ [Fact]
+ public static void SerializeEnumClass()
+ {
+ EnumClass enumClass = new EnumClass()
+ {
+ StoreColor = StoreColor.Red,
+ NullableStoreColor1 = StoreColor.White,
+ NullableStoreColor2 = null
+ };
+
+ string json = JsonSerializer.ToString(enumClass, new JsonSerializerOptions { WriteIndented = true });
+
+ Assert.Equal(@"{
+ ""StoreColor"": 2,
+ ""NullableStoreColor1"": 8,
+ ""NullableStoreColor2"": null
+}", json);
+ }
+
+ [Fact]
+ public static void SerializeEnumClassUndefined()
+ {
+ EnumClass enumClass = new EnumClass()
+ {
+ StoreColor = (StoreColor)1000,
+ NullableStoreColor1 = (StoreColor)1000,
+ NullableStoreColor2 = null
+ };
+
+ string json = JsonSerializer.ToString(enumClass, new JsonSerializerOptions { WriteIndented = true });
+
+ Assert.Equal(@"{
+ ""StoreColor"": 1000,
+ ""NullableStoreColor1"": 1000,
+ ""NullableStoreColor2"": null
+}", json);
+ }
+
+ [Fact]
+ public static void SerializeFlagEnum()
+ {
+ EnumClass enumClass = new EnumClass()
+ {
+ StoreColor = StoreColor.Red | StoreColor.White,
+ NullableStoreColor1 = StoreColor.White & StoreColor.Yellow,
+ NullableStoreColor2 = StoreColor.Red | StoreColor.White | StoreColor.Black
+ };
+
+ string json = JsonSerializer.ToString(enumClass, new JsonSerializerOptions { WriteIndented = true });
+
+ Assert.Equal(@"{
+ ""StoreColor"": 10,
+ ""NullableStoreColor1"": 0,
+ ""NullableStoreColor2"": 11
+}", json);
+ }
+
+ [Fact]
+ public static void SerializeNegativeFlagsEnum()
+ {
+ NegativeFlagsEnumClass negativeEnumClass = new NegativeFlagsEnumClass();
+ negativeEnumClass.Value1 = NegativeFlagsEnum.NegativeFour | NegativeFlagsEnum.NegativeTwo;
+ negativeEnumClass.Value2 = NegativeFlagsEnum.Two | NegativeFlagsEnum.Four;
+
+ string json = JsonSerializer.ToString(negativeEnumClass, new JsonSerializerOptions { WriteIndented = true });
+
+ Assert.Equal(@"{
+ ""Value1"": -2,
+ ""Value2"": 6
+}", json);
+ }
+
+ [Fact]
+ public static void SerializeNegativeEnum()
+ {
+ NegativeEnumClass negativeEnumClass = new NegativeEnumClass()
+ {
+ Value1 = NegativeEnum.Negative,
+ Value2 = (NegativeEnum)int.MinValue
+ };
+
+ string json = JsonSerializer.ToString(negativeEnumClass, new JsonSerializerOptions { WriteIndented = true });
+
+ Assert.Equal(@"{
+ ""Value1"": -1,
+ ""Value2"": -2147483648
+}", json);
+ }
+
+ [Fact]
+ public static void EnumMemberPlusFlags()
+ {
+ List<Foo> lfoo =
+ new List<Foo>
+ {
+ Foo.Bat | Foo.SerializeAsBaz,
+ Foo.FooBar,
+ Foo.Bat,
+ Foo.SerializeAsBaz,
+ Foo.FooBar | Foo.SerializeAsBaz,
+ (Foo)int.MaxValue
+ };
+
+ string json1 = JsonSerializer.ToString(lfoo, new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+
+ Assert.Equal(@"[
+ 6,
+ 1,
+ 2,
+ 4,
+ 5,
+ 2147483647
+]", json1);
+
+ IList<Foo> foos = JsonSerializer.Parse<List<Foo>>(json1);
+
+ Assert.Equal(6, foos.Count);
+ Assert.Equal(Foo.Bat | Foo.SerializeAsBaz, foos[0]);
+ Assert.Equal(Foo.FooBar, foos[1]);
+ Assert.Equal(Foo.Bat, foos[2]);
+ Assert.Equal(Foo.SerializeAsBaz, foos[3]);
+ Assert.Equal(Foo.FooBar | Foo.SerializeAsBaz, foos[4]);
+ Assert.Equal((Foo)int.MaxValue, foos[5]);
+
+ List<Bar> lbar = new List<Bar>() { Bar.FooBar, Bar.Bat, Bar.SerializeAsBaz };
+
+ string json2 = JsonSerializer.ToString(lbar, new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+
+ Assert.Equal(@"[
+ 0,
+ 1,
+ 2
+]", json2);
+
+ IList<Bar> bars = JsonSerializer.Parse<List<Bar>>(json2);
+
+ Assert.Equal(3, bars.Count);
+ Assert.Equal(Bar.FooBar, bars[0]);
+ Assert.Equal(Bar.Bat, bars[1]);
+ Assert.Equal(Bar.SerializeAsBaz, bars[2]);
+ }
+
+ [Fact]
+ public static void TestValidIntegerValue()
+ {
+ StoreColor c = JsonSerializer.Parse<StoreColor>("1");
+ Assert.Equal(c, StoreColor.Black);
+ }
+
+ [Fact]
+ public static void DuplicateNameEnumTest()
+ {
+ JsonException e = Assert.Throws<JsonException>(() =>
+ JsonSerializer.Parse<DuplicateNameEnum>("\"foo_bar\""));
+ }
+
+ [Fact]
+ public static void InvalidValueStringNumber()
+ {
+ JsonException ex = Assert.Throws<JsonException>(() =>
+ {
+ StoreColor s = JsonSerializer.Parse<StoreColor>("\"1\"");
+ });
+ }
+
+ [Fact]
+ public static void SerializeEnumWithDifferentCases()
+ {
+ string json = JsonSerializer.ToString(EnumWithDifferentCases.M);
+
+ Assert.Equal("0", json);
+
+ json = JsonSerializer.ToString(EnumWithDifferentCases.m);
+
+ Assert.Equal("1", json);
+ }
+
+ [Fact]
+ public static void DeserializeEnumWithDifferentCases()
+ {
+ EnumWithDifferentCases e = JsonSerializer.Parse<EnumWithDifferentCases>("0");
+ Assert.Equal(EnumWithDifferentCases.M, e);
+
+ e = JsonSerializer.Parse<EnumWithDifferentCases>("1");
+ Assert.Equal(EnumWithDifferentCases.m, e);
+ }
+
+ [Fact]
+ public static void SerializeEnumMemberWithDifferentCases()
+ {
+ string json = JsonSerializer.ToString(EnumMemberWithDifferentCases.Month);
+
+ Assert.Equal("0", json);
+
+ json = JsonSerializer.ToString(EnumMemberWithDifferentCases.Minute);
+
+ Assert.Equal("1", json);
+ }
+
+ [Fact]
+ public static void InvalidValueDash()
+ {
+ JsonException ex = Assert.Throws<JsonException>(() =>
+ {
+ JsonSerializer.Parse<StoreColor>("\"-\"");
+ });
+ }
+
+ [Fact]
+ public static void DeserializeNegativeEnum()
+ {
+ string json = @"{
+ ""Value1"": -1,
+ ""Value2"": -2147483648
+}";
+ NegativeEnumClass negativeEnumClass = JsonSerializer.Parse<NegativeEnumClass>(json);
+ Assert.Equal(NegativeEnum.Negative, negativeEnumClass.Value1);
+ Assert.Equal((NegativeEnum)int.MinValue, negativeEnumClass.Value2);
+ }
+
+ [Fact]
+ public static void DeserializeEnumClass()
+ {
+ string json = @"{
+ ""StoreColor"": 2,
+ ""NullableStoreColor1"": 8,
+ ""NullableStoreColor2"": null
+}";
+ EnumClass enumClass = JsonSerializer.Parse<EnumClass>(json);
+ Assert.Equal(StoreColor.Red, enumClass.StoreColor);
+ Assert.Equal(StoreColor.White, enumClass.NullableStoreColor1);
+ Assert.Equal(null, enumClass.NullableStoreColor2);
+ }
+
+ [Fact]
+ public static void DeserializeFlagEnum()
+ {
+ string json = @"{
+ ""StoreColor"": 10,
+ ""NullableStoreColor1"": 0,
+ ""NullableStoreColor2"": 11
+}";
+ EnumClass enumClass = JsonSerializer.Parse<EnumClass>(json);
+ Assert.Equal(StoreColor.Red | StoreColor.White, enumClass.StoreColor);
+ Assert.Equal((StoreColor)0, enumClass.NullableStoreColor1);
+ Assert.Equal(StoreColor.Red | StoreColor.White | StoreColor.Black, enumClass.NullableStoreColor2);
+ }
+ }
+
+ [Flags]
+ internal enum Foo
+ {
+ FooBar = 0x01,
+ Bat = 0x02,
+ SerializeAsBaz = 0x4,
+ }
+
+ internal enum Bar
+ {
+ FooBar,
+ Bat,
+ SerializeAsBaz
+ }
+
+ internal enum NegativeEnum
+ {
+ Negative = -1,
+ Zero = 0,
+ Positive = 1
+ }
+
+ [Flags]
+ internal enum NegativeFlagsEnum
+ {
+ NegativeFour = -4,
+ NegativeTwo = -2,
+ NegativeOne = -1,
+ Zero = 0,
+ One = 1,
+ Two = 2,
+ Four = 4
+ }
+
+ internal enum EnumWithDifferentCases
+ {
+ M,
+ m
+ }
+
+ internal enum EnumMemberWithDifferentCases
+ {
+ Month,
+ Minute
+ }
+
+ internal class NegativeEnumClass
+ {
+ public NegativeEnum Value1 { get; set; }
+ public NegativeEnum Value2 { get; set; }
+ }
+
+ internal class NegativeFlagsEnumClass
+ {
+ public NegativeFlagsEnum Value1 { get; set; }
+ public NegativeFlagsEnum Value2 { get; set; }
+ }
+
+ [Flags]
+ internal enum StoreColor
+ {
+ Black = 1,
+ Red = 2,
+ Yellow = 4,
+ White = 8,
+ DarkGoldenrod = 16
+ }
+
+ internal class EnumClass
+ {
+ public StoreColor StoreColor { get; set; }
+ public StoreColor NullableStoreColor1 { get; set; }
+ public StoreColor? NullableStoreColor2 { get; set; }
+ }
+
+ internal enum DuplicateNameEnum
+ {
+ [EnumMember]
+ first = 0,
+
+ [EnumMember]
+ foo_bar = 1,
+
+ [EnumMember(Value = "foo_bar")]
+ FooBar = 2,
+
+ [EnumMember]
+ foo_bar_NOT_USED = 3
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Text.Json.Serialization;
+using Xunit;
+
+namespace System.Text.Json.Tests
+{
+ public class ImmutableCollectionsTests
+ {
+ private static readonly JsonSerializerOptions s_indentedOption = new JsonSerializerOptions { WriteIndented = true };
+
+ #region List
+ [Fact]
+ public void SerializeList()
+ {
+ ImmutableList<string> data = ImmutableList.CreateRange(new List<string>
+ {
+ "One",
+ "II",
+ "3"
+ });
+
+ string json = JsonSerializer.ToString(data);
+ Assert.Equal(@"[""One"",""II"",""3""]", json);
+ }
+
+ [Fact]
+ public void DeserializeList()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+]";
+
+ ImmutableList<string> data = JsonSerializer.Parse<ImmutableList<string>>(json);
+
+ Assert.Equal(3, data.Count);
+ Assert.Equal("One", data[0]);
+ Assert.Equal("II", data[1]);
+ Assert.Equal("3", data[2]);
+ }
+
+ [Fact]
+ public void DeserializeListInterface()
+ {
+ string json = @"[
+ ""Volibear"",
+ ""Teemo"",
+ ""Katarina""
+ ]";
+
+ IImmutableList<string> champions = JsonSerializer.Parse<IImmutableList<string>>(json);
+
+ Assert.Equal(3, champions.Count);
+ Assert.Equal("Volibear", champions[0]);
+ Assert.Equal("Teemo", champions[1]);
+ Assert.Equal("Katarina", champions[2]);
+ }
+ #endregion
+
+ #region Array
+ [ActiveIssue(36643)]
+ [Fact]
+ public void SerializeArray()
+ {
+ ImmutableArray<string> data = ImmutableArray.CreateRange(new List<string>
+ {
+ "One",
+ "II",
+ "3"
+ });
+
+ string json = JsonSerializer.ToString(data, s_indentedOption);
+ Assert.Equal(@"[
+ ""One"",
+ ""II"",
+ ""3""
+]", json);
+ }
+
+ [ActiveIssue(36643)]
+ [Fact]
+ public void DeserializeArray()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+ ]";
+
+ ImmutableArray<string> data = JsonSerializer.Parse<ImmutableArray<string>>(json);
+
+ Assert.Equal(3, data.Length);
+ Assert.Equal("One", data[0]);
+ Assert.Equal("II", data[1]);
+ Assert.Equal("3", data[2]);
+ }
+
+ [ActiveIssue(36643)]
+ [Fact]
+ public void SerializeDefaultArray()
+ {
+ InvalidOperationException e = Assert.Throws<InvalidOperationException>(
+ () => JsonSerializer.ToString(default(ImmutableArray<int>), s_indentedOption));
+ Assert.Equal(e.Message, "This operation cannot be performed on a default instance of ImmutableArray<T>. Consider initializing the array, or checking the ImmutableArray<T>.IsDefault property.");
+ }
+ #endregion
+
+ #region Queue
+ [Fact]
+ public void SerializeQueue()
+ {
+ ImmutableQueue<string> data = ImmutableQueue.CreateRange(new List<string>
+ {
+ "One",
+ "II",
+ "3"
+ });
+
+ string json = JsonSerializer.ToString(data);
+ Assert.Equal(@"[""One"",""II"",""3""]", json);
+ }
+
+ [Fact]
+ public void DeserializeQueue()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+]";
+
+ ImmutableQueue<string> data = JsonSerializer.Parse<ImmutableQueue<string>>(json);
+
+ Assert.False(data.IsEmpty);
+ Assert.Equal("One", data.Peek());
+ data = data.Dequeue();
+ Assert.Equal("II", data.Peek());
+ data = data.Dequeue();
+ Assert.Equal("3", data.Peek());
+ }
+
+ [Fact]
+ public void DeserializeQueueInterface()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+]";
+
+ IImmutableQueue<string> data = JsonSerializer.Parse<IImmutableQueue<string>>(json);
+
+ Assert.False(data.IsEmpty);
+ Assert.Equal("One", data.Peek());
+ data = data.Dequeue();
+ Assert.Equal("II", data.Peek());
+ data = data.Dequeue();
+ Assert.Equal("3", data.Peek());
+ }
+ #endregion
+
+ #region Stack
+ [Fact]
+ public void SerializeStack()
+ {
+ ImmutableStack<string> data = ImmutableStack.CreateRange(new List<string>
+ {
+ "One",
+ "II",
+ "3"
+ });
+
+ string json = JsonSerializer.ToString(data);
+ Assert.Equal(@"[""3"",""II"",""One""]", json);
+ }
+
+ [Fact]
+ public void DeserializeStack()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+]";
+
+ ImmutableStack<string> data = JsonSerializer.Parse<ImmutableStack<string>>(json);
+
+ Assert.False(data.IsEmpty);
+ Assert.Equal("3", data.Peek());
+ data = data.Pop();
+ Assert.Equal("II", data.Peek());
+ data = data.Pop();
+ Assert.Equal("One", data.Peek());
+ }
+
+ [Fact]
+ public void DeserializeStackInterface()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+]";
+
+ IImmutableStack<string> data = JsonSerializer.Parse<IImmutableStack<string>>(json);
+
+ Assert.False(data.IsEmpty);
+ Assert.Equal("3", data.Peek());
+ data = data.Pop();
+ Assert.Equal("II", data.Peek());
+ data = data.Pop();
+ Assert.Equal("One", data.Peek());
+ }
+ #endregion
+
+ #region HashSet
+ [Fact]
+ public void SerializeHashSet()
+ {
+ ImmutableHashSet<string> data = ImmutableHashSet.CreateRange(new List<string>
+ {
+ "One",
+ "II",
+ "3"
+ });
+
+ string json = JsonSerializer.ToString(data, s_indentedOption);
+
+ ImmutableHashSet<string> a = JsonSerializer.Parse<ImmutableHashSet<string>>(json);
+ Assert.Equal(3, a.Count);
+ Assert.True(a.Contains("One"));
+ Assert.True(a.Contains("II"));
+ Assert.True(a.Contains("3"));
+ }
+
+ [Fact]
+ public void DeserializeHashSet()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+]";
+
+ ImmutableHashSet<string> data = JsonSerializer.Parse<ImmutableHashSet<string>>(json);
+
+ Assert.Equal(3, data.Count);
+ Assert.True(data.Contains("3"));
+ Assert.True(data.Contains("II"));
+ Assert.True(data.Contains("One"));
+ }
+
+ [Fact]
+ public void DeserializeHashSetInterface()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+]";
+
+ IImmutableSet<string> data = JsonSerializer.Parse<IImmutableSet<string>>(json);
+
+ Assert.Equal(3, data.Count);
+ Assert.True(data.Contains("3"));
+ Assert.True(data.Contains("II"));
+ Assert.True(data.Contains("One"));
+ }
+ #endregion
+
+ #region SortedSet
+ [Fact]
+ public void SerializeSortedSet()
+ {
+ ImmutableSortedSet<string> data = ImmutableSortedSet.CreateRange(new List<string>
+ {
+ "One",
+ "II",
+ "3"
+ });
+
+ string json = JsonSerializer.ToString(data);
+ Assert.Equal(@"[""3"",""II"",""One""]", json);
+ }
+
+ [Fact]
+ public void DeserializeSortedSet()
+ {
+ string json = @"[
+ ""One"",
+ ""II"",
+ ""3""
+]";
+
+ ImmutableSortedSet<string> data = JsonSerializer.Parse<ImmutableSortedSet<string>>(json);
+
+ Assert.Equal(3, data.Count);
+ Assert.True(data.Contains("3"));
+ Assert.True(data.Contains("II"));
+ Assert.True(data.Contains("One"));
+ }
+ #endregion
+
+ #region Dictionary
+ [ActiveIssue(36643)]
+ [Fact]
+ public void SerializeDictionary()
+ {
+ ImmutableDictionary<int, string> data = ImmutableDictionary.CreateRange(new Dictionary<int, string>
+ {
+ { 1, "One" },
+ { 2, "II" },
+ { 3, "3" }
+ });
+
+ string json = JsonSerializer.ToString(data, s_indentedOption);
+ ImmutableDictionary<int, string> a = JsonSerializer.Parse<ImmutableDictionary<int, string>>(json);
+ Assert.Equal(3, a.Count);
+ Assert.Equal("One", (string)a[1]);
+ Assert.Equal("II", (string)a[2]);
+ Assert.Equal("3", (string)a[3]);
+ }
+
+ [ActiveIssue(36643)]
+ [Fact]
+ public void DeserializeDictionary()
+ {
+ string json = @"{
+ ""1"": ""One"",
+ ""2"": ""II"",
+ ""3"": ""3""
+}";
+
+ ImmutableDictionary<int, string> data = JsonSerializer.Parse<ImmutableDictionary<int, string>>(json);
+
+ Assert.Equal(3, data.Count);
+ Assert.Equal("One", data[1]);
+ Assert.Equal("II", data[2]);
+ Assert.Equal("3", data[3]);
+ }
+
+ [ActiveIssue(36643)]
+ [Fact]
+ public void DeserializeDictionaryInterface()
+ {
+ string json = @"{
+ ""1"": ""One"",
+ ""2"": ""II"",
+ ""3"": ""3""
+}";
+
+ IImmutableDictionary<int, string> data = JsonSerializer.Parse<IImmutableDictionary<int, string>>(json);
+
+ Assert.Equal(3, data.Count);
+ Assert.Equal("One", data[1]);
+ Assert.Equal("II", data[2]);
+ Assert.Equal("3", data[3]);
+ }
+ #endregion
+
+ #region SortedDictionary
+ [ActiveIssue(36643)]
+ [Fact]
+ public void SerializeSortedDictionary()
+ {
+ ImmutableSortedDictionary<int, string> data = ImmutableSortedDictionary.CreateRange(new SortedDictionary<int, string>
+ {
+ { 1, "One" },
+ { 2, "II" },
+ { 3, "3" }
+ });
+
+ string json = JsonSerializer.ToString(data, s_indentedOption);
+ Assert.Equal(@"{
+ ""1"": ""One"",
+ ""2"": ""II"",
+ ""3"": ""3""
+}", json);
+ }
+
+ [ActiveIssue(36643)]
+ [Fact]
+ public void DeserializeSortedDictionary()
+ {
+ string json = @"{
+ ""1"": ""One"",
+ ""2"": ""II"",
+ ""3"": ""3""
+}";
+
+ ImmutableSortedDictionary<int, string> data = JsonSerializer.Parse<ImmutableSortedDictionary<int, string>>(json);
+
+ Assert.Equal(3, data.Count);
+ Assert.Equal("One", data[1]);
+ Assert.Equal("II", data[2]);
+ Assert.Equal("3", data[3]);
+ }
+ #endregion
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+using Xunit;
+
+namespace System.Text.Json.Tests
+{
+ public class IncompleteTestClass
+ {
+ public int Key { get; set; }
+ }
+
+ public class JsonSerializerTests
+ {
+ [Fact]
+ public void DeserializeBoolean_Null()
+ {
+ Assert.Throws<ArgumentNullException>(
+ () => JsonSerializer.Parse<IList<bool>>(@"[null]"));
+ }
+
+ [Fact]
+ public void DeserializeBoolean_DateTime()
+ {
+ Assert.Throws<JsonException>(
+ () => JsonSerializer.Parse<IList<bool>>(@"['2000-12-20T10:55:55Z']"));
+ }
+
+ [Fact]
+ public void DeserializeBoolean_BadString()
+ {
+ Assert.Throws<JsonException>(
+ () => JsonSerializer.Parse<IList<bool>>(@"['pie']"));
+ }
+
+ [Fact]
+ public void DeserializeBoolean_EmptyString()
+ {
+ Assert.Throws<JsonException>(
+ () => JsonSerializer.Parse<IList<bool>>(@"['']"));
+ }
+
+ [Fact]
+ public void IncompleteContainers()
+ {
+ JsonException e = Assert.Throws<JsonException>(() => JsonSerializer.Parse<IList<object>>("[1,"));
+ Assert.Equal(e.Message, "Expected start of a property name or value, but instead reached end of data. Path: $[1] | LineNumber: 0 | BytePositionInLine: 2.");
+
+ e = Assert.Throws<JsonException>(() => JsonSerializer.Parse<IList<int>>("[1,"));
+ Assert.Equal(e.Message, "Expected start of a property name or value, but instead reached end of data. Path: $[1] | LineNumber: 0 | BytePositionInLine: 2.");
+
+ e = Assert.Throws<JsonException>(() => JsonSerializer.Parse<IList<int>>("[1"));
+ Assert.Equal(e.Message, "'1' is an invalid end of a number. Expected a delimiter. Path: $[0] | LineNumber: 0 | BytePositionInLine: 2.");
+
+ e = Assert.Throws<JsonException>(() => JsonSerializer.Parse<IDictionary<string, int>>("{\"key\":1,"));
+ Assert.Equal(e.Message, "Expected start of a property name or value, but instead reached end of data. Path: $.key | LineNumber: 0 | BytePositionInLine: 8.");
+
+ e = Assert.Throws<JsonException>(() => JsonSerializer.Parse<IDictionary<string, int>>("{\"key\":1"));
+ Assert.Equal(e.Message, "'1' is an invalid end of a number. Expected a delimiter. Path: $.key | LineNumber: 0 | BytePositionInLine: 8.");
+
+ e = Assert.Throws<JsonException>(() => JsonSerializer.Parse<IncompleteTestClass>("{\"key\":1,"));
+ Assert.Equal(e.Message, "Expected start of a property name or value, but instead reached end of data. Path: $ | LineNumber: 0 | BytePositionInLine: 8.");
+ }
+
+ [Fact]
+ public void NewProperty()
+ {
+ Assert.Equal(@"{""IsTransient"":true}", JsonSerializer.ToString(new ChildClass { IsTransient = true }));
+
+ ChildClass childClass = JsonSerializer.Parse<ChildClass>(@"{""IsTransient"":true}");
+ Assert.Equal(true, childClass.IsTransient);
+ }
+
+ [Fact]
+ public void NewPropertyVirtual()
+ {
+ Assert.Equal(@"{""IsTransient"":true}", JsonSerializer.ToString(new ChildClassVirtual { IsTransient = true }));
+
+ ChildClassVirtual childClass = JsonSerializer.Parse<ChildClassVirtual>(@"{""IsTransient"":true}");
+ Assert.Equal(true, childClass.IsTransient);
+ }
+
+ [Fact]
+ public void DeserializeCommentTestObjectWithComments()
+ {
+ CommentTestObject o = JsonSerializer.Parse<CommentTestObject>(@"{/* Test */}", new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip });
+ Assert.Equal(false, o.A);
+
+ o = JsonSerializer.Parse<CommentTestObject>(@"{""A"": true/* Test */}", new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip });
+ Assert.Equal(true, o.A);
+ }
+
+ [Fact]
+ public void PreserveReferencesCallbackTest()
+ {
+ PersonReference p1 = new PersonReference
+ {
+ Name = "John Smith"
+ };
+ PersonReference p2 = new PersonReference
+ {
+ Name = "Mary Sue",
+ };
+
+ p1.Spouse = p2;
+ p2.Spouse = p1;
+ Assert.Throws<InvalidOperationException> (() => JsonSerializer.ToString(p1));
+ }
+ }
+
+ public class PersonReference
+ {
+ internal Guid Id { get; set; }
+ public string Name { get; set; }
+ public PersonReference Spouse { get; set; }
+ }
+
+ public class CommentTestObject
+ {
+ public bool A { get; set; }
+ }
+
+ public class ChildClassVirtual : BaseClassVirtual
+ {
+ public new virtual bool IsTransient { get; set; }
+ }
+
+ public class BaseClassVirtual
+ {
+ internal virtual bool IsTransient { get; set; }
+ }
+
+ public class BaseClass
+ {
+ internal bool IsTransient { get; set; }
+ }
+
+ public class ChildClass : BaseClass
+ {
+ public new bool IsTransient { get; set; }
+ }
+}
<Compile Include="JsonReaderStateAndOptionsTests.cs" />
<Compile Include="JsonTestHelper.cs" />
<Compile Include="JsonWriterOptionsTests.cs" />
+ <Compile Include="NewtonsoftTests\CamelCaseTests.cs" />
+ <Compile Include="NewtonsoftTests\CustomObjectConverterTests.cs" />
+ <Compile Include="NewtonsoftTests\DateTimeConverterTests.cs" />
+ <Compile Include="NewtonsoftTests\EnumConverterTests.cs" />
+ <Compile Include="NewtonsoftTests\ImmutableCollectionsTests.cs" />
+ <Compile Include="NewtonsoftTests\JsonSerializerTests.cs" />
<Compile Include="Serialization\Array.ReadTests.cs" />
<Compile Include="Serialization\Array.WriteTests.cs" />
<Compile Include="Serialization\CacheTests.cs" />