<Compile Include="System\Text\Json\Serialization\Converters\JsonValueConverterUInt64.cs" />
<Compile Include="System\Text\Json\Serialization\Converters\JsonValueConverterUri.cs" />
<Compile Include="System\Text\Json\Serialization\ExtensionDataWriteStatus.cs" />
+ <Compile Include="System\Text\Json\Serialization\ImmutableCollectionCreator.cs" />
<Compile Include="System\Text\Json\Serialization\JsonAttribute.cs" />
<Compile Include="System\Text\Json\Serialization\JsonCamelCaseNamingPolicy.cs" />
<Compile Include="System\Text\Json\Serialization\JsonClassInfo.cs" />
Type constructingType = underlyingType.Assembly.GetType(constructingTypeName);
// Create a delegate which will point to the CreateRange method.
- object createRangeDelegate;
- createRangeDelegate = options.MemberAccessorStrategy.ImmutableDictionaryCreateRange(constructingType, elementType);
+ ImmutableCollectionCreator createRangeDelegate;
+ createRangeDelegate = options.MemberAccessorStrategy.ImmutableDictionaryCreateRange(constructingType, immutableCollectionType, elementType);
// Cache the delegate
options.TryAddCreateRangeDelegate(delegateKey, createRangeDelegate);
// This converter returns enumerables in the System.Collections.Immutable namespace.
internal sealed class DefaultImmutableEnumerableConverter : JsonEnumerableConverter
{
- private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray";
+ public const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray";
public const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1";
private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList";
switch (underlyingType.FullName)
{
+ case ImmutableArrayGenericTypeName:
+ constructingTypeName = ImmutableArrayTypeName;
+ break;
case ImmutableListGenericTypeName:
case ImmutableListGenericInterfaceTypeName:
constructingTypeName = ImmutableListTypeName;
Type constructingType = underlyingType.Assembly.GetType(constructingTypeName);
// Create a delegate which will point to the CreateRange method.
- object createRangeDelegate;
- createRangeDelegate = options.MemberAccessorStrategy.ImmutableCollectionCreateRange(constructingType, elementType);
+ ImmutableCollectionCreator createRangeDelegate;
+ createRangeDelegate = options.MemberAccessorStrategy.ImmutableCollectionCreateRange(constructingType, immutableCollectionType, elementType);
// Cache the delegate
options.TryAddCreateRangeDelegate(delegateKey, createRangeDelegate);
--- /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.
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace System.Text.Json
+{
+ internal abstract class ImmutableCollectionCreator
+ {
+ public abstract void RegisterCreatorDelegateFromMethod(MethodInfo creator);
+ public abstract bool CreateImmutableEnumerable(IList items, out IEnumerable collection);
+ public abstract bool CreateImmutableDictionary(IDictionary items, out IDictionary collection);
+ }
+
+ internal sealed class ImmutableEnumerableCreator<TElement, TCollection> : ImmutableCollectionCreator
+ where TCollection : IEnumerable<TElement>
+ {
+ private Func<IEnumerable<TElement>, TCollection> _creatorDelegate;
+
+ public override void RegisterCreatorDelegateFromMethod(MethodInfo creator)
+ {
+ Debug.Assert(_creatorDelegate == null);
+ _creatorDelegate = (Func<IEnumerable<TElement>, TCollection>)creator.CreateDelegate(typeof(Func<IEnumerable<TElement>, TCollection>));
+ }
+
+ public override bool CreateImmutableEnumerable(IList items, out IEnumerable collection)
+ {
+ Debug.Assert(_creatorDelegate != null);
+ collection = _creatorDelegate(CreateGenericTElementIEnumerable(items));
+ return true;
+ }
+
+ public override bool CreateImmutableDictionary(IDictionary items, out IDictionary collection)
+ {
+ // Shouldn't be calling this method for immutable dictionaries.
+ collection = default;
+ return false;
+ }
+
+ private IEnumerable<TElement> CreateGenericTElementIEnumerable(IList sourceList)
+ {
+ foreach (object item in sourceList)
+ {
+ yield return (TElement)item;
+ }
+ }
+ }
+
+ internal sealed class ImmutableDictionaryCreator<TElement, TCollection> : ImmutableCollectionCreator
+ where TCollection : IReadOnlyDictionary<string, TElement>
+ {
+ private Func<IEnumerable<KeyValuePair<string, TElement>>, TCollection> _creatorDelegate;
+
+ public override void RegisterCreatorDelegateFromMethod(MethodInfo creator)
+ {
+ Debug.Assert(_creatorDelegate == null);
+ _creatorDelegate = (Func<IEnumerable<KeyValuePair<string, TElement>>, TCollection>)creator.CreateDelegate(
+ typeof(Func<IEnumerable<KeyValuePair<string, TElement>>, TCollection>));
+ }
+
+ public override bool CreateImmutableEnumerable(IList items, out IEnumerable collection)
+ {
+ // Shouldn't be calling this method for immutable non-dictionaries.
+ collection = default;
+ return false;
+ }
+
+ public override bool CreateImmutableDictionary(IDictionary items, out IDictionary collection)
+ {
+ Debug.Assert(_creatorDelegate != null);
+ collection = (IDictionary)_creatorDelegate(CreateGenericTElementIDictionary(items));
+ return true;
+ }
+
+ private IEnumerable<KeyValuePair<string, TElement>> CreateGenericTElementIDictionary(IDictionary sourceDictionary)
+ {
+ foreach (DictionaryEntry item in sourceDictionary)
+ {
+ yield return new KeyValuePair<string, TElement>((string)item.Key, (TElement)item.Value);
+ }
+ }
+ }
+}
// CreateRange<TRuntimePropertyType> method to create and return the desired immutable collection type.
public override IEnumerable CreateImmutableCollectionInstance(Type collectionType, string delegateKey, IList sourceList, string jsonPath, JsonSerializerOptions options)
{
- if (!options.TryGetCreateRangeDelegate(delegateKey, out object createRangeDelegateObj))
+ IEnumerable collection = null;
+
+ if (!options.TryGetCreateRangeDelegate(delegateKey, out ImmutableCollectionCreator creator) ||
+ !creator.CreateImmutableEnumerable(sourceList, out collection))
{
ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(collectionType, jsonPath);
}
- JsonSerializerOptions.ImmutableCreateRangeDelegate<TRuntimeProperty> createRangeDelegate = (
- (JsonSerializerOptions.ImmutableCreateRangeDelegate<TRuntimeProperty>)createRangeDelegateObj);
-
- return (IEnumerable)createRangeDelegate.Invoke(CreateGenericTRuntimePropertyIEnumerable(sourceList));
+ return collection;
}
// Creates an IEnumerable<TRuntimePropertyType> and populates it with the items in the
// CreateRange<TRuntimePropertyType> method to create and return the desired immutable collection type.
public override IDictionary CreateImmutableDictionaryInstance(Type collectionType, string delegateKey, IDictionary sourceDictionary, string jsonPath, JsonSerializerOptions options)
{
- if (!options.TryGetCreateRangeDelegate(delegateKey, out object createRangeDelegateObj))
+ IDictionary collection = null;
+
+ if (!options.TryGetCreateRangeDelegate(delegateKey, out ImmutableCollectionCreator creator) ||
+ !creator.CreateImmutableDictionary(sourceDictionary, out collection))
{
ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(collectionType, jsonPath);
}
- JsonSerializerOptions.ImmutableDictCreateRangeDelegate<string, TRuntimeProperty> createRangeDelegate = (
- (JsonSerializerOptions.ImmutableDictCreateRangeDelegate<string, TRuntimeProperty>)createRangeDelegateObj);
-
- return (IDictionary)createRangeDelegate.Invoke(CreateGenericIEnumerableFromDictionary(sourceDictionary));
+ return collection;
}
private IEnumerable<TRuntimeProperty> CreateGenericTRuntimePropertyIEnumerable(IList sourceList)
else
{
IList list = (IList)state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue);
- if (list == null)
+ if (list == null ||
+ // ImmutableArray<T> is a struct, so default value won't be null.
+ state.Current.JsonPropertyInfo.RuntimePropertyType.FullName.StartsWith(DefaultImmutableEnumerableConverter.ImmutableArrayGenericTypeName))
{
state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value);
}
private readonly ConcurrentDictionary<Type, JsonClassInfo> _classes = new ConcurrentDictionary<Type, JsonClassInfo>();
private readonly ConcurrentDictionary<Type, JsonPropertyInfo> _objectJsonProperties = new ConcurrentDictionary<Type, JsonPropertyInfo>();
- private static ConcurrentDictionary<string, object> s_createRangeDelegates = new ConcurrentDictionary<string, object>();
+ private static ConcurrentDictionary<string, ImmutableCollectionCreator> s_createRangeDelegates = new ConcurrentDictionary<string, ImmutableCollectionCreator>();
private MemberAccessor _memberAccessorStrategy;
private JsonNamingPolicy _dictionayKeyPolicy;
private JsonNamingPolicy _jsonPropertyNamingPolicy;
};
}
- internal delegate object ImmutableCreateRangeDelegate<T>(IEnumerable<T> items);
- internal delegate object ImmutableDictCreateRangeDelegate<TKey, TValue>(IEnumerable<KeyValuePair<TKey, TValue>> items);
-
internal JsonPropertyInfo GetJsonPropertyInfoFromClassInfo(JsonClassInfo classInfo, JsonSerializerOptions options)
{
Type objectType = classInfo.Type;
return s_createRangeDelegates.ContainsKey(key);
}
- internal bool TryGetCreateRangeDelegate(string delegateKey, out object createRangeDelegate)
+ internal bool TryGetCreateRangeDelegate(string delegateKey, out ImmutableCollectionCreator createRangeDelegate)
{
return s_createRangeDelegates.TryGetValue(delegateKey, out createRangeDelegate) && createRangeDelegate != null;
}
- internal bool TryAddCreateRangeDelegate(string key, object createRangeDelegate)
+ internal bool TryAddCreateRangeDelegate(string key, ImmutableCollectionCreator createRangeDelegate)
{
return s_createRangeDelegates.TryAdd(key, createRangeDelegate);
}
{
public abstract JsonClassInfo.ConstructorDelegate CreateConstructor(Type classType);
- public abstract object ImmutableCollectionCreateRange(Type constructingType, Type elementType);
+ public abstract ImmutableCollectionCreator ImmutableCollectionCreateRange(Type constructingType, Type collectionType, Type elementType);
- public abstract object ImmutableDictionaryCreateRange(Type constructingType, Type elementType);
+ public abstract ImmutableCollectionCreator ImmutableDictionaryCreateRange(Type constructingType, Type collectionType, Type elementType);
protected MethodInfo ImmutableCollectionCreateRangeMethod(Type constructingType, Type elementType)
{
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
+using System.Text.Json.Serialization.Converters;
namespace System.Text.Json
{
state.Current.TempEnumerableValues = converterList;
// Clear the value if present to ensure we don't confuse tempEnumerableValues with the collection.
- if (!jsonPropertyInfo.IsPropertyPolicy)
+ if (!jsonPropertyInfo.IsPropertyPolicy &&
+ !state.Current.JsonPropertyInfo.RuntimePropertyType.FullName.StartsWith(DefaultImmutableEnumerableConverter.ImmutableArrayGenericTypeName))
{
jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null);
}
}
- public override object ImmutableCollectionCreateRange(Type constructingType, Type elementType)
+ public override ImmutableCollectionCreator ImmutableCollectionCreateRange(Type constructingType, Type collectionType, Type elementType)
{
MethodInfo createRange = ImmutableCollectionCreateRangeMethod(constructingType, elementType);
return null;
}
- return createRange.CreateDelegate(
- typeof(JsonSerializerOptions.ImmutableCreateRangeDelegate<>).MakeGenericType(elementType), null);
+ Type creatorType = typeof(ImmutableEnumerableCreator<,>).MakeGenericType(elementType, collectionType);
+
+ ConstructorInfo realMethod = creatorType.GetConstructor(
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
+ binder: null,
+ Type.EmptyTypes,
+ modifiers: null);
+
+ Debug.Assert(realMethod != null);
+
+ var dynamicMethod = new DynamicMethod(
+ ConstructorInfo.ConstructorName,
+ typeof(object),
+ Type.EmptyTypes,
+ typeof(ReflectionEmitMemberAccessor).Module,
+ skipVisibility: true);
+
+ ILGenerator generator = dynamicMethod.GetILGenerator();
+ generator.Emit(OpCodes.Newobj, realMethod);
+ generator.Emit(OpCodes.Ret);
+
+ JsonClassInfo.ConstructorDelegate constructor = (JsonClassInfo.ConstructorDelegate)dynamicMethod.CreateDelegate(
+ typeof(JsonClassInfo.ConstructorDelegate));
+
+ ImmutableCollectionCreator creator = (ImmutableCollectionCreator)constructor();
+
+ creator.RegisterCreatorDelegateFromMethod(createRange);
+ return creator;
}
- public override object ImmutableDictionaryCreateRange(Type constructingType, Type elementType)
+ public override ImmutableCollectionCreator ImmutableDictionaryCreateRange(Type constructingType, Type collectionType, Type elementType)
{
MethodInfo createRange = ImmutableDictionaryCreateRangeMethod(constructingType, elementType);
return null;
}
- return createRange.CreateDelegate(
- typeof(JsonSerializerOptions.ImmutableDictCreateRangeDelegate<,>).MakeGenericType(typeof(string), elementType), null);
+ Type creatorType = typeof(ImmutableDictionaryCreator<,>).MakeGenericType(elementType, collectionType);
+
+ ConstructorInfo realMethod = creatorType.GetConstructor(
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
+ binder: null,
+ Type.EmptyTypes,
+ modifiers: null);
+
+ Debug.Assert(realMethod != null);
+
+ var dynamicMethod = new DynamicMethod(
+ ConstructorInfo.ConstructorName,
+ typeof(object),
+ Type.EmptyTypes,
+ typeof(ReflectionEmitMemberAccessor).Module,
+ skipVisibility: true);
+
+ ILGenerator generator = dynamicMethod.GetILGenerator();
+ generator.Emit(OpCodes.Newobj, realMethod);
+ generator.Emit(OpCodes.Ret);
+
+ JsonClassInfo.ConstructorDelegate constructor = (JsonClassInfo.ConstructorDelegate)dynamicMethod.CreateDelegate(
+ typeof(JsonClassInfo.ConstructorDelegate));
+
+ ImmutableCollectionCreator creator = (ImmutableCollectionCreator)constructor();
+
+ creator.RegisterCreatorDelegateFromMethod(createRange);
+ return creator;
}
public override Func<object, TProperty> CreatePropertyGetter<TClass, TProperty>(PropertyInfo propertyInfo) =>
return () => Activator.CreateInstance(type);
}
- public override object ImmutableCollectionCreateRange(Type constructingType, Type elementType)
+ public override ImmutableCollectionCreator ImmutableCollectionCreateRange(Type constructingType, Type collectionType, Type elementType)
{
MethodInfo createRange = ImmutableCollectionCreateRangeMethod(constructingType, elementType);
return null;
}
- return createRange.CreateDelegate(
- typeof(JsonSerializerOptions.ImmutableCreateRangeDelegate<>).MakeGenericType(elementType), null);
+ Type creatorType = typeof(ImmutableEnumerableCreator<,>).MakeGenericType(elementType, collectionType);
+ ConstructorInfo constructor = creatorType.GetConstructor(
+ BindingFlags.Public |
+ BindingFlags.NonPublic |
+ BindingFlags.Instance, binder: null,
+ Type.EmptyTypes,
+ modifiers: null);
+
+ ImmutableCollectionCreator creator = (ImmutableCollectionCreator)constructor.Invoke(new object[] { });
+ creator.RegisterCreatorDelegateFromMethod(createRange);
+ return creator;
}
- public override object ImmutableDictionaryCreateRange(Type constructingType, Type elementType)
+ public override ImmutableCollectionCreator ImmutableDictionaryCreateRange(Type constructingType, Type collectionType, Type elementType)
{
MethodInfo createRange = ImmutableDictionaryCreateRangeMethod(constructingType, elementType);
return null;
}
- return createRange.CreateDelegate(
- typeof(JsonSerializerOptions.ImmutableDictCreateRangeDelegate<,>).MakeGenericType(typeof(string), elementType), null);
+ Type creatorType = typeof(ImmutableDictionaryCreator<,>).MakeGenericType(elementType, collectionType);
+ ConstructorInfo constructor = creatorType.GetConstructor(
+ BindingFlags.Public |
+ BindingFlags.NonPublic |
+ BindingFlags.Instance, binder: null,
+ Type.EmptyTypes,
+ modifiers: null);
+
+ ImmutableCollectionCreator creator = (ImmutableCollectionCreator)constructor.Invoke(new object[] { });
+ creator.RegisterCreatorDelegateFromMethod(createRange);
+ return creator;
}
public override Func<object, TProperty> CreatePropertyGetter<TClass, TProperty>(PropertyInfo propertyInfo)
json = JsonSerializer.Serialize<object>(linkedlist);
Assert.Equal(ExpectedJson, json);
+ ImmutableArray<object> immutablearray = ImmutableArray.CreateRange(new List<object> { 1, true, address, null, "foo" });
+ json = JsonSerializer.Serialize(immutablearray);
+ Assert.Equal(ExpectedJson, json);
+
+ json = JsonSerializer.Serialize<object>(immutablearray);
+ Assert.Equal(ExpectedJson, json);
+
IImmutableList<object> iimmutablelist = ImmutableList.CreateRange(new List<object> { 1, true, address, null, "foo" });
json = JsonSerializer.Serialize(iimmutablelist);
Assert.Equal(ExpectedJson, json);
Assert.Contains(@"""HashSetT"":[""Hello"",""World""]", json);
Assert.Contains(@"""LinkedListT"":[""Hello"",""World""]", json);
Assert.Contains(@"""SortedSetT"":[""Hello"",""World""]", json);
+ Assert.Contains(@"""ImmutableArrayT"":[""Hello"",""World""]", json);
Assert.Contains(@"""IImmutableListT"":[""Hello"",""World""]", json);
Assert.Contains(@"""IImmutableStackT"":[""World"",""Hello""]", json);
Assert.Contains(@"""IImmutableQueueT"":[""Hello"",""World""]", json);
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
SimpleTestClass obj = JsonSerializer.Deserialize<SimpleTestClass>(@"{}", options);
+
string json = JsonSerializer.Serialize(obj, options);
Assert.Contains(@"""myInt16"":0", json);
Assert.Contains(@"""myInt32"":0", json);
namespace System.Text.Json.Serialization.Tests
{
+ public class SimpleTestClassWithImmutableArray : ITestClass
+ {
+ public ImmutableArray<string> MyStringImmutableArray { get; set; }
+
+ public static readonly string s_json = @"{""MyStringImmutableArray"":[""Hello""]}";
+
+ public void Initialize()
+ {
+ MyStringImmutableArray = ImmutableArray.CreateRange(new List<string> { "Hello" });
+ }
+
+ public void Verify()
+ {
+ Assert.Equal("Hello", MyStringImmutableArray[0]);
+ }
+ }
+
+ public class SimpleTestClassWithObjectImmutableArray : ITestClass
+ {
+ public object MyStringImmutableArray { get; set; }
+
+ public static readonly string s_json = @"{""MyStringImmutableArray"":[""Hello""]}";
+
+ public void Initialize()
+ {
+ MyStringImmutableArray = ImmutableArray.CreateRange(new List<string> { "Hello" });
+ }
+
+ public void Verify()
+ {
+ Assert.Equal("Hello", ((ImmutableArray<string>)MyStringImmutableArray)[0]);
+ }
+ }
+
public class SimpleTestClassWithIImmutableDictionaryWrapper
{
public StringToStringIImmutableDictionaryWrapper MyStringToStringImmutableDictionaryWrapper { get; set; }
public object /*HashSet<string>*/ HashSetT { get; set; }
public object /*LinkedList<string>*/ LinkedListT { get; set; }
public object /*SortedSet<string>*/ SortedSetT { get; set; }
+ public object /*ImmutableArray<string>*/ ImmutableArrayT { get; set; }
public object /*IImmutableList<string>*/ IImmutableListT { get; set; }
public object /*IImmutableStack<string>*/ IImmutableStackT { get; set; }
public object /*IImmutableQueue<string>*/ IImmutableQueueT { get; set; }
HashSetT = new HashSet<string>(new List<string> { "Hello", "World" });
LinkedListT = new LinkedList<string>(new List<string> { "Hello", "World" });
SortedSetT = new SortedSet<string>(new List<string> { "Hello", "World" });
+ ImmutableArrayT = ImmutableArray.CreateRange(new List<string> { "Hello", "World" });
IImmutableListT = ImmutableList.CreateRange(new List<string> { "Hello", "World" });
IImmutableStackT = ImmutableStack.CreateRange(new List<string> { "Hello", "World" });
IImmutableQueueT = ImmutableQueue.CreateRange(new List<string> { "Hello", "World" });
public object MyStringIImmutableQueueT { get; set; }
public object MyStringIImmutableSetT { get; set; }
public object MyStringImmutableHashSetT { get; set; }
+ public object MyStringImmutableArray { get; set; }
public object MyStringImmutableListT { get; set; }
public object MyStringImmutableStackT { get; set; }
public object MyStringImmutablQueueT { get; set; }
public class TestClassWithObjectImmutableTypes : ITestClass
{
+ public ImmutableArray<SimpleTestClass> MyImmutableArray { get; set; }
public IImmutableList<SimpleTestClass> MyIImmutableList { get; set; }
public IImmutableStack<SimpleTestClass> MyIImmutableStack { get; set; }
public IImmutableQueue<SimpleTestClass> MyIImmutableQueue { get; set; }
public static readonly byte[] s_data = Encoding.UTF8.GetBytes(
@"{" +
+ @"""MyImmutableArray"":[" +
+ SimpleTestClass.s_json + "," +
+ SimpleTestClass.s_json +
+ @"]," +
@"""MyIImmutableList"":[" +
SimpleTestClass.s_json + "," +
SimpleTestClass.s_json +
SimpleTestClass obj2 = new SimpleTestClass();
obj2.Initialize();
+ MyImmutableArray = ImmutableArray.CreateRange(new List<SimpleTestClass> { obj1, obj2 });
+ }
+ {
+ SimpleTestClass obj1 = new SimpleTestClass();
+ obj1.Initialize();
+
+ SimpleTestClass obj2 = new SimpleTestClass();
+ obj2.Initialize();
+
MyIImmutableList = ImmutableList.CreateRange(new List<SimpleTestClass> { obj1, obj2 });
}
{
public void Verify()
{
+ Assert.Equal(2, MyImmutableArray.Length);
+ foreach (SimpleTestClass data in MyImmutableArray)
+ {
+ data.Verify();
+ }
+
Assert.Equal(2, MyIImmutableList.Count);
foreach (SimpleTestClass data in MyIImmutableList)
{
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
+using System.Text.Json.Tests;
using Xunit;
namespace System.Text.Json.Serialization.Tests
public static partial class ValueTests
{
[Fact]
+ public static void ReadImmutableArrayOfImmutableArray()
+ {
+ ImmutableArray<ImmutableArray<int>> result = JsonSerializer.Deserialize<ImmutableArray<ImmutableArray<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+ int expected = 1;
+
+ foreach (ImmutableArray<int> l in result)
+ {
+ foreach (int i in l)
+ {
+ Assert.Equal(expected++, i);
+ }
+ }
+ }
+
+ [Fact]
+ public static void ReadImmutableArrayOfArray()
+ {
+ ImmutableArray<int[]> result = JsonSerializer.Deserialize<ImmutableArray<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+ int expected = 1;
+
+ foreach (int[] arr in result)
+ {
+ foreach (int i in arr)
+ {
+ Assert.Equal(expected++, i);
+ }
+ }
+ }
+
+ [Fact]
+ public static void ReadArrayOfImmutableArray()
+ {
+ ImmutableArray<int>[] result = JsonSerializer.Deserialize<ImmutableArray<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+ int expected = 1;
+
+ foreach (ImmutableArray<int> l in result)
+ {
+ foreach (int i in l)
+ {
+ Assert.Equal(expected++, i);
+ }
+ }
+ }
+
+ [Fact]
+ public static void ReadSimpleImmutableArray()
+ {
+ ImmutableArray<int> result = JsonSerializer.Deserialize<ImmutableArray<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+ int expected = 1;
+
+ foreach (int i in result)
+ {
+ Assert.Equal(expected++, i);
+ }
+
+ result = JsonSerializer.Deserialize<ImmutableArray<int>>(Encoding.UTF8.GetBytes(@"[]"));
+ Assert.Equal(0, result.Count());
+ }
+
+ [Fact]
+ public static void ReadSimpleClassWithImmutableArray()
+ {
+ SimpleTestClassWithImmutableArray obj = JsonSerializer.Deserialize<SimpleTestClassWithImmutableArray>(SimpleTestClassWithImmutableArray.s_json);
+ obj.Verify();
+ }
+
+ [Fact]
public static void ReadIImmutableListTOfIImmutableListT()
{
IImmutableList<IImmutableList<int>> result = JsonSerializer.Deserialize<IImmutableList<IImmutableList<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
}
[Fact]
- public static void ReadPrimitiveImmutableArrayThrows()
- {
- Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<ImmutableArray<int>>(Encoding.UTF8.GetBytes(@"[1,2]")));
- }
-
- [Fact]
public static void ReadSimpleTestClass_ImmutableCollectionWrappers_Throws()
{
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<SimpleTestClassWithIImmutableDictionaryWrapper>(SimpleTestClassWithIImmutableDictionaryWrapper.s_json));
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Text.Json.Tests;
using Xunit;
namespace System.Text.Json.Serialization.Tests
public static partial class ValueTests
{
[Fact]
+ public static void WriteImmutableArrayOfImmutableArray()
+ {
+ ImmutableArray<ImmutableArray<int>> input = ImmutableArray.CreateRange(new List<ImmutableArray<int>>{
+ ImmutableArray.CreateRange(new List<int>() { 1, 2 }),
+ ImmutableArray.CreateRange(new List<int>() { 3, 4 })
+ });
+
+ string json = JsonSerializer.Serialize(input);
+ Assert.Equal("[[1,2],[3,4]]", json);
+ }
+
+ [Fact]
+ public static void WriteImmutableArrayOfArray()
+ {
+ ImmutableArray<int[]> input = ImmutableArray.CreateRange(new List<int[]>
+ {
+ new int[] { 1, 2 },
+ new int[] { 3, 4 }
+ });
+
+ string json = JsonSerializer.Serialize(input);
+ Assert.Equal("[[1,2],[3,4]]", json);
+ }
+
+ [Fact]
+ public static void WriteArrayOfImmutableArray()
+ {
+ ImmutableArray<int>[] input = new ImmutableArray<int>[2];
+ input[0] = ImmutableArray.CreateRange(new List<int>() { 1, 2 });
+ input[1] = ImmutableArray.CreateRange(new List<int>() { 3, 4 });
+
+ string json = JsonSerializer.Serialize(input);
+ Assert.Equal("[[1,2],[3,4]]", json);
+ }
+
+ [Fact]
+ public static void WriteSimpleImmutableArray()
+ {
+ ImmutableArray<int> input = ImmutableArray.CreateRange(new List<int> { 1, 2 });
+
+ string json = JsonSerializer.Serialize(input);
+ Assert.Equal("[1,2]", json);
+ }
+
+ [Fact]
public static void WriteIImmutableListTOfIImmutableListT()
{
IImmutableList<IImmutableList<int>> input = ImmutableList.CreateRange(new List<IImmutableList<int>>{
}
[Fact]
+ public static void WriteSimpleClassWithImmutableArray()
+ {
+ SimpleTestClassWithImmutableArray obj = new SimpleTestClassWithImmutableArray();
+ obj.Initialize();
+
+ Assert.Equal(SimpleTestClassWithImmutableArray.s_json, JsonSerializer.Serialize(obj));
+ }
+
+ [Fact]
+ public static void WriteSimpleClassWithObjectImmutableArray()
+ {
+ SimpleTestClassWithObjectImmutableArray obj = new SimpleTestClassWithObjectImmutableArray();
+ obj.Initialize();
+
+ Assert.Equal(SimpleTestClassWithObjectImmutableArray.s_json, JsonSerializer.Serialize(obj));
+ }
+
+ [Fact]
public static void WriteArrayOfIImmutableListT()
{
IImmutableList<int>[] input = new IImmutableList<int>[2];