Skip to content

Commit

Permalink
New ?_shape=array option + tweaks to _shape, closes #245
Browse files Browse the repository at this point in the history
* Default is now ?_shape=arrays (renamed from lists)
* New ?_shape=array returns an array of objects as the root object
* Changed ?_shape=object to return the object as the root
* Updated docs
  • Loading branch information
simonw authored and Simon Willison committed May 2, 2018
1 parent 2565d62 commit a4cc5dc
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 13 deletions.
17 changes: 13 additions & 4 deletions datasette/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ async def view_get(self, request, name, hash, **kwargs):
forward_querystring=False
)
# Deal with the _shape option
shape = request.args.get('_shape', 'lists')
shape = request.args.get('_shape', 'arrays')
if shape in ('objects', 'object', 'array'):
columns = data.get('columns')
rows = data.get('rows')
Expand All @@ -275,17 +275,26 @@ async def view_get(self, request, name, hash, **kwargs):
for row in data['rows']:
pk_string = path_from_row_pks(row, pks, not pks)
object_rows[pk_string] = row
data['rows'] = object_rows
data = object_rows
if error:
data = {
'ok': False,
'error': error,
'database': name,
'database_hash': hash,
}
if shape == 'array':
elif shape == 'array':
data = data['rows']

elif shape == 'arrays':
pass
else:
status_code = 400
data = {
'ok': False,
'error': 'Invalid _shape: {}'.format(shape),
'status': 400,
'title': None,
}
headers = {}
if self.ds.cors:
headers['Access-Control-Allow-Origin'] = '*'
Expand Down
32 changes: 27 additions & 5 deletions docs/json_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,35 @@ The ``_shape`` parameter can be used to access alternative formats for the
``rows`` key which may be more convenient for your application. There are three
options:

* ``?_shape=lists`` - the default option, shown above
* ``?_shape=objects`` - a list of JSON key/value objects
* ``?_shape=object`` - a JSON object keyed using the primary keys of the rows
* ``?_shape=arrays`` - ``"rows"`` is the default option, shown above
* ``?_shape=objects`` - ``"rows"`` is a list of JSON key/value objects
* ``?_shape=array`` - the entire response is an array of objects
* ``?_shape=object`` - the entire response is a JSON object keyed using the primary keys of the rows

``objects`` looks like this::

"rows": [
{
"database": "sf-trees",
...
"rows": [
{
"id": 1,
"value": "Myoporum laetum :: Myoporum"
},
{
"id": 2,
"value": "Metrosideros excelsa :: New Zealand Xmas Tree"
},
{
"id": 3,
"value": "Pinus radiata :: Monterey Pine"
}
]
}

``array`` looks like this::

[
{
"id": 1,
"value": "Myoporum laetum :: Myoporum"
Expand All @@ -82,7 +104,7 @@ options:

``object`` looks like this::

"rows": {
{
"1": {
"id": 1,
"value": "Myoporum laetum :: Myoporum"
Expand Down
38 changes: 34 additions & 4 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,9 @@ def test_jsono_redirects_to_shape_objects(app_client):
assert response.headers['Location'].endswith('?_shape=objects')


def test_table_shape_lists(app_client):
def test_table_shape_arrays(app_client):
response = app_client.get(
'/test_tables/simple_primary_key.json?_shape=lists',
'/test_tables/simple_primary_key.json?_shape=arrays',
gather_request=False
)
assert [
Expand All @@ -359,6 +359,36 @@ def test_table_shape_objects(app_client):
}] == response.json['rows']


def test_table_shape_array(app_client):
response = app_client.get(
'/test_tables/simple_primary_key.json?_shape=array',
gather_request=False
)
assert [{
'id': '1',
'content': 'hello',
}, {
'id': '2',
'content': 'world',
}, {
'id': '3',
'content': '',
}] == response.json


def test_table_shape_invalid(app_client):
response = app_client.get(
'/test_tables/simple_primary_key.json?_shape=invalid',
gather_request=False
)
assert {
'ok': False,
'error': 'Invalid _shape: invalid',
'status': 400,
'title': None,
} == response.json


def test_table_shape_object(app_client):
response = app_client.get(
'/test_tables/simple_primary_key.json?_shape=object',
Expand All @@ -377,7 +407,7 @@ def test_table_shape_object(app_client):
'id': '3',
'content': '',
}
} == response.json['rows']
} == response.json


def test_table_shape_object_compound_primary_Key(app_client):
Expand All @@ -391,7 +421,7 @@ def test_table_shape_object_compound_primary_Key(app_client):
'pk2': 'b',
'content': 'c',
}
} == response.json['rows']
} == response.json


def test_table_with_slashes_in_name(app_client):
Expand Down

0 comments on commit a4cc5dc

Please sign in to comment.