Repository: horejsek/python-fastjsonschema

Issue:
Support for validating tuples as arrays?
Would a PR be accepted that modified fastjsonschema to validate a `tuple` object as an array?  Possible as an optional behavior?

The array validation function here https://github.com/horejsek/python-fastjsonschema/blob/master/fastjsonschema/generator.py#L275 only accepts a list, and I have a situation where I have data structures coming in from httpapi endpoints and custom RPC endpoints; and the RPC endpoints have all their array objects deserialized as tuples; so currently i'm having to wrap the fastjsonschema callable objects with a function that will recursively list-ify all values I pass in for validation.

This is similar to https://github.com/Julian/jsonschema/issues/148

Discussion:

Patch:
diff --git a/fastjsonschema/draft04.py b/fastjsonschema/draft04.py
index 01cc07e..6c50a21 100644
--- a/fastjsonschema/draft04.py
+++ b/fastjsonschema/draft04.py
@@ -11,7 +11,7 @@ JSON_TYPE_TO_PYTHON_TYPE = {
     'number': 'int, float',
     'integer': 'int',
     'string': 'str',
-    'array': 'list',
+    'array': 'list, tuple',
     'object': 'dict',
 }
 
diff --git a/fastjsonschema/generator.py b/fastjsonschema/generator.py
index fc5b4b1..17cebd6 100644
--- a/fastjsonschema/generator.py
+++ b/fastjsonschema/generator.py
@@ -281,7 +281,7 @@ class CodeGenerator:
         if variable_name in self._variables:
             return
         self._variables.add(variable_name)
-        self.l('{variable}_is_list = isinstance({variable}, list)')
+        self.l('{variable}_is_list = isinstance({variable}, (list, tuple))')
 
     def create_variable_is_dict(self):
         """


Test patch:
diff --git a/tests/test_array.py b/tests/test_array.py
index 33f6a06..3d77435 100644
--- a/tests/test_array.py
+++ b/tests/test_array.py
@@ -134,3 +134,35 @@ def test_different_items_without_additional_items(asserter, value, expected):
         ],
         'additionalItems': False,
     }, value, expected)
+
+
+@pytest.mark.parametrize('value, expected', [
+    ((), ()),
+    (('a',), ('a',)),
+    (('a', 'b'), ('a', 'b')),
+    (('a', 'b', 3), JsonSchemaException('data[2] must be string', value=3, name='data[2]',
+                                        definition={'type': 'string'}, rule='type')),
+])
+def test_tuples_as_arrays(asserter, value, expected):
+    asserter({
+        '$schema': 'http://json-schema.org/draft-06/schema',
+        'type': 'array',
+        'items':
+            {'type': 'string'},
+
+    }, value, expected)
+
+
+@pytest.mark.parametrize('value, expected', [
+    ({'a': [], 'b': ()}, {'a': [], 'b': ()}),
+    ({'a': (1, 2), 'b': (3, 4)}, {'a': (1, 2), 'b': (3, 4)}),
+])
+def test_mixed_arrays(asserter, value, expected):
+    asserter({
+        'type': 'object',
+        'properties': {
+            'a': {'type': 'array'},
+            'b': {'type': 'array'},
+        },
+    }, value, expected)
+
diff --git a/tests/test_integration.py b/tests/test_integration.py
index 5ea2c08..27135f9 100644
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -52,6 +52,10 @@ definition = {
         [9, 'world', [1], {'a': 'a', 'b': 'b', 'd': 'd'}, 42, 3],
         [9, 'world', [1], {'a': 'a', 'b': 'b', 'c': 'abc', 'd': 'd'}, 42, 3],
     ),
+    (
+        (9, 'world', (1,), {'a': 'a', 'b': 'b', 'd': 'd'}, 42, 3),
+        (9, 'world', (1,), {'a': 'a', 'b': 'b', 'c': 'abc', 'd': 'd'}, 42, 3),
+    ),
     (
         [9, 'world', [1], {'a': 'a', 'b': 'b', 'c': 'xy'}, 42, 3],
         [9, 'world', [1], {'a': 'a', 'b': 'b', 'c': 'xy'}, 42, 3],