Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion src/EFCore/EFCore.baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -17294,7 +17294,7 @@
"Member": "abstract object FromJson(ref Microsoft.EntityFrameworkCore.Storage.Json.Utf8JsonReaderManager manager, object? existingObject = null);"
},
{
"Member": "object FromJsonString(string json, object? existingObject = null);"
"Member": "object? FromJsonString(string json, object? existingObject = null);"
},
{
"Member": "abstract void ToJson(System.Text.Json.Utf8JsonWriter writer, object? value);"
Expand Down
6 changes: 4 additions & 2 deletions src/EFCore/Storage/Json/JsonValueReaderWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ internal JsonValueReaderWriter()
/// <param name="json">The JSON to parse.</param>
/// <param name="existingObject">Can be used to update an existing object, rather than create a new one.</param>
/// <returns>The read value.</returns>
public object FromJsonString(string json, object? existingObject = null)
public object? FromJsonString(string json, object? existingObject = null)
{
if (string.IsNullOrWhiteSpace(json))
{
Expand All @@ -79,7 +79,9 @@ public object FromJsonString(string json, object? existingObject = null)

var readerManager = new Utf8JsonReaderManager(new JsonReaderData(Encoding.UTF8.GetBytes(json)), null);
readerManager.MoveNext();
return FromJson(ref readerManager, existingObject);
return readerManager.CurrentReader.TokenType == JsonTokenType.Null
? null
: FromJson(ref readerManager, existingObject);
}

/// <summary>
Expand Down
70 changes: 57 additions & 13 deletions test/EFCore.Specification.Tests/JsonTypesTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2623,6 +2623,45 @@ protected class NullableEnumU64CollectionType
public IList<EnumU64?> EnumU64 { get; set; } = null!;
}

[Fact]
public virtual Task Can_read_write_null_value_of_collection_of_string_JSON_values()
=> Can_read_and_write_JSON_value<NullStringCollectionType, List<string>?>(
nameof(NullStringCollectionType.String),
null,
"""{"Prop":null}""",
mappedCollection: true);

protected class NullStringCollectionType
{
public List<string>? String { get; set; }
}

[Fact]
public virtual Task Can_read_write_null_value_of_collection_of_int_JSON_values()
=> Can_read_and_write_JSON_value<NullIntCollectionType, List<int>?>(
nameof(NullIntCollectionType.Int32),
null,
"""{"Prop":null}""",
mappedCollection: true);

protected class NullIntCollectionType
{
public List<int>? Int32 { get; set; }
}

[Fact]
public virtual Task Can_read_write_null_value_of_collection_of_nullable_int_JSON_values()
=> Can_read_and_write_JSON_value<NullNullableIntCollectionType, List<int?>?>(
nameof(NullNullableIntCollectionType.Int32),
null,
"""{"Prop":null}""",
mappedCollection: true);

protected class NullNullableIntCollectionType
{
public List<int?>? Int32 { get; set; }
}

[Fact]
public virtual Task Can_read_write_collection_of_sbyte_values_with_converter_as_JSON_string()
=> Can_read_and_write_JSON_property_value<Int8ConvertedType, sbyte[]>(
Expand Down Expand Up @@ -3671,16 +3710,18 @@ protected virtual Task Can_read_and_write_JSON_value<TEntity, TModel>(
using var writer = new Utf8JsonWriter(stream);

var jsonReaderWriter = property.GetJsonValueReaderWriter()
?? property.GetTypeMapping().JsonValueReaderWriter!;
?? property.GetTypeMapping().JsonValueReaderWriter;

var toString = value == null ? null : jsonReaderWriter.ToJsonString(value);
var fromString = toString == null ? null : jsonReaderWriter.FromJsonString(toString, existingObject);
var toString = value == null ? null : jsonReaderWriter!.ToJsonString(value);
var fromString = value == null
? jsonReaderWriter?.FromJsonString("null")
: jsonReaderWriter!.FromJsonString(toString!, existingObject);
Assert.Equal(value, fromString);

var actual = ToJsonPropertyString(jsonReaderWriter, value);
var actual = ToJsonPropertyString(jsonReaderWriter!, value);
Assert.Equal(json, actual);

var fromJson = FromJsonPropertyString(jsonReaderWriter, actual, existingObject);
var fromJson = FromJsonPropertyString(jsonReaderWriter!, actual, existingObject);
if (existingObject != null)
{
Assert.Same(fromJson, existingObject);
Expand Down Expand Up @@ -3717,15 +3758,18 @@ protected virtual Task Can_read_and_write_JSON_value<TEntity, TModel>(

Assert.Equal(elementNullable, element.IsNullable);

var comparer = element.GetValueComparer()!;
var elementReaderWriter = element.GetJsonValueReaderWriter()!;
foreach (var item in (IEnumerable)value!)
if (value != null)
{
Assert.True(comparer.Equals(item, comparer.Snapshot(item)));
Assert.True(
comparer.Equals(
item, FromJsonPropertyString(
elementReaderWriter, ToJsonPropertyString(elementReaderWriter, item))));
var comparer = element.GetValueComparer()!;
var elementReaderWriter = element.GetJsonValueReaderWriter()!;
foreach (var item in (IEnumerable)value)
{
Assert.True(comparer.Equals(item, comparer.Snapshot(item)));
Assert.True(
comparer.Equals(
item, FromJsonPropertyString(
elementReaderWriter, ToJsonPropertyString(elementReaderWriter, item))));
}
}

AssertElementFacets(element, facets);
Expand Down