@@ -13,14 +13,19 @@ namespace Nest
13
13
{
14
14
internal class ElasticContractResolver : DefaultContractResolver
15
15
{
16
- private static readonly Type _readAsType = typeof ( ReadAsTypeJsonConverter < > ) ;
17
- private static readonly MachineLearningDateTimeConverter MachineLearningDateTimeConverter = new MachineLearningDateTimeConverter ( ) ;
16
+ private static readonly Type [ ] StringSignalTypes = { typeof ( KeywordAttribute ) , typeof ( TextAttribute ) } ;
17
+ private static readonly Assembly ThisAssembly = typeof ( ElasticContractResolver ) . Assembly ( ) ;
18
18
19
+ private static readonly MachineLearningDateTimeConverter MachineLearningDateTimeConverter = new MachineLearningDateTimeConverter ( ) ;
19
20
private static readonly StringEnumConverter StringEnumConverter = new StringEnumConverter ( ) ;
20
- private static readonly Type [ ] StringSignalTypes = { typeof ( KeywordAttribute ) , typeof ( TextAttribute ) } ;
21
21
private static readonly StringTimeSpanConverter StringTimeSpanConverter = new StringTimeSpanConverter ( ) ;
22
+ private static readonly TimeSpanToStringConverter TimeSpanToStringConverter = new TimeSpanToStringConverter ( ) ;
23
+ private static readonly QueryContainerCollectionJsonConverter QueryContainerCollectionJsonConverter = new QueryContainerCollectionJsonConverter ( ) ;
24
+ private static readonly IsoDateTimeConverter IsoDateTimeConverter = new IsoDateTimeConverter { Culture = CultureInfo . InvariantCulture } ;
25
+ private static readonly VerbatimDictionaryKeysJsonConverter VerbatimDictionaryKeysJsonConverter = new VerbatimDictionaryKeysJsonConverter ( ) ;
26
+ private static readonly ErrorJsonConverter ErrorJsonConverter = new ErrorJsonConverter ( ) ;
27
+ private static readonly ErrorCauseJsonConverter ErrorCauseJsonConverter = new ErrorCauseJsonConverter ( ) ;
22
28
23
- private static readonly Assembly ThisAssembly = typeof ( ElasticContractResolver ) . Assembly ( ) ;
24
29
private readonly Lazy < bool > _usingSourceSerializer ;
25
30
26
31
public ElasticContractResolver ( IConnectionSettingsValues connectionSettings )
@@ -34,8 +39,14 @@ public ElasticContractResolver(IConnectionSettingsValues connectionSettings)
34
39
/// </summary>
35
40
public IConnectionSettingsValues ConnectionSettings { get ; }
36
41
42
+ /// <summary>
43
+ /// A JsonSerializer with defaults
44
+ /// </summary>
37
45
public static JsonSerializer Empty { get ; } = new JsonSerializer ( ) ;
38
46
47
+ /// <summary>
48
+ /// Determines whether a custom source serializer is being used rather than the internal serializer
49
+ /// </summary>
39
50
public bool UsingSourceSerializer => _usingSourceSerializer . Value ;
40
51
41
52
/// <summary>
@@ -46,43 +57,45 @@ public ElasticContractResolver(IConnectionSettingsValues connectionSettings)
46
57
protected bool CanRemoveSourceConverter ( JsonConverter converter )
47
58
{
48
59
if ( UsingSourceSerializer || converter == null ) return false ;
49
-
50
60
return converter is SourceConverter ;
51
61
}
52
62
53
63
protected override JsonContract CreateContract ( Type objectType ) => ConnectionSettings . Inferrer . Contracts . GetOrAdd ( objectType , o =>
54
64
{
55
- var contract = base . CreateContract ( o ) ;
56
-
57
- if ( o == typeof ( Error ) ) contract . Converter = new ErrorJsonConverter ( ) ;
58
- else if ( o == typeof ( ErrorCause ) ) contract . Converter = new ErrorCauseJsonConverter ( ) ;
59
- else if ( CanRemoveSourceConverter ( contract . Converter ) ) contract . Converter = null ; //rely on defaults
60
- else if ( o . IsGeneric ( ) && o . GetGenericTypeDefinition ( ) == typeof ( SuggestDictionary < > ) )
61
- contract . Converter =
62
- ( JsonConverter ) typeof ( SuggestDictionaryConverter < > ) . CreateGenericInstance ( o . GetGenericArguments ( ) ) ;
65
+ JsonContract contract ;
63
66
64
- else if ( contract . Converter == null &&
65
- ( typeof ( IDictionary ) . IsAssignableFrom ( o ) || o . IsGenericDictionary ( ) ) && ! typeof ( IIsADictionary ) . IsAssignableFrom ( o ) )
67
+ // short circuit for types with converters
68
+ if ( o . Assembly == ThisAssembly )
66
69
{
67
- if ( ! o . TryGetGenericDictionaryArguments ( out var genericArguments ) )
68
- contract . Converter = new VerbatimDictionaryKeysJsonConverter ( ) ;
69
- else
70
- contract . Converter =
71
- ( JsonConverter ) typeof ( VerbatimDictionaryKeysJsonConverter < , > ) . CreateGenericInstance ( genericArguments ) ;
70
+ var converter = GetContractJsonConverter ( o ) ;
71
+ if ( converter != null )
72
+ {
73
+ contract = CreateObjectContract ( o ) ;
74
+ contract . Converter = converter ;
75
+ return contract ;
76
+ }
72
77
}
73
78
79
+ contract = base . CreateContract ( o ) ;
80
+
81
+ if ( CanRemoveSourceConverter ( contract . Converter ) ) contract . Converter = null ; //rely on defaults
82
+ else if ( o == typeof ( Error ) ) contract . Converter = ErrorJsonConverter ;
83
+ else if ( o == typeof ( ErrorCause ) ) contract . Converter = ErrorCauseJsonConverter ;
84
+ else if ( o . IsGeneric ( ) && o . GetGenericTypeDefinition ( ) == typeof ( SuggestDictionary < > ) )
85
+ contract . Converter = typeof ( SuggestDictionaryConverter < > ) . CreateGenericInstance < JsonConverter > ( o . GetGenericArguments ( ) ) ;
86
+ else if ( contract . Converter == null &&
87
+ ( typeof ( IDictionary ) . IsAssignableFrom ( o ) || o . IsGenericDictionary ( ) ) && ! typeof ( IIsADictionary ) . IsAssignableFrom ( o ) )
88
+ contract . Converter = ! o . TryGetGenericDictionaryArguments ( out var genericArguments )
89
+ ? VerbatimDictionaryKeysJsonConverter
90
+ : typeof ( VerbatimDictionaryKeysJsonConverter < , > ) . CreateGenericInstance < JsonConverter > ( genericArguments ) ;
74
91
else if ( o == typeof ( DateTime ) || o == typeof ( DateTime ? ) )
75
- contract . Converter = new IsoDateTimeConverter { Culture = CultureInfo . InvariantCulture } ;
92
+ contract . Converter = IsoDateTimeConverter ;
76
93
else if ( o == typeof ( TimeSpan ) || o == typeof ( TimeSpan ? ) )
77
- contract . Converter = new TimeSpanToStringConverter ( ) ;
94
+ contract . Converter = TimeSpanToStringConverter ;
78
95
else if ( typeof ( IEnumerable < QueryContainer > ) . IsAssignableFrom ( o ) )
79
- contract . Converter = new QueryContainerCollectionJsonConverter ( ) ;
80
-
81
- ApplyBuildInSerializersForType ( o , contract ) ;
82
-
83
- if ( ! o . FullName . StartsWith ( "Nest." , StringComparison . OrdinalIgnoreCase ) ) return contract ;
84
- if ( ApplyExactContractJsonAttribute ( o , contract ) ) return contract ;
85
- if ( ApplyContractJsonAttribute ( o , contract ) ) return contract ;
96
+ contract . Converter = QueryContainerCollectionJsonConverter ;
97
+ else if ( o . GetTypeInfo ( ) . GetCustomAttribute < StringEnumAttribute > ( ) != null )
98
+ contract . Converter = StringEnumConverter ;
86
99
87
100
return contract ;
88
101
} ) ;
@@ -96,41 +109,37 @@ protected override JsonConverter ResolveContractConverter(Type objectType)
96
109
97
110
var readAsType = attribute . Type ;
98
111
var readAsTypeInfo = readAsType . GetTypeInfo ( ) ;
112
+ var readAsJsonConverterType = typeof ( ReadAsTypeJsonConverter < > ) ;
99
113
if ( ! readAsTypeInfo . IsGenericType || ! readAsTypeInfo . IsGenericTypeDefinition )
100
- return ( JsonConverter ) _readAsType . CreateGenericInstance ( objectType ) ;
114
+ return ( JsonConverter ) readAsJsonConverterType . CreateGenericInstance ( objectType ) ;
101
115
102
116
var targetType = objectType ;
103
117
if ( info . IsGenericType ) targetType = targetType . GetGenericArguments ( ) . First ( ) ;
104
118
105
119
var concreteType = readAsType . MakeGenericType ( targetType ) ;
106
- return ( JsonConverter ) _readAsType . CreateGenericInstance ( concreteType ) ;
120
+ return ( JsonConverter ) readAsJsonConverterType . CreateGenericInstance ( concreteType ) ;
107
121
}
108
122
109
- private static bool ApplyExactContractJsonAttribute ( Type objectType , JsonContract contract )
123
+ private static JsonConverter GetContractJsonConverter ( Type objectType )
110
124
{
111
- var attribute = ( ExactContractJsonConverterAttribute ) objectType . GetTypeInfo ( )
125
+ var exactAttribute = ( ExactContractJsonConverterAttribute ) objectType . GetTypeInfo ( )
112
126
. GetCustomAttributes ( typeof ( ExactContractJsonConverterAttribute ) )
113
127
. FirstOrDefault ( ) ;
114
- if ( attribute ? . Converter == null ) return false ;
115
128
116
- contract . Converter = attribute . Converter ;
117
- return true ;
118
- }
129
+ if ( exactAttribute ? . Converter != null )
130
+ return exactAttribute . Converter ;
119
131
120
- private static bool ApplyContractJsonAttribute ( Type objectType , JsonContract contract )
121
- {
122
132
foreach ( var t in TypeWithInterfaces ( objectType ) )
123
133
{
124
- var attribute =
125
- ( ContractJsonConverterAttribute ) t . GetTypeInfo ( )
126
- . GetCustomAttributes ( typeof ( ContractJsonConverterAttribute ) , true )
127
- . FirstOrDefault ( ) ;
134
+ var attribute = ( ContractJsonConverterAttribute ) t . GetTypeInfo ( )
135
+ . GetCustomAttributes ( typeof ( ContractJsonConverterAttribute ) , true )
136
+ . FirstOrDefault ( ) ;
128
137
if ( attribute ? . Converter == null ) continue ;
129
138
130
- contract . Converter = attribute . Converter ;
131
- return true ;
139
+ return attribute . Converter ;
132
140
}
133
- return false ;
141
+
142
+ return null ;
134
143
}
135
144
136
145
private static IEnumerable < Type > TypeWithInterfaces ( Type objectType )
@@ -150,13 +159,12 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
150
159
if ( member . Name == nameof ( IResponse . ApiCall ) && typeof ( IResponse ) . IsAssignableFrom ( member . DeclaringType ) )
151
160
property . Ignored = true ;
152
161
153
- ApplyShouldSerializer ( property ) ;
162
+ ApplyShouldSerialize ( property ) ;
154
163
ApplyPropertyOverrides ( member , property ) ;
155
- ApplyBuildInSerializers ( member , property ) ;
164
+ ApplyBuiltInConverters ( member , property ) ;
156
165
return property ;
157
166
}
158
167
159
-
160
168
protected override IList < JsonProperty > CreateProperties ( Type type , MemberSerialization memberSerialization )
161
169
{
162
170
// Only serialize explicitly implemented IProperty properties on attribute types
@@ -167,10 +175,6 @@ protected override IList<JsonProperty> CreateProperties(Type type, MemberSeriali
167
175
if ( typeof ( IDescriptor ) . IsAssignableFrom ( type ) )
168
176
return PropertiesOfAll ( type , memberSerialization ) ;
169
177
170
- var nativeType = type . Assembly ( ) == ThisAssembly ;
171
- if ( nativeType )
172
- return base . CreateProperties ( type , memberSerialization ) ;
173
-
174
178
return base . CreateProperties ( type , memberSerialization ) ;
175
179
}
176
180
@@ -232,7 +236,7 @@ protected bool ShouldSerializeRouting(object o, JsonProperty prop)
232
236
return ! resolved . IsNullOrEmpty ( ) ;
233
237
}
234
238
235
- private static void ApplyBuildInSerializers ( MemberInfo member , JsonProperty property )
239
+ private static void ApplyBuiltInConverters ( MemberInfo member , JsonProperty property )
236
240
{
237
241
var attributes = member . GetCustomAttributes ( ) . ToList ( ) ;
238
242
var stringy = attributes . Any ( a => StringSignalTypes . Contains ( a . GetType ( ) ) ) ;
@@ -248,12 +252,6 @@ private static void ApplyBuildInSerializers(MemberInfo member, JsonProperty prop
248
252
property . Converter = MachineLearningDateTimeConverter ;
249
253
}
250
254
251
- private static void ApplyBuildInSerializersForType ( Type type , JsonContract contract )
252
- {
253
- if ( type . GetTypeInfo ( ) . GetCustomAttribute < StringEnumAttribute > ( ) != null )
254
- contract . Converter = StringEnumConverter ;
255
- }
256
-
257
255
/// <summary> Renames/Ignores a property based on the connection settings mapping or custom attributes for the property </summary>
258
256
private void ApplyPropertyOverrides ( MemberInfo member , JsonProperty property )
259
257
{
@@ -270,7 +268,7 @@ private void ApplyPropertyOverrides(MemberInfo member, JsonProperty property)
270
268
property . Ignored = overrideIgnore . Value ;
271
269
}
272
270
273
- private void ApplyShouldSerializer ( JsonProperty property )
271
+ private void ApplyShouldSerialize ( JsonProperty property )
274
272
{
275
273
if ( property . PropertyType == typeof ( QueryContainer ) )
276
274
property . ShouldSerialize = o => ShouldSerializeQueryContainer ( o , property ) ;
0 commit comments