Skip to content

Commit

Permalink
Support for complex types
Browse files Browse the repository at this point in the history
  • Loading branch information
apiad committed Jan 27, 2018
1 parent 2c3a17b commit 83dffeb
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 4 deletions.
6 changes: 5 additions & 1 deletion docs/operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,8 @@ You can also directly query for `_keys` and `_values` (using sub-queries to sele
{'cube': 27},
{'cube': 64}]}}

```
```

## Moving on

Learn more about [adding type declarations](/types.md) to you api.
30 changes: 29 additions & 1 deletion docs/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,32 @@
layout: default
---

# Adding type declarations
# Adding type annotations

If you add type annotations to your method arguments, `JsonApi` will parse them accordingly before
passing them to corresponding methods. The easiest way to use this feature is to declare your own
classes inheriting from `JsonObj`, so you get a free out-of-the-box dictionary to object constructor.
Make sure to **always** initialize like it's shown below, passing the corresponding `**kwargs` to `JsonApi`:

```python
>>> from pprint import pprint
>>> from jsonapi import JsonApi, JsonObj

>>> class Person(JsonObj):
... def __init__(self, first_name, last_name):
... super(Person, self).__init__(first_name=first_name, last_name=last_name)
...
... def fullname(self):
... return "%s %s" % (self.first_name, self.last_name)

>>> class PersonApi(JsonApi):
... def name_it(self, person: Person):
... return person.fullname()

>>> api = PersonApi()
>>> r = api({ 'name_it': {'$person': {'first_name': 'John',
... 'last_name': 'Doe' }}})
>>> pprint(r)
{'name_it': 'John Doe'}

```
19 changes: 17 additions & 2 deletions jsonapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,12 @@ def _query_obj(self, obj, query):
attr = getattr(obj, key)
args, query = self._extract(value, "$", True)

if hasattr(attr, '__call__'): result = attr(**args)
else: result = attr
if hasattr(attr, '__call__'):
if attr.__annotations__:
args = self._convert(args, attr.__annotations__)
result = attr(**args)
else:
result = attr

payload[key] = self._query(result, query)

Expand All @@ -132,6 +136,17 @@ def _extract(self, query, label, parse=False):

return args, query

def _convert(self, args, annotations):
result = {}

for k,v in args.items():
if k in annotations:
result[k] = annotations[k](**v.dict())
else:
result[k] = v

return result

@staticmethod
def _meta_count(obj, query):
return len(obj)
Expand Down
17 changes: 17 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,20 @@ def test_api_input_string():
assert api(query) == expected_response
assert api(query) == api(query_str)
assert json.dumps(api(query), sort_keys=True) == api(query, encode=True, sort_keys=True)


class Person(JsonObj):
def __init__(self, first_name, last_name):
super(Person, self).__init__(first_name=first_name, last_name=last_name)
def fullname(self):
return "%s %s" % (self.first_name, self.last_name)

class PersonApi(JsonApi):
def name_it(self, person: Person):
return person.fullname()


def test_parse_args():
api = PersonApi()
r = api({ 'name_it': {'$person': {'first_name': 'John',
'last_name': 'Doe' }}})

0 comments on commit 83dffeb

Please sign in to comment.