diff --git a/src/EFCore/EFCore.baseline.json b/src/EFCore/EFCore.baseline.json
index 7c9812b71e2..7758e38cca6 100644
--- a/src/EFCore/EFCore.baseline.json
+++ b/src/EFCore/EFCore.baseline.json
@@ -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);"
diff --git a/src/EFCore/Storage/Json/JsonValueReaderWriter.cs b/src/EFCore/Storage/Json/JsonValueReaderWriter.cs
index 94daf881dcb..c70814cb8cd 100644
--- a/src/EFCore/Storage/Json/JsonValueReaderWriter.cs
+++ b/src/EFCore/Storage/Json/JsonValueReaderWriter.cs
@@ -70,7 +70,7 @@ internal JsonValueReaderWriter()
/// The JSON to parse.
/// Can be used to update an existing object, rather than create a new one.
/// The read value.
- public object FromJsonString(string json, object? existingObject = null)
+ public object? FromJsonString(string json, object? existingObject = null)
{
if (string.IsNullOrWhiteSpace(json))
{
@@ -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);
}
///
diff --git a/test/EFCore.Specification.Tests/JsonTypesTestBase.cs b/test/EFCore.Specification.Tests/JsonTypesTestBase.cs
index c50aeef9b48..a77eb8527fb 100644
--- a/test/EFCore.Specification.Tests/JsonTypesTestBase.cs
+++ b/test/EFCore.Specification.Tests/JsonTypesTestBase.cs
@@ -2623,6 +2623,45 @@ protected class NullableEnumU64CollectionType
public IList 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?>(
+ nameof(NullStringCollectionType.String),
+ null,
+ """{"Prop":null}""",
+ mappedCollection: true);
+
+ protected class NullStringCollectionType
+ {
+ public List? String { get; set; }
+ }
+
+ [Fact]
+ public virtual Task Can_read_write_null_value_of_collection_of_int_JSON_values()
+ => Can_read_and_write_JSON_value?>(
+ nameof(NullIntCollectionType.Int32),
+ null,
+ """{"Prop":null}""",
+ mappedCollection: true);
+
+ protected class NullIntCollectionType
+ {
+ public List? 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?>(
+ nameof(NullNullableIntCollectionType.Int32),
+ null,
+ """{"Prop":null}""",
+ mappedCollection: true);
+
+ protected class NullNullableIntCollectionType
+ {
+ public List? 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(
@@ -3671,16 +3710,18 @@ protected virtual Task Can_read_and_write_JSON_value(
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);
@@ -3717,15 +3758,18 @@ protected virtual Task Can_read_and_write_JSON_value(
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);