The following works for json whose outermost container is an object like { ... }
@service.json
def index():
data = request.vars
#fields are now accessible via data["fieldname"] or data.fieldname
#processing must be done to turn Storage object into dict()
return data_as_dict
If you post a list however, it does not work
POST:
[
{"test": 1}
]
data
will be an empty Storage object and data[0]
will be None
The workaround is simple:
@service.json #so output is still returned as json
def index():
data = json.loads(request.body.read())
return data
data
is now a dict in cases of object style JSON (easier to work with than a Storage object imo) and a native list when the JSON is a list.
My question is why is this not the default behaviour? Why should a JSON service not accept valid JSON?
The @service.json decorator simply registers a function so it can be accessed via a controller that returns a Service
object. The decorator ensures that the service controller returns a JSON response when the decorated function is called, but it does nothing regarding the processing of JSON input.
In any case, your problem is not with the @service.json
decorator but with a misunderstanding regarding request.vars
. request.vars
is a dictionary-like object that is populated with keys and values from the query string and/or the request body (if the request body includes form variables or a JSON object of keys and values). It is not intended to simply be a copy of any arbitrary data structure that is posted in the request body. So, if you post a JSON array in the request body, it would not make sense to copy that array to request.vars
, as it is not the appropriate type of data structure. If you want to post a JSON array, the correct way to process it is to read the request body, as you have done.
Also, note that because your index
function does not take any arguments and therefore does not take advantage of the @service
decorator's ability to map parameters from the HTTP request into function arguments, you could simplify your code by foregoing the @service
decorator and accessing the index
function more directly:
def index():
data = json.loads(request.body.read())
return data
Assuming index
is in the default.py controller, you could post JSON to /yourapp/default/index.json
(note the .json
extension), and you will get back a JSON response.