Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close issues fixed by serializer refactoring #33819

Merged
merged 4 commits into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 HashSetWithBackingClollection : 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 HashSetWithBackingClollection()
{
foreach (KeyValuePair<string, T> item in items)
{
Add(item.Key, item.Value);
}
_inner = new HashSet<string>();
}

public HashSetWithBackingClollection(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 @@ -1220,5 +1220,67 @@ 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);
}

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

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