requests.Request 中参数data与json的区别

requests.Request使用参数data传值

  • 当使用data传值时,入参为object类型,在发送前,request将参数前置处理,在body中处理成格式为k1=v1&k2=v2 格式,content_type:application/x-www-form-urlencoded

import requests
import json
if __name__ == '__main__':
    playload={
        "person":json.dumps({
            "name":"Milton",
            "age": "18"
        })
    }
    resp = requests.post("http://localhost:8000/rftester/dd_msg/",data=playload)
    # resp = requests.post("http://localhost:8000/rftester/dd_msg/", json=json.dumps(playload))

预处理格式如下:

content_type:application/x-www-form-urlencoded
data body: person={"name": "Milton", "age": "18"}

这种情况下,服务端可以通过各个key将参数提取,如person = request.POST.get("person")

  • 注意:当如上字典多层嵌套时,只能解析到第一层,value值必须为字符串,否则会解析出错,如下

import requests
import json
if __name__ == '__main__':
    playload={
        "person":{
            "name":"Milton",
            "age": "18"
        }
    }
    resp = requests.post("http://localhost:8000/rftester/dd_msg/",data=playload)
    # resp = requests.post("http://localhost:8000/rftester/dd_msg/", json=json.dumps(playload))

预处理后,格式如下:

content_type:application/x-www-form-urlencoded
data body: person=name&person=age

这种情况,服务端解析,会解析不到预期的入参,请注意!!!

requests.Request使用参数json传值

  • 当request使用json传值时,入参为json字符串,在发送前,request将参数前置处理,在body中处理成格式为json字符串,content_type:application/json

import requests
import json
if __name__ == '__main__':
    playload={
        "person":{
            "name":"Milton",
            "age": "18"
        }
    }
    # resp = requests.post("http://localhost:8000/rftester/dd_msg/",data=playload)
    resp = requests.post("http://localhost:8000/rftester/dd_msg/", json=json.dumps(playload))
    print(resp.text)

预处理格式如下:

content_type:application/json
json body: "{\"person\": {\"name\": \"Milton\", \"age\": \"18\"}}"

这种情况,服务端直接解析body,可以解析出合法json字符串,可以转换成对象。如:body=json.loads(request.body)

修改源码,使得使用data传参时,支持解析嵌套字典。

找到源码位置:site-packages\requests\models.py
_encode_params方法修改如下:

    @staticmethod
    def _encode_params(data):
        """Encode parameters in a piece of data.

        Will successfully encode parameters when passed as a dict or a list of
        2-tuples. Order is retained if data is a list of 2-tuples but arbitrary
        if parameters are supplied as a dict.
        """

        if isinstance(data, (str, bytes)):
            return data
        elif hasattr(data, 'read'):
            return data
        elif hasattr(data, '__iter__'):
            result = []
            for k, vs in to_key_val_list(data):
                if isinstance(vs, basestring) or not hasattr(vs, '__iter__'):
                    vs = [vs]
                    for v in vs:
                        if v is not None:
                            result.append(
                                (k.encode('utf-8') if isinstance(k, str) else k,
                                 v.encode('utf-8') if isinstance(v, str) else v))
                if isinstance(vs,dict):
                    result.append((k.encode('utf-8') if isinstance(k, str) else k,
                                 complexjson.dumps(vs).encode('utf-8')))
            return urlencode(result, doseq=True)
        else:
            return data

测试结果如下

import requests
import json
if __name__ == '__main__':
    playload={
        "person":{
            "name":"Milton",
            "age": "18"
        },
        "address":"GZ"
    }
    requests.Request()
    resp = requests.post("http://localhost:8000/rftester/dd_msg/",data=playload)

预处理参数如下:

content_type:application/x-www-form-urlencoded
data body: person={"name": "Milton", "age": "18"}&address=GZ

通过以上修改源码后,data参数已经可以支持嵌套多层字典!!!

posted @ 2020-10-09 10:57  鲨鱼逛大街  阅读(3979)  评论(0编辑  收藏  举报