@@ -131,7 +131,7 @@ var validate = exports._validate = function(/*Any*/instance,/*Object*/schema,/*O
131
131
if ( schema . items ) {
132
132
var itemsIsArray = schema . items instanceof Array ;
133
133
var propDef = schema . items ;
134
- for ( i = 0 , l = value . length ; i < l ; i += 1 ) {
134
+ for ( var i = 0 , l = value . length ; i < l ; i += 1 ) {
135
135
if ( itemsIsArray )
136
136
propDef = schema . items [ i ] ;
137
137
if ( options . coerce )
@@ -145,6 +145,16 @@ var validate = exports._validate = function(/*Any*/instance,/*Object*/schema,/*O
145
145
if ( schema . maxItems && value . length > schema . maxItems ) {
146
146
addError ( "There must be a maximum of " + schema . maxItems + " in the array" ) ;
147
147
}
148
+ if ( schema . uniqueItems ) {
149
+ for ( var i = 0 , l = value . length ; i < l ; i += 1 ) {
150
+ for ( var j = i + 1 ; j < l ; j += 1 ) {
151
+ if ( ! compareItems ( value [ i ] , value [ j ] ) ) {
152
+ addError ( "The items in the array must be unique." ) ;
153
+ break ;
154
+ }
155
+ }
156
+ }
157
+ }
148
158
} else if ( schema . properties || schema . additionalProperties ) {
149
159
errors . concat ( checkObj ( value , schema . properties , path , schema . additionalProperties ) ) ;
150
160
}
@@ -194,8 +204,8 @@ var validate = exports._validate = function(/*Any*/instance,/*Object*/schema,/*O
194
204
if ( typeof instance != 'object' || instance instanceof Array ) {
195
205
errors . push ( { property :path , message :"an object is required" } ) ;
196
206
}
197
-
198
- for ( var i in objTypeDef ) {
207
+
208
+ for ( var i in objTypeDef ) {
199
209
if ( objTypeDef . hasOwnProperty ( i ) ) {
200
210
var value = instance [ i ] ;
201
211
// skip _not_ specified properties
@@ -212,7 +222,7 @@ var validate = exports._validate = function(/*Any*/instance,/*Object*/schema,/*O
212
222
}
213
223
}
214
224
}
215
- for ( i in instance ) {
225
+ for ( var i in instance ) {
216
226
if ( instance . hasOwnProperty ( i ) && ! ( i . charAt ( 0 ) == '_' && i . charAt ( 1 ) == '_' ) && objTypeDef && ! objTypeDef [ i ] && additionalProp === false ) {
217
227
if ( options . filter ) {
218
228
delete instance [ i ] ;
@@ -239,6 +249,39 @@ var validate = exports._validate = function(/*Any*/instance,/*Object*/schema,/*O
239
249
}
240
250
return errors ;
241
251
}
252
+ // compare a value against another for equality (for uniqueItems)
253
+ function compareItems ( item1 , item2 ) {
254
+ if ( typeof item1 !== typeof item2 ) {
255
+ return false ;
256
+ }
257
+ if ( Array . isArray ( item1 ) ) {
258
+ if ( item1 . length !== item2 . length ) {
259
+ return false ;
260
+ }
261
+ for ( var i = 0 , l = item1 . length ; i < l ; i += 1 ) {
262
+ if ( ! compareItems ( item1 [ i ] , item2 [ i ] ) ) {
263
+ return false ;
264
+ }
265
+ }
266
+ return true ;
267
+ }
268
+ if ( item1 instanceof Object ) {
269
+ var item1Keys = Object . keys ( item1 ) ;
270
+ var item2Keys = Object . keys ( item2 ) ;
271
+ if ( item1Keys . length !== item2Keys . length ) {
272
+ return false ;
273
+ }
274
+ for ( var i = 0 , l = item1Keys . length ; i < l ; i += 1 ) {
275
+ var key = item1Keys [ i ] ;
276
+ if ( ! item2 . hasOwnProperty ( key ) ||
277
+ ! compareItems ( item1 [ key ] , item2 [ key ] ) ) {
278
+ return false ;
279
+ }
280
+ }
281
+ return true ;
282
+ }
283
+ return item1 === item2 ;
284
+ }
242
285
if ( schema ) {
243
286
checkProp ( instance , schema , '' , _changing || '' ) ;
244
287
}
0 commit comments