Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"array" type should be (list, tuple) #148

Closed
igrishaev opened this issue Feb 18, 2014 · 10 comments
Closed

"array" type should be (list, tuple) #148

igrishaev opened this issue Feb 18, 2014 · 10 comments

Comments

@igrishaev
Copy link

Currently, it's impossible to use tuples as arrays, only lists.
Array type should be a tuple like (list, tuple).

default_types = {
            "array" : (list, tuple), "boolean" : bool, "integer" : int_types, ...

or

default_types = {
            "array" : array_types, "boolean" : bool, "integer" : int_types, ...

, where

array_types = (list, tuple)
@Julian
Copy link
Member

Julian commented Feb 18, 2014

Hey!

simplejson will never give you a tuple when loading a JSON array.

That said, if you want to actually allow tuples, you can provide a mapping of types that you want to consider to be arrays by providing a types dictionary to a validator's __init__.

@igrishaev
Copy link
Author

Julian, thank you for you advice, I've figured out with types={'array': (list, tuple)} parameter in .validate()

I needed to validate some python dict with nested tuples.

@eirnym
Copy link

eirnym commented Jul 1, 2015

JSON parsers are not only source for your library. For example I check all requests and all responses.

@Julian
Copy link
Member

Julian commented Jul 1, 2015

Yup -- I'm glad, I think the current APIs should be usable for whatever use case you have in mind, please feel free to reach out if you have any issues.

@eirnym
Copy link

eirnym commented Jul 1, 2015

Could you please extend array type if you think so?

@Julian
Copy link
Member

Julian commented Jul 3, 2015

What is it you mean by extend the array type? As the post two comments above you mentioned, Draft4Validatot(schema, types=dict(array=(list, tuple))) is how you say that you want JSON arrays to allow tuples

Once again be concrete on where you are having issues.

@CMCDragonkai
Copy link

Is there a way to do Draft4Validator(...) without specifying the draft version? Just Validator(..., types=...)? In my case the version is specified within the schema. Or is that possible by just using jsonschema.validate(instance=..., schema=..., types=dict(array=(list, tuple)))?

@pekkaklarck
Copy link

Something has apparently changed and using Draft4Validator(schema, types=dict(array=(list, tuple))) proposed by @Julian above doesn't work anymore. Testing with v4.17.3:

>>> Draft4Validator(schema, types=dict(array=(list, tuple)))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: create.<locals>.Validator.__init__() got an unexpected keyword argument 'types'

I honestly don't see why tuples couldn't be accepted by default. It's true that json.load won't return tuples, but then again json.dump accepts them just fine. I have data that uses tuples that I'd like to validate before converting it to JSON and this limitation is pretty annoying.

@stojan-jovic
Copy link

stojan-jovic commented Apr 16, 2024

Previous method is deprecated from the jsonschema version 4.x (or something like that), but now the same can be achieved as follows:

from jsonschema import validators, Draft201909Validator  # Provide draft version as you need...


def list_and_tuple(checker, instance):
    return isinstance(instance, (list, tuple))


type_checker = Draft201909Validator.TYPE_CHECKER.redefine(
    'array', list_and_tuple,
)

CustomArrayValidator = validators.extend(
    Draft201909Validator,
    type_checker=type_checker,
)

# A sample schema, like what we'd get from json.load()
schema = {
    'type': 'object',
    'properties': {
        'price': {'type': 'number'},
        'name': {'type': 'string'},
        'features': {'type': 'array'}
    }
}
CustomArrayValidator.check_schema(schema)

# If no exception is raised by validate(), the instance is valid.
validator = CustomArrayValidator(schema=schema)
validator.validate(
    instance={
        'name': 'Eggs',
        'price': 34.99,
        # 'features': [1, 2, 3],  # Valid!
        'features': (1, 2, 3),  # Valid!
        # 'features': {1, 2, 3}  # Not valid!
    }
)

It requires much more code than earlier, but it's possible to make tuples valid.

Btw, I agree that it should be supported by default.

@mmulich
Copy link

mmulich commented Oct 18, 2024

I'm in agreement with @pekkaklarck, @stojan-jovic and others, tuple should be a valid default.

Building off @stojan-jovic's workaround, I've updated a portion of their code to grab the latest validator.

import jsonschema

LatestValidator = jsonschema.validators._LATEST_VERSION

def list_and_tuple(checker, instance):
    return isinstance(instance, (list, tuple))

type_checker = LatestValidator.TYPE_CHECKER.redefine(
    'array', list_and_tuple,
)

CustomValidator = jsonschema.validators.extend(
    LatestValidator,
    type_checker=type_checker,
)

Thanks @stojan-jovic!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants