开发者

Handling application/json data with bottle

I'm trying to write a simple server frontend to a python3 application, using a restful JSON-based protocol. So far, bottle seems the best suited framework for the task (it supports python3, handles method dispatching in a nice way, and easily returns JSON.) The problem is parsing the JSON in the input request.

The documentation only mention request.fields and request.files, both I assume refer to multipart/form-data data. No mention of accessing the request data directly.

Peeking at the source code, I can see a request.body object of type BytesIO. json.load refuses to act on it directly, dying in the json lib 开发者_JS百科with can't use a string pattern on a bytes-like object. The proper way to do it may be to first decode the bytes to unicode characters, according to whichever charset was specified in the Content-Type HTTP header. I don't know how to do that; I can see a StringIO class and assume it may hold a buffer of characters instead of bytes, but see no way of decoding a BytesIO to a StringIO, if this is even possible at all.

Of course, it may also be possible to read the BytesIO object into a bytestring, then decode it into a string before passing it to the JSON decoder, but if I understand correctly, that breaks the nice buffering behavior of the whole thing.

Or is there any better way to do it ?


It seems that io.TextIOWrapper from the standard library does the trick !

def parse(request):
    encoding = ... #get encoding from headers
    return json.load(TextIOWrapper(request.body, encoding=encoding))


Here's what I do to read in json on a RESTful service with Python3 and Bottle:

import bson.json_util as bson_json

@app.post('/location/API')
def post_json_example():
    """
    param: _id, value
    return: I usually return something like {"status": "successful", "message": "discription"}
    """

    query_string = bottle.request.query.json
    query_dict = bson_json.loads(query_string)
    _id = query_dict['_id']
    value = query_dict['value']

Then to Test

  • from python3 interpreter, import requests
  • s = request.Session()
  • r = s.post('http://youserver.com:8080/location/API?json {"_id":"540a16663dafb492a0a7626c","value":"test"}')
  • use r.text to verify what was returned.


I wrote an helper to use the good idea of b0fh. After 2 weeks on response.json analyzing, I connect to StackOver Flow and understand that we need a work around

Here is:

def json_app_rqt():
    # about request
    request.accept = 'application/json, text/plain; charset=utf-8'

def json_app_resp():
    # about response
    response.headers['Access-Control-Allow-Origin'] = _allow_origin
    response.headers['Access-Control-Allow-Methods'] = _allow_methods
    # response.headers['Access-Control-Allow-Headers'] = _allow_headers
    response.headers['Content-Type'] = 'application/json; charset=utf-8'

def json_app():
    json_app_rqt()
    json_app_resp()

def get_json_request(rqt):
    with TextIOWrapper(rqt.body, encoding = "UTF-8") as json_wrap:
        json_text = ''.join(json_wrap.readlines())
        json_data = json.loads(json_text)
        return json_data

For the using, we cand do:

if __name__ == "__main__":

    json_app()

    @post("/train_control/:control")
    def do_train_control(control):
        json_app_resp()

        data = get_json_request(request)
        print(json.dumps(data))

        return data

Thanks to all

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜