Source code for json_api_doc.serialization
# -*- coding: utf-8 -*-
from collections import OrderedDict
[docs]def serialize(data={}, errors={}, meta={}, links={}):
"""
:param data: Dict with data to serialize
:param errors: Dict with error data to serialize
:param meta: Dict with meta data to serialize
:returns: Dict normalized as a valid JSON API document
"""
if data and errors:
raise AttributeError("""Only 'data' or 'errors' can be present in a
valid JSON API document""")
included = OrderedDict()
res = {}
if data:
if isinstance(data, list):
res["data"] = list(
map(lambda item: _serialize(item, included), data))
else:
res["data"] = _serialize(data, included)
elif isinstance(data, list):
res["data"] = []
if included:
res["included"] = list(included.values())
if meta:
res["meta"] = meta
if errors:
res["errors"] = errors
if links:
res["links"] = links
return res or {"data": None}
def _serialize(data, included):
obj_type = data.get("$type", None)
if obj_type is None:
raise AttributeError("Missing object $type")
res = _expand(data, included)
res["type"] = obj_type
obj_id = data.get("id", None)
if obj_id is not None:
res["id"] = obj_id
return res
def _expand(data, included):
res = {}
attrs = {}
rels = {}
for k, v in data.items():
if k in ["$type", "id"]:
continue
if isinstance(v, dict):
embedded, is_res = _expand_included(v, included)
if is_res:
rels[k] = {
"data": embedded
}
else:
attrs[k] = embedded
elif isinstance(v, list):
embedded = list(map(lambda l: _expand_included(l, included), v))
if all(map(lambda i: i[1], embedded)):
rels[k] = {
"data": list(map(lambda i: i[0], embedded))
}
else:
attrs[k] = list(map(lambda i: i[0], embedded))
else:
attrs[k] = v
if len(attrs):
res["attributes"] = attrs
if len(rels):
res["relationships"] = rels
return res
def _expand_included(data, included):
if not isinstance(data, dict):
return data, False
typ = data.get("$type", None)
id = data.get("id", None)
if typ is None or id is None:
# not a sub-resource, return as is
return data, False
if typ is not None and id is not None and (typ, id) not in included:
serialized = _expand(data, included)
serialized["type"] = typ
serialized["id"] = id
included[(typ, id)] = serialized
return {"type": typ, "id": id}, True