首页 > ajax中json嵌套字典传入后端flask时无法显示

ajax中json嵌套字典传入后端flask时无法显示

第一种情况:前端采用jquery,js中产生一个变量

var mydata1={"G2":{"fs1":1,"fs2":2}}
$('#calculate').bind('click', function() {
    console.log(mydata1);
    $.getJSON('/pile_calculate',mydata1,function(data) {$(".Rsk").text(data.result);});
return false;
});

后端采用flask

@app.route('/pile_calculate',methods=['GET','POST'])
def pile_calculate():
    fs=request.args.get('G2')
    print('start')
    print(fs)       #out None
    print(type(fs)) #out <class 'NoneType'>
    print('end')
    return jsonify(result=fs)

    

第二种情况,前端采用jquery,js中产生一个变量

var mydata2={"fs1":1,"fs2":2}
$('#calculate').bind('click', function() {
    console.log(mydata2);
    $.getJSON('/pile_calculate',mydata2,function(data) {$(".Rsk").text(data.result);});
return false;
});

后端采用flask,

@app.route('/pile_calculate',methods=['GET','POST'])
def pile_calculate():
    fs=request.args.get('fs1')
    print('start')
    print(fs)         #out 1
    print(type(fs))   #out <class 'str'>
    print('end')
    return jsonify(result=fs)

为什么第一种情况字典里面嵌套字典就会出错啊,第二种情况就是对的啊,麻烦各位有经验的牛人帮忙解答以下啊,谢谢!


后端flask这里还可以再优化一下,尽量不要用Python的eval方法。
改进后的Python代码如下:

data = json.loads(request.args.get('G1'))
# 这里将从前端接收的数据转换成Json格式,我的理解,在Python中Json就类似字典
# 这里的data是dict类型

print(data['fs1'])
# Output: 1

return jsonify(data)
# 将data转换为json格式再传给前端

  1. JQuery的getJSON方法使用HTTP GET方法

  2. getJSON的data参数会被转换为查询字符串拼接在URL后面,如:

let data = {abc: 12, foo: 34};
$.getJSON('/path/to/getjson',data, function(d) {
});
// 这句话实际的请求是:http://www.host.com/path/to/getjson?abc=12&foo=34

let data = {abc: {foo: 23, df: 34}, mok: 33};
$.getJSON('/path/to/getjson', data, function(d) {
});
// 这句话实际的请求是:http://www.host.com/path/to/getjson?abc[foo]=23&abc[df]=34&mok=33
// 这里实际上会把请求URL做URLencode处理, 为了方便直接写了

不知道flask会把abc[foo]=23&abc[df]=34&mok=33解析成什么


经过多日baidu之后解决问题,主要查阅了:

第一步:首先我们了解一下jQuery的ajax方法。

   $.getJSON(myurl,mydata,success(data,status,xhr)) ;

getJSON函数的定义:通过HTTP GET请求载入JSON 数据。(这个从其名字叫做getJSON即可知道)
上述函数等同于

    $.ajax({
        type:"get",
        url:"myurl",
        data:mydata,    //发送到服务器的数据,可以自行构造
        dataType:"json",    //预期服务器返回的数据类型
        success:callback    //callback回调函数,这里一般可要求服务器返回特定数据
    });
    关于ajax()中的参数设置可参考http://www.w3school.com.cn/jquery/ajax_ajax.asp
    

示例1:

//前端js主要代码:
let myurl="pile_calculate"
let mydata1={"fs1":1,"fs2":2};
$.ajax({
    type:"get",
    url:myurl,
    data:mydata1,
    dataType:"json",
    success:callback_function()
}); 
//ajax提交后请求参数附加在url中:http://127.0.0.1/pile_calculate?fs1=1&fs2=2

//后端flask主要代码:        
request.args.get('fs1') //out: 1 后端flask中解析数据正常
request.args.get('fs2') //out: 2 后端flask中解析数据正常

示例2:

//前端js主要代码:
let myurl="pile_calculate"
let mydata2={"G1":{"fs1":1,"fs2":2}};
$.ajax({
    type:"get",
    url:myurl,
    data:mydata2,
    dataType:"json",
    success:callback_function()
}); 
//ajax提交后请求参数附加在url中:http://127.0.0.1/pile_calculate?G1[fs1]=1&G1[fs2]=2
    
//后端flask主要代码:   
request.args.get('G1') //out:None 后端flask中解析数据不正常

那么问题来了,
question:为什么flask对于mydata1可以正常解析,对于myata2则不能解析呢?

第二步:我们了解一下flask的request.args方法。

request.args返回值类型为ImmutableMultiDict,一个类似dict的数据类型,dict具有的方法,它均具备,同时可用to_dict()方法将其转换成dict类型。
现直接引用http://werkzeug.pocoo.org/docs/0.11/datastructures/#http-related上关于MultiDict的介绍,方便大家了解:

A MultiDict is a dictionary subclass customized to deal with multiple values for the same key which is for example used by the parsing functions in the wrappers. This is necessary because some HTML form elements pass multiple values for the same key.
MultiDict implements all standard dictionary methods. Internally, it saves all values for a key as a list, but the standard dict access methods will only return the first value for a key. If you want to gain access to the other values, too, you have to use the list methods as explained below.

answer:因为前端get请求时将发送到服务器的数据mydata2由{"G1":{"fs1":1,"fs2":2}}转换成G1[fs1]=1&G1[fs2]=2
也就意味着后端flask中request.args=ImmutableMultiDict([('G1[fs1]', '1'), ('G1[fs2]', '2')])
并非我们期望的request.args= ImmutableMultiDict([("G1", "{fs1:1}"), ("G1", "{fs2:2}")])
故后端flask语句应改成

request.args.get('G1[fs1]') //out: 1 后端flask中解析数据正常
request.args.get('G1[fs2]') //out: 2 后端flask中解析数据正常 

修改后,虽然可以正常显示,但明显不利于编程,特别对于字典嵌套多层字典的情况,更为不利。

第三步:改进

//前端js主要代码,主要改进的内容是利用JSON.stringify()将json对象转换成字符串,以避免get提交时对json对象的破坏:
        let myurl="pile_calculate"
        let mydata2={"G1":{"fs1":1,"fs2":2}};
        $.ajax({
            type:"get",
            url:myurl,
            data:JSON.stringify(mydata2),//将json对象转换成字符串
            dataType:"json",
            success:callback_function()
        }); 
        //ajax提交后请求参数附加在url中:http://127.0.0.1/pile_calculate?{"G1":{"fs1":1,"fs2":2}}
        
//后端flask主要代码,主要改进的内容是将返回值转换成dict,而后提取dict的第一个key,并通过eval()函数将字符串化的key转换成dict:
        // request.args返回值为:ImmutableMultiDict([('{"G2":{"fs1":1,"fs2":2}}', '')]) 
        myargs=request.args.to_dict()  
        //out :{"{'G2':{'fs1':1,'fs2':2}}":""}
        for outerkey in myargs.keys():
            return eval(outerkey)  //eval(outerkey) 将字符串形式的outerkey类型转换为字典
            
            

以上是本人的浅见,有改进或不对的地方,欢迎大家喷水。
另外,由于本人是segment新手,排版比较乱,望同学们见谅。

【热门文章】
【热门文章】