Returns a validator for a JSON array. If the property is missing, it is treated as if it were []. Otherwise, it must be a list. If validate_item=False, it's treated as if it were (lambda x: x) - i.e. any item is considered valid, and is unchanged. If validate_item is a type or a tu
(validate_item=False, vectorize=False, size=None)
| 172 | |
| 173 | |
| 174 | def array(validate_item=False, vectorize=False, size=None): |
| 175 | """Returns a validator for a JSON array. |
| 176 | |
| 177 | If the property is missing, it is treated as if it were []. Otherwise, it must |
| 178 | be a list. |
| 179 | |
| 180 | If validate_item=False, it's treated as if it were (lambda x: x) - i.e. any item |
| 181 | is considered valid, and is unchanged. If validate_item is a type or a tuple, |
| 182 | it's treated as if it were json.of_type(validate). |
| 183 | |
| 184 | Every item in the list is replaced with validate_item(item) in-place, propagating |
| 185 | any exceptions raised by the latter. If validate_item is a type or a tuple, it is |
| 186 | treated as if it were json.of_type(validate_item). |
| 187 | |
| 188 | If vectorize=True, and the value is neither a list nor a dict, it is treated as |
| 189 | if it were a single-element list containing that single value - e.g. "foo" is |
| 190 | then the same as ["foo"]; but {} is an error, and not [{}]. |
| 191 | |
| 192 | If size is not None, it can be an int, a tuple of one int, a tuple of two ints, |
| 193 | or a set. If it's an int, the array must have exactly that many elements. If it's |
| 194 | a tuple of one int, it's the minimum length. If it's a tuple of two ints, they |
| 195 | are the minimum and the maximum lengths. If it's a set, it's the set of sizes that |
| 196 | are valid - e.g. for {2, 4}, the array can be either 2 or 4 elements long. |
| 197 | """ |
| 198 | |
| 199 | if not validate_item: |
| 200 | validate_item = lambda x: x |
| 201 | elif isinstance(validate_item, type) or isinstance(validate_item, tuple): |
| 202 | validate_item = of_type(validate_item) |
| 203 | |
| 204 | if size is None: |
| 205 | validate_size = lambda _: True |
| 206 | elif isinstance(size, set): |
| 207 | size = {operator.index(n) for n in size} |
| 208 | validate_size = lambda value: ( |
| 209 | len(value) in size |
| 210 | or "must have {0} elements".format( |
| 211 | " or ".join(str(n) for n in sorted(size)) |
| 212 | ) |
| 213 | ) |
| 214 | elif isinstance(size, tuple): |
| 215 | assert 1 <= len(size) <= 2 |
| 216 | size = tuple(operator.index(n) for n in size) |
| 217 | min_len, max_len = (size + (None,))[0:2] |
| 218 | validate_size = lambda value: ( |
| 219 | "must have at least {0} elements".format(min_len) |
| 220 | if len(value) < min_len |
| 221 | else "must have at most {0} elements".format(max_len) |
| 222 | if max_len is not None and len(value) < max_len |
| 223 | else True |
| 224 | ) |
| 225 | else: |
| 226 | size = operator.index(size) |
| 227 | validate_size = lambda value: ( |
| 228 | len(value) == size or "must have {0} elements".format(size) |
| 229 | ) |
| 230 | |
| 231 | def validate(value): |