Skip to content

Commit

Permalink
Close issues fixed by serializer refactoring (#33819)
Browse files Browse the repository at this point in the history
* Close issues fixed by serializer refactoring

* Validate ext test results

* Fix CI issue

* Address review feedback
  • Loading branch information
layomia committed Mar 26, 2020
1 parent 12e77a6 commit 358070c
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -770,12 +770,16 @@ private class ClassWithExtensionPropertyCustomIImmutableJsonElement
public GenericIImmutableDictionaryWrapper<string, JsonElement> MyOverflow { get; set; }
}

[Fact]
public static void DeserializeIntoGenericDictionaryParameterCount()
[Theory]
[InlineData(typeof(ClassWithExtensionPropertyNoGenericParameters))]
[InlineData(typeof(ClassWithExtensionPropertyOneGenericParameter))]
[InlineData(typeof(ClassWithExtensionPropertyThreeGenericParameters))]
public static void DeserializeIntoGenericDictionaryParameterCount(Type type)
{
JsonSerializer.Deserialize<ClassWithExtensionPropertyNoGenericParameters>("{\"hello\":\"world\"}");
JsonSerializer.Deserialize<ClassWithExtensionPropertyOneGenericParameter>("{\"hello\":\"world\"}");
JsonSerializer.Deserialize<ClassWithExtensionPropertyThreeGenericParameters>("{\"hello\":\"world\"}");
object obj = JsonSerializer.Deserialize("{\"hello\":\"world\"}", type);

IDictionary<string, object> extData = (IDictionary<string, object>)type.GetProperty("MyOverflow").GetValue(obj)!;
Assert.Equal("world", ((JsonElement)extData["hello"]).GetString());
}

private class ClassWithExtensionPropertyNoGenericParameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,5 +394,47 @@ IEnumerator IEnumerable.GetEnumerator()
return ((IDictionary<string, TValue>)dict).GetEnumerator();
}
}

[Fact]
public static void NullableCustomStructRoundtrip()
{
string serialized = JsonSerializer.Serialize(new ClassWithNullablePerson
{
Person = new Person
{
FirstName = "John",
Age = 24
}
});
Assert.Contains(@"{""Person"":{", serialized);
Assert.Contains(@"""FirstName"":""John""", serialized);
Assert.Contains(@"""Age"":24", serialized);
Assert.Contains(@"""Birthday"":null", serialized);
Assert.DoesNotContain(@"""Value"":{""", serialized);
Assert.DoesNotContain(@"""HasValue"":""", serialized);

var obj = JsonSerializer.Deserialize<ClassWithNullablePerson>(serialized);
Assert.Equal("John", obj.Person?.FirstName);
Assert.Equal(24, obj.Person?.Age);
Assert.Null(obj.Person?.Birthday);

serialized = JsonSerializer.Serialize(new ClassWithNullablePerson());
Assert.Equal(@"{""Person"":null}", serialized);

obj = JsonSerializer.Deserialize<ClassWithNullablePerson>(serialized);
Assert.Null(obj.Person);
}

public class ClassWithNullablePerson
{
public Person? Person { get; set; }
}

public struct Person
{
public string FirstName { get; set; }
public int? Age { get; set; }
public DateTime? Birthday { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1349,17 +1349,57 @@ public StringToStringSortedDictionaryWrapper(IList<KeyValuePair<string, string>>
}
}

public class StringToGenericSortedDictionary<T> : SortedDictionary<string, T>
public class HashSetWithBackingCollection : ICollection<string>
{
public StringToGenericSortedDictionary() { }
private readonly ICollection<string> _inner;

// For populating test data only. We cannot assume actual input will have this method.
public StringToGenericSortedDictionary(IList<KeyValuePair<string, T>> items)
public HashSetWithBackingCollection()
{
foreach (KeyValuePair<string, T> item in items)
{
Add(item.Key, item.Value);
}
_inner = new HashSet<string>();
}

public HashSetWithBackingCollection(IEnumerable<string> values)
{
_inner = new HashSet<string>(values);
}

public int Count => _inner.Count;

public bool IsReadOnly => _inner.IsReadOnly;

public void Add(string item)
{
_inner.Add(item);
}

public void Clear()
{
_inner.Clear();
}

public bool Contains(string item)
{
return _inner.Contains(item);
}

public void CopyTo(string[] array, int arrayIndex)
{
_inner.CopyTo(array, arrayIndex);
}

public IEnumerator<string> GetEnumerator()
{
return _inner.GetEnumerator();
}

public bool Remove(string item)
{
return _inner.Remove(item);
}

IEnumerator IEnumerable.GetEnumerator()
{
return _inner.GetEnumerator();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System;
using Xunit;

namespace System.Text.Json.Serialization.Tests
Expand Down Expand Up @@ -1220,5 +1218,64 @@ public static void Read_Generic_NoPublicConstructor_Throws(Type type, string jso
NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize(json, type));
Assert.Contains(type.ToString(), ex.Message);
}

[Fact]
public static void DoesNotCall_CollectionPropertyGetter_EveryTimeElementIsAdded()
{
var networkList = new List<string> { "Network1", "Network2" };

string serialized = JsonSerializer.Serialize(new NetworkWrapper { NetworkList = networkList });
Assert.Equal(@"{""NetworkList"":[""Network1"",""Network2""]}", serialized);

NetworkWrapper obj = JsonSerializer.Deserialize<NetworkWrapper>(serialized);

int i = 0;
foreach (string network in obj.NetworkList)
{
Assert.Equal(networkList[i], network);
i++;
}
}

public class NetworkWrapper
{
private string _Networks = string.Empty;

[JsonIgnore]
public string Networks
{
get => _Networks;
set => _Networks = value ?? string.Empty;
}

public IEnumerable<string> NetworkList
{
get => Networks.Split(',');
set => Networks = value != null ? string.Join(",", value) : "";
}
}

[Fact]
public static void CollectionWith_BackingField_CanRoundtrip()
{
string json = "{\"AllowedGrantTypes\":[\"client_credentials\"]}";

Client obj = JsonSerializer.Deserialize<Client>(json);
Assert.Equal("client_credentials", obj.AllowedGrantTypes.First());

string serialized = JsonSerializer.Serialize(obj);
Assert.Equal(json, serialized);
}

private class Client
{
private ICollection<string> _allowedGrantTypes = new HashSetWithBackingCollection();

public ICollection<string> AllowedGrantTypes
{
get { return _allowedGrantTypes; }
set { _allowedGrantTypes = new HashSetWithBackingCollection(value); }
}
}
}
}

0 comments on commit 358070c

Please sign in to comment.