Skip to content

Commit b336fbe

Browse files
authored
Support customized reading and writing of JSON values (#31021)
1 parent 7d3e715 commit b336fbe

File tree

110 files changed

+4085
-210
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+4085
-210
lines changed

Diff for: src/EFCore.Cosmos/Storage/Internal/CosmosTypeMapping.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.EntityFrameworkCore.Storage.Json;
5+
46
namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
57

68
/// <summary>
@@ -20,13 +22,15 @@ public class CosmosTypeMapping : CoreTypeMapping
2022
public CosmosTypeMapping(
2123
Type clrType,
2224
ValueComparer? comparer = null,
23-
ValueComparer? keyComparer = null)
25+
ValueComparer? keyComparer = null,
26+
JsonValueReaderWriter? jsonValueReaderWriter = null)
2427
: base(
2528
new CoreTypeMappingParameters(
2629
clrType,
2730
converter: null,
2831
comparer,
29-
keyComparer))
32+
keyComparer,
33+
jsonValueReaderWriter: jsonValueReaderWriter))
3034
{
3135
}
3236

Diff for: src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs

+20-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,13 @@ public CosmosTypeMappingSource(TypeMappingSourceDependencies dependencies)
2626
: base(dependencies)
2727
{
2828
_clrTypeMappings
29-
= new Dictionary<Type, CosmosTypeMapping> { { typeof(JObject), new CosmosTypeMapping(typeof(JObject)) } };
29+
= new Dictionary<Type, CosmosTypeMapping>
30+
{
31+
{
32+
typeof(JObject), new CosmosTypeMapping(
33+
typeof(JObject), jsonValueReaderWriter: dependencies.JsonValueReaderWriterSource.FindReaderWriter(typeof(JObject)))
34+
}
35+
};
3036
}
3137

3238
/// <summary>
@@ -47,21 +53,22 @@ public CosmosTypeMappingSource(TypeMappingSourceDependencies dependencies)
4753
?? base.FindMapping(mappingInfo));
4854
}
4955

50-
private static CoreTypeMapping? FindPrimitiveMapping(in TypeMappingInfo mappingInfo)
56+
private CoreTypeMapping? FindPrimitiveMapping(in TypeMappingInfo mappingInfo)
5157
{
5258
var clrType = mappingInfo.ClrType!;
5359
if ((clrType.IsValueType
5460
&& clrType != typeof(Guid)
5561
&& !clrType.IsEnum)
5662
|| clrType == typeof(string))
5763
{
58-
return new CosmosTypeMapping(clrType);
64+
return new CosmosTypeMapping(
65+
clrType, jsonValueReaderWriter: Dependencies.JsonValueReaderWriterSource.FindReaderWriter(clrType));
5966
}
6067

6168
return null;
6269
}
6370

64-
private static CoreTypeMapping? FindCollectionMapping(in TypeMappingInfo mappingInfo)
71+
private CoreTypeMapping? FindCollectionMapping(in TypeMappingInfo mappingInfo)
6572
{
6673
var clrType = mappingInfo.ClrType!;
6774
var elementType = clrType.TryGetSequenceType();
@@ -70,14 +77,17 @@ public CosmosTypeMappingSource(TypeMappingSourceDependencies dependencies)
7077
return null;
7178
}
7279

80+
var jsonValueReaderWriter = Dependencies.JsonValueReaderWriterSource.FindReaderWriter(clrType);
81+
7382
if (clrType.IsArray)
7483
{
7584
var elementMappingInfo = new TypeMappingInfo(elementType);
7685
var elementMapping = FindPrimitiveMapping(elementMappingInfo)
7786
?? FindCollectionMapping(elementMappingInfo);
7887
return elementMapping == null
7988
? null
80-
: new CosmosTypeMapping(clrType, CreateArrayComparer(elementMapping, elementType));
89+
: new CosmosTypeMapping(
90+
clrType, CreateArrayComparer(elementMapping, elementType), jsonValueReaderWriter: jsonValueReaderWriter);
8191
}
8292

8393
if (clrType.IsGenericType
@@ -93,7 +103,8 @@ public CosmosTypeMappingSource(TypeMappingSourceDependencies dependencies)
93103
?? FindCollectionMapping(elementMappingInfo);
94104
return elementMapping == null
95105
? null
96-
: new CosmosTypeMapping(clrType, CreateListComparer(elementMapping, elementType, clrType));
106+
: new CosmosTypeMapping(
107+
clrType, CreateListComparer(elementMapping, elementType, clrType), jsonValueReaderWriter: jsonValueReaderWriter);
97108
}
98109

99110
if (genericTypeDefinition == typeof(Dictionary<,>)
@@ -112,7 +123,9 @@ public CosmosTypeMappingSource(TypeMappingSourceDependencies dependencies)
112123
?? FindCollectionMapping(elementMappingInfo);
113124
return elementMapping == null
114125
? null
115-
: new CosmosTypeMapping(clrType, CreateStringDictionaryComparer(elementMapping, elementType, clrType));
126+
: new CosmosTypeMapping(
127+
clrType, CreateStringDictionaryComparer(elementMapping, elementType, clrType),
128+
jsonValueReaderWriter: jsonValueReaderWriter);
116129
}
117130
}
118131

Diff for: src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs

+30-9
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,31 @@ private void Create(
834834
.Append("()");
835835
}
836836

837+
var jsonValueReaderWriterType = (Type?)property[CoreAnnotationNames.JsonValueReaderWriterType];
838+
if (jsonValueReaderWriterType != null)
839+
{
840+
AddNamespace(jsonValueReaderWriterType, parameters.Namespaces);
841+
842+
var instanceProperty = jsonValueReaderWriterType.GetAnyProperty("Instance");
843+
if (instanceProperty != null
844+
&& instanceProperty.IsStatic()
845+
&& instanceProperty.GetMethod?.IsPublic == true
846+
&& jsonValueReaderWriterType.IsAssignableFrom(instanceProperty.PropertyType))
847+
{
848+
mainBuilder.AppendLine(",")
849+
.Append("jsonValueReaderWriter: ")
850+
.Append(_code.Reference(jsonValueReaderWriterType))
851+
.Append(".Instance");
852+
}
853+
else
854+
{
855+
mainBuilder.AppendLine(",")
856+
.Append("jsonValueReaderWriter: new ")
857+
.Append(_code.Reference(jsonValueReaderWriterType))
858+
.Append("()");
859+
}
860+
}
861+
837862
var sentinel = property.Sentinel;
838863
if (sentinel != null)
839864
{
@@ -900,8 +925,9 @@ private void Create(
900925
}
901926

902927
return i == ForeignKey.LongestFkChainAllowedLength
903-
? throw new InvalidOperationException(CoreStrings.RelationshipCycle(
904-
property.DeclaringEntityType.DisplayName(), property.Name, "ValueConverterType"))
928+
? throw new InvalidOperationException(
929+
CoreStrings.RelationshipCycle(
930+
property.DeclaringEntityType.DisplayName(), property.Name, "ValueConverterType"))
905931
: null;
906932
}
907933

@@ -1474,18 +1500,13 @@ private static void CreateAnnotations<TAnnotatable>(
14741500
{
14751501
process(
14761502
annotatable,
1477-
parameters with
1478-
{
1479-
Annotations = annotatable.GetAnnotations().ToDictionary(a => a.Name, a => a.Value),
1480-
IsRuntime = false
1481-
});
1503+
parameters with { Annotations = annotatable.GetAnnotations().ToDictionary(a => a.Name, a => a.Value), IsRuntime = false });
14821504

14831505
process(
14841506
annotatable,
14851507
parameters with
14861508
{
1487-
Annotations = annotatable.GetRuntimeAnnotations().ToDictionary(a => a.Name, a => a.Value),
1488-
IsRuntime = true
1509+
Annotations = annotatable.GetRuntimeAnnotations().ToDictionary(a => a.Name, a => a.Value), IsRuntime = true
14891510
});
14901511
}
14911512

Diff for: src/EFCore.InMemory/Storage/Internal/InMemoryTypeMapping.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.EntityFrameworkCore.Storage.Json;
5+
46
namespace Microsoft.EntityFrameworkCore.InMemory.Storage.Internal;
57

68
/// <summary>
@@ -20,13 +22,15 @@ public class InMemoryTypeMapping : CoreTypeMapping
2022
public InMemoryTypeMapping(
2123
Type clrType,
2224
ValueComparer? comparer = null,
23-
ValueComparer? keyComparer = null)
25+
ValueComparer? keyComparer = null,
26+
JsonValueReaderWriter? jsonValueReaderWriter = null)
2427
: base(
2528
new CoreTypeMappingParameters(
2629
clrType,
2730
converter: null,
2831
comparer,
29-
keyComparer))
32+
keyComparer,
33+
jsonValueReaderWriter: jsonValueReaderWriter))
3034
{
3135
}
3236

Diff for: src/EFCore.InMemory/Storage/Internal/InMemoryTypeMappingSource.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ public InMemoryTypeMappingSource(TypeMappingSourceDependencies dependencies)
3333
var clrType = mappingInfo.ClrType;
3434
Check.DebugAssert(clrType != null, "ClrType is null");
3535

36+
var jsonValueReaderWriter = Dependencies.JsonValueReaderWriterSource.FindReaderWriter(clrType);
37+
3638
if (clrType.IsValueType
3739
|| clrType == typeof(string)
3840
|| clrType == typeof(byte[]))
3941
{
40-
return new InMemoryTypeMapping(clrType);
42+
return new InMemoryTypeMapping(
43+
clrType, jsonValueReaderWriter: jsonValueReaderWriter);
4144
}
4245

4346
if (clrType.FullName == "NetTopologySuite.Geometries.Geometry"
@@ -48,7 +51,8 @@ public InMemoryTypeMappingSource(TypeMappingSourceDependencies dependencies)
4851
return new InMemoryTypeMapping(
4952
clrType,
5053
comparer,
51-
comparer);
54+
comparer,
55+
jsonValueReaderWriter);
5256
}
5357

5458
return base.FindMapping(mappingInfo);

Diff for: src/EFCore.Relational/Storage/BoolTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Data;
5+
using Microsoft.EntityFrameworkCore.Storage.Json;
56

67
namespace Microsoft.EntityFrameworkCore.Storage;
78

@@ -28,7 +29,7 @@ public class BoolTypeMapping : RelationalTypeMapping
2829
public BoolTypeMapping(
2930
string storeType,
3031
DbType? dbType = System.Data.DbType.Boolean)
31-
: base(storeType, typeof(bool), dbType)
32+
: base(storeType, typeof(bool), dbType, jsonValueReaderWriter: JsonBoolReaderWriter.Instance)
3233
{
3334
}
3435

Diff for: src/EFCore.Relational/Storage/ByteArrayTypeMapping.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Data;
55
using System.Globalization;
66
using System.Text;
7+
using Microsoft.EntityFrameworkCore.Storage.Json;
78

89
namespace Microsoft.EntityFrameworkCore.Storage;
910

@@ -35,7 +36,8 @@ public ByteArrayTypeMapping(
3536
: base(
3637
new RelationalTypeMappingParameters(
3738
new CoreTypeMappingParameters(
38-
typeof(byte[])), storeType, StoreTypePostfix.None, dbType, unicode: false, size))
39+
typeof(byte[]), jsonValueReaderWriter: JsonByteArrayReaderWriter.Instance), storeType, StoreTypePostfix.None, dbType,
40+
unicode: false, size))
3941
{
4042
}
4143

Diff for: src/EFCore.Relational/Storage/ByteTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Data;
5+
using Microsoft.EntityFrameworkCore.Storage.Json;
56

67
namespace Microsoft.EntityFrameworkCore.Storage;
78

@@ -28,7 +29,7 @@ public class ByteTypeMapping : RelationalTypeMapping
2829
public ByteTypeMapping(
2930
string storeType,
3031
DbType? dbType = System.Data.DbType.Byte)
31-
: base(storeType, typeof(byte), dbType)
32+
: base(storeType, typeof(byte), dbType, jsonValueReaderWriter: JsonByteReaderWriter.Instance)
3233
{
3334
}
3435

Diff for: src/EFCore.Relational/Storage/CharTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Data;
5+
using Microsoft.EntityFrameworkCore.Storage.Json;
56

67
namespace Microsoft.EntityFrameworkCore.Storage;
78

@@ -28,7 +29,7 @@ public class CharTypeMapping : RelationalTypeMapping
2829
public CharTypeMapping(
2930
string storeType,
3031
DbType? dbType = System.Data.DbType.String)
31-
: base(storeType, typeof(char), dbType)
32+
: base(storeType, typeof(char), dbType, jsonValueReaderWriter: JsonCharReaderWriter.Instance)
3233
{
3334
}
3435

Diff for: src/EFCore.Relational/Storage/DateOnlyTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Data;
5+
using Microsoft.EntityFrameworkCore.Storage.Json;
56

67
namespace Microsoft.EntityFrameworkCore.Storage;
78

@@ -30,7 +31,7 @@ public class DateOnlyTypeMapping : RelationalTypeMapping
3031
public DateOnlyTypeMapping(
3132
string storeType,
3233
DbType? dbType = System.Data.DbType.Date)
33-
: base(storeType, typeof(DateOnly), dbType)
34+
: base(storeType, typeof(DateOnly), dbType, jsonValueReaderWriter: JsonDateOnlyReaderWriter.Instance)
3435
{
3536
}
3637

Diff for: src/EFCore.Relational/Storage/DateTimeOffsetTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Data;
5+
using Microsoft.EntityFrameworkCore.Storage.Json;
56

67
namespace Microsoft.EntityFrameworkCore.Storage;
78

@@ -30,7 +31,7 @@ public class DateTimeOffsetTypeMapping : RelationalTypeMapping
3031
public DateTimeOffsetTypeMapping(
3132
string storeType,
3233
DbType? dbType = System.Data.DbType.DateTimeOffset)
33-
: base(storeType, typeof(DateTimeOffset), dbType)
34+
: base(storeType, typeof(DateTimeOffset), dbType, jsonValueReaderWriter: JsonDateTimeOffsetReaderWriter.Instance)
3435
{
3536
}
3637

Diff for: src/EFCore.Relational/Storage/DateTimeTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Data;
5+
using Microsoft.EntityFrameworkCore.Storage.Json;
56

67
namespace Microsoft.EntityFrameworkCore.Storage;
78

@@ -30,7 +31,7 @@ public class DateTimeTypeMapping : RelationalTypeMapping
3031
public DateTimeTypeMapping(
3132
string storeType,
3233
DbType? dbType = System.Data.DbType.DateTime)
33-
: base(storeType, typeof(DateTime), dbType)
34+
: base(storeType, typeof(DateTime), dbType, jsonValueReaderWriter: JsonDateTimeReaderWriter.Instance)
3435
{
3536
}
3637

Diff for: src/EFCore.Relational/Storage/DecimalTypeMapping.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Data;
5+
using Microsoft.EntityFrameworkCore.Storage.Json;
56

67
namespace Microsoft.EntityFrameworkCore.Storage;
78

@@ -34,7 +35,8 @@ public DecimalTypeMapping(
3435
DbType? dbType = System.Data.DbType.Decimal,
3536
int? precision = null,
3637
int? scale = null)
37-
: base(storeType, typeof(decimal), dbType, precision: precision, scale: scale)
38+
: base(
39+
storeType, typeof(decimal), dbType, precision: precision, scale: scale, jsonValueReaderWriter: JsonDecimalReaderWriter.Instance)
3840
{
3941
}
4042

Diff for: src/EFCore.Relational/Storage/DoubleTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Data;
55
using System.Globalization;
6+
using Microsoft.EntityFrameworkCore.Storage.Json;
67

78
namespace Microsoft.EntityFrameworkCore.Storage;
89

@@ -29,7 +30,7 @@ public class DoubleTypeMapping : RelationalTypeMapping
2930
public DoubleTypeMapping(
3031
string storeType,
3132
DbType? dbType = System.Data.DbType.Double)
32-
: base(storeType, typeof(double), dbType)
33+
: base(storeType, typeof(double), dbType, jsonValueReaderWriter: JsonDoubleReaderWriter.Instance)
3334
{
3435
}
3536

Diff for: src/EFCore.Relational/Storage/FloatTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Data;
55
using System.Globalization;
6+
using Microsoft.EntityFrameworkCore.Storage.Json;
67

78
namespace Microsoft.EntityFrameworkCore.Storage;
89

@@ -29,7 +30,7 @@ public class FloatTypeMapping : RelationalTypeMapping
2930
public FloatTypeMapping(
3031
string storeType,
3132
DbType? dbType = System.Data.DbType.Single)
32-
: base(storeType, typeof(float), dbType)
33+
: base(storeType, typeof(float), dbType, jsonValueReaderWriter: JsonFloatReaderWriter.Instance)
3334
{
3435
}
3536

0 commit comments

Comments
 (0)