4
4
using System ;
5
5
using System . Text . Json ;
6
6
using System . Text . Json . Nodes ;
7
+ using Microsoft . OpenApi . Any ;
7
8
using Microsoft . OpenApi . Models ;
8
9
9
10
namespace Microsoft . OpenApi . Validations . Rules
@@ -41,28 +42,28 @@ public static bool IsEmailAddress(this string input)
41
42
}
42
43
43
44
public static void ValidateDataTypeMismatch (
44
- IValidationContext context ,
45
- string ruleName ,
46
- JsonNode value ,
47
- OpenApiSchema schema )
45
+ IValidationContext context ,
46
+ string ruleName ,
47
+ JsonNode value ,
48
+ OpenApiSchema schema )
48
49
{
49
50
if ( schema == null )
50
51
{
51
52
return ;
52
53
}
53
54
54
- var type = schema . Type . ToString ( ) ;
55
+ // convert value to JsonElement and access the ValueKind property to determine the type.
56
+ var jsonElement = JsonDocument . Parse ( JsonSerializer . Serialize ( value ) ) . RootElement ;
57
+
58
+ var type = ( string ) schema . Type ;
55
59
var format = schema . Format ;
56
60
var nullable = schema . Nullable ;
57
61
58
- // convert JsonNode to JsonElement
59
- JsonElement element = value . GetValue < JsonElement > ( ) ;
60
-
61
62
// Before checking the type, check first if the schema allows null.
62
63
// If so and the data given is also null, this is allowed for any type.
63
64
if ( nullable )
64
65
{
65
- if ( element . ValueKind is JsonValueKind . Null )
66
+ if ( jsonElement . ValueKind is JsonValueKind . Null )
66
67
{
67
68
return ;
68
69
}
@@ -73,26 +74,23 @@ public static void ValidateDataTypeMismatch(
73
74
// It is not against the spec to have a string representing an object value.
74
75
// To represent examples of media types that cannot naturally be represented in JSON or YAML,
75
76
// a string value can contain the example with escaping where necessary
76
- if ( element . ValueKind is JsonValueKind . String )
77
+ if ( jsonElement . ValueKind is JsonValueKind . String )
77
78
{
78
79
return ;
79
80
}
80
81
81
82
// If value is not a string and also not an object, there is a data mismatch.
82
- if ( element . ValueKind is not JsonValueKind . Object )
83
+ if ( value is not JsonObject anyObject )
83
84
{
84
85
context . CreateWarning (
85
86
ruleName ,
86
87
DataTypeMismatchedErrorMessage ) ;
87
88
return ;
88
89
}
89
90
90
- // Else, cast element to object
91
- var anyObject = value . AsObject ( ) ;
92
-
93
91
foreach ( var kvp in anyObject )
94
92
{
95
- string key = kvp . Key ;
93
+ var key = kvp . Key ;
96
94
context . Enter ( key ) ;
97
95
98
96
if ( schema . Properties != null &&
@@ -116,23 +114,20 @@ public static void ValidateDataTypeMismatch(
116
114
// It is not against the spec to have a string representing an array value.
117
115
// To represent examples of media types that cannot naturally be represented in JSON or YAML,
118
116
// a string value can contain the example with escaping where necessary
119
- if ( element . ValueKind is JsonValueKind . String )
117
+ if ( jsonElement . ValueKind is JsonValueKind . String )
120
118
{
121
119
return ;
122
120
}
123
121
124
122
// If value is not a string and also not an array, there is a data mismatch.
125
- if ( element . ValueKind is not JsonValueKind . Array )
123
+ if ( value is not JsonArray anyArray )
126
124
{
127
125
context . CreateWarning (
128
126
ruleName ,
129
127
DataTypeMismatchedErrorMessage ) ;
130
128
return ;
131
129
}
132
130
133
- // Else, cast element to array
134
- var anyArray = value . AsArray ( ) ;
135
-
136
131
for ( var i = 0 ; i < anyArray . Count ; i ++ )
137
132
{
138
133
context . Enter ( i . ToString ( ) ) ;
@@ -147,7 +142,7 @@ public static void ValidateDataTypeMismatch(
147
142
148
143
if ( type == "integer" && format == "int32" )
149
144
{
150
- if ( element . ValueKind is not JsonValueKind . Number )
145
+ if ( jsonElement . ValueKind is not JsonValueKind . Number )
151
146
{
152
147
context . CreateWarning (
153
148
ruleName ,
@@ -159,7 +154,7 @@ public static void ValidateDataTypeMismatch(
159
154
160
155
if ( type == "integer" && format == "int64" )
161
156
{
162
- if ( element . ValueKind is not JsonValueKind . Number )
157
+ if ( jsonElement . ValueKind is not JsonValueKind . Number )
163
158
{
164
159
context . CreateWarning (
165
160
ruleName ,
@@ -169,16 +164,21 @@ public static void ValidateDataTypeMismatch(
169
164
return ;
170
165
}
171
166
172
- if ( type == "integer" && element . ValueKind is not JsonValueKind . Number )
167
+ if ( type == "integer" && jsonElement . ValueKind is not JsonValueKind . Number )
173
168
{
174
- context . CreateWarning (
175
- ruleName ,
176
- DataTypeMismatchedErrorMessage ) ;
169
+ if ( jsonElement . ValueKind is not JsonValueKind . Number )
170
+ {
171
+ context . CreateWarning (
172
+ ruleName ,
173
+ DataTypeMismatchedErrorMessage ) ;
174
+ }
175
+
176
+ return ;
177
177
}
178
178
179
179
if ( type == "number" && format == "float" )
180
180
{
181
- if ( element . ValueKind is not JsonValueKind . Number )
181
+ if ( jsonElement . ValueKind is not JsonValueKind . Number )
182
182
{
183
183
context . CreateWarning (
184
184
ruleName ,
@@ -190,7 +190,7 @@ public static void ValidateDataTypeMismatch(
190
190
191
191
if ( type == "number" && format == "double" )
192
192
{
193
- if ( element . ValueKind is not JsonValueKind . Number )
193
+ if ( jsonElement . ValueKind is not JsonValueKind . Number )
194
194
{
195
195
context . CreateWarning (
196
196
ruleName ,
@@ -202,7 +202,7 @@ public static void ValidateDataTypeMismatch(
202
202
203
203
if ( type == "number" )
204
204
{
205
- if ( element . ValueKind is not JsonValueKind . Number )
205
+ if ( jsonElement . ValueKind is not JsonValueKind . Number )
206
206
{
207
207
context . CreateWarning (
208
208
ruleName ,
@@ -214,7 +214,7 @@ public static void ValidateDataTypeMismatch(
214
214
215
215
if ( type == "string" && format == "byte" )
216
216
{
217
- if ( element . ValueKind is not JsonValueKind . String )
217
+ if ( jsonElement . ValueKind is not JsonValueKind . String )
218
218
{
219
219
context . CreateWarning (
220
220
ruleName ,
@@ -226,7 +226,7 @@ public static void ValidateDataTypeMismatch(
226
226
227
227
if ( type == "string" && format == "date" )
228
228
{
229
- if ( element . ValueKind is not JsonValueKind . String )
229
+ if ( jsonElement . ValueKind is not JsonValueKind . String )
230
230
{
231
231
context . CreateWarning (
232
232
ruleName ,
@@ -238,7 +238,7 @@ public static void ValidateDataTypeMismatch(
238
238
239
239
if ( type == "string" && format == "date-time" )
240
240
{
241
- if ( element . ValueKind is not JsonValueKind . String )
241
+ if ( jsonElement . ValueKind is not JsonValueKind . String )
242
242
{
243
243
context . CreateWarning (
244
244
ruleName ,
@@ -250,7 +250,7 @@ public static void ValidateDataTypeMismatch(
250
250
251
251
if ( type == "string" && format == "password" )
252
252
{
253
- if ( element . ValueKind is not JsonValueKind . String )
253
+ if ( jsonElement . ValueKind is not JsonValueKind . String )
254
254
{
255
255
context . CreateWarning (
256
256
ruleName ,
@@ -262,7 +262,7 @@ public static void ValidateDataTypeMismatch(
262
262
263
263
if ( type == "string" )
264
264
{
265
- if ( element . ValueKind is not JsonValueKind . String )
265
+ if ( jsonElement . ValueKind is not JsonValueKind . String )
266
266
{
267
267
context . CreateWarning (
268
268
ruleName ,
@@ -274,7 +274,7 @@ public static void ValidateDataTypeMismatch(
274
274
275
275
if ( type == "boolean" )
276
276
{
277
- if ( element . ValueKind is not JsonValueKind . True || element . ValueKind is not JsonValueKind . True )
277
+ if ( jsonElement . ValueKind is not JsonValueKind . True && jsonElement . ValueKind is not JsonValueKind . False )
278
278
{
279
279
context . CreateWarning (
280
280
ruleName ,
0 commit comments