88using System . Text ;
99using System . Text . RegularExpressions ;
1010using System . Net ;
11-
11+ using Newtonsoft . Json . Linq ;
1212
1313namespace netmockery
1414{
@@ -20,14 +20,16 @@ public static Endpoint ReadEndpoint(string jsonString, string rootDir, JSONDefau
2020 }
2121 }
2222
23- public class JSONParam
23+ public class JSONParam : JSONObjectWithAdditionalData
2424 {
2525 public string name ;
2626 public string @default ;
2727 public string description ;
2828
2929 public JSONParam Validated ( )
3030 {
31+ ThrowExceptionIfAdditionalData ( ) ;
32+
3133 if ( name == null )
3234 {
3335 throw new ArgumentException ( $ "Parameter missing name") ;
@@ -52,7 +54,7 @@ public JSONParam Validated()
5254 }
5355 }
5456
55- public class JSONTest
57+ public class JSONTest : JSONObjectWithAdditionalData
5658 {
5759 public string name ;
5860 public string method ;
@@ -69,6 +71,8 @@ public class JSONTest
6971
7072 public JSONTest Validated ( )
7173 {
74+ ThrowExceptionIfAdditionalData ( ) ;
75+
7276 if ( requestpath == null )
7377 {
7478 throw new ArgumentNullException ( nameof ( requestpath ) ) ;
@@ -111,7 +115,7 @@ public NetmockeryTestCase CreateTestCase(string directory)
111115 }
112116 }
113117
114- public class JSONResponse
118+ public class JSONResponse : JSONObjectWithAdditionalData
115119 {
116120 public JSONRequestMatcher match ;
117121
@@ -133,10 +137,20 @@ public class JSONResponse
133137
134138 public JSONResponse Validated ( )
135139 {
140+ ThrowExceptionIfAdditionalData ( ) ;
136141 if ( match == null )
137142 {
138143 throw new ArgumentException ( "match must be specified" ) ;
139144 }
145+
146+ if ( replacements != null )
147+ {
148+ foreach ( var replacement in replacements )
149+ {
150+ replacement . ThrowExceptionIfAdditionalData ( ) ;
151+ }
152+ }
153+
140154 var mutuallyExclusive = new [ ] { literal , file , script , forward } ;
141155 var mutExWithValues = from value in mutuallyExclusive where value != null select value ;
142156 if ( mutExWithValues . Count ( ) != 1 )
@@ -207,7 +221,7 @@ from jsonreplacement in replacements
207221
208222 }
209223
210- public class JSONRequestMatcher
224+ public class JSONRequestMatcher : JSONObjectWithAdditionalData
211225 {
212226 public string methods ;
213227 public string xpath ;
@@ -216,6 +230,8 @@ public class JSONRequestMatcher
216230
217231 public RequestMatcher CreateRequestMatcher ( )
218232 {
233+ ThrowExceptionIfAdditionalData ( ) ;
234+
219235 RequestMatcher retval ;
220236 if ( xpath != null )
221237 {
@@ -224,6 +240,7 @@ public RequestMatcher CreateRequestMatcher()
224240 {
225241 foreach ( var jsonNs in namespaces )
226242 {
243+ jsonNs . ThrowExceptionIfAdditionalData ( ) ;
227244 xpathMatcher . AddNamespace ( jsonNs . prefix , jsonNs . ns ) ;
228245 }
229246 }
@@ -245,19 +262,33 @@ public RequestMatcher CreateRequestMatcher()
245262 }
246263 }
247264
248- public class JSONXPathNamespace
265+ public class JSONXPathNamespace : JSONObjectWithAdditionalData
249266 {
250267 public string prefix ;
251268 public string ns ;
252269 }
253270
254- public class JSONReplacement
271+ public class JSONReplacement : JSONObjectWithAdditionalData
255272 {
256273 public string search ;
257274 public string replace ;
258275 }
259276
260- public class JSONEndpoint
277+ public class JSONObjectWithAdditionalData
278+ {
279+ [ JsonExtensionData ]
280+ public IDictionary < string , JToken > AdditionalData ;
281+
282+ public void ThrowExceptionIfAdditionalData ( )
283+ {
284+ if ( AdditionalData != null )
285+ {
286+ throw new ArgumentException ( $ "Unknown JSON attributes: " + string . Join ( ", " , from key in AdditionalData . Keys select $ "'{ key } '") ) ;
287+ }
288+ }
289+ }
290+
291+ public class JSONEndpoint : JSONObjectWithAdditionalData
261292 {
262293 public string name ;
263294 public string pathregex ;
@@ -266,6 +297,7 @@ public class JSONEndpoint
266297
267298 public Endpoint CreateEndpoint ( string rootDir , JSONDefaults globalDefaults )
268299 {
300+ ThrowExceptionIfAdditionalData ( ) ;
269301 var endpoint = new Endpoint ( name , pathregex )
270302 {
271303 Directory = rootDir
@@ -278,6 +310,10 @@ public Endpoint CreateEndpoint(string rootDir, JSONDefaults globalDefaults)
278310 JsonConvert . DeserializeObject < JSONDefaults > ( File . ReadAllText ( endpointDefaultsFile ) )
279311 :
280312 null ;
313+ if ( endpointDefaults != null )
314+ {
315+ endpointDefaults . ThrowExceptionIfAdditionalData ( ) ;
316+ }
281317
282318 foreach ( var jsonResponse in responses )
283319 {
@@ -330,7 +366,7 @@ private void applyDefaults(JSONDefaults defaults, JSONResponse jsonResponse)
330366 }
331367 }
332368
333- public class JSONDefaults
369+ public class JSONDefaults : JSONObjectWithAdditionalData
334370 {
335371 public string contenttype ;
336372 public string charset ;
0 commit comments