首页 > 解决方案 > 将递归 POST 数据转换为 JSON 对象

问题描述

POST通过 javascript 将 JSON 作为表单数据发送到端点,而不是在正文中。我这样做是为了避免额外的 CORSOPTIONS查找。JSON 格式如下:

$.ajax({
    url: 'somewhere',
    type: 'POST',
    data: {
        "foo": [
            "a",
            "b"
        ],
        "bar": [
            {
                "biz": [
                    "c",
                    "d"
                ]
            }
        ]
    },
    success: function(response) {
        // something
    }
});

当查询字符串通过时,它看起来像foo%5B%5D=a&foo%5B%5D=b&bar%5B0%5D%5Bbiz%5D%5B%5D=c&bar%5B0%5D%5Bbiz%5D%5B%5D=d

我解析查询字符串:

data = parse.unquote(data)
data = parse.parse_qs(data)
print(json.dumps(data))

但结果 dict/json 是

{
  "foo[]": [
    "a",
    "b"
  ],
  "bar[0][biz][]": [
    "c",
    "d"
  ]
}

这是有问题的,因为我无法遍历原始键。如何将接收到的值转换回其原始 JSON 形式?


这是我到目前为止所拥有的

def findValue(value):
    if isinstance(value, dict):
        value = findValue(list(value.keys())[0])
    elif isinstance(value, list):
        value = findValue(value[0])
    return prepareValue(value)

def prepareKey(data, value=None):
    print(data)
    if isinstance(data, str):
        match = re.findall('([a-zA-Z0-9_-]+)\[([a-zA-Z0-9_-]+)\](.*)', data)
        return match[0]
    if data[2] != '':
        additional = prepareKey(data[2], value)
    else:
        additional = value
    return {data[0]: {data[1]: additional}}

def prepareValue(value):
    if len(value) == 1:
        value = value[0]
    return value

def preparePost(data, newData=False):
    if isinstance(data, dict):
        if not newData:
            newData = {}
        for key, value in data.items():
            match = re.findall('([a-zA-Z0-9_-]+)\[([a-zA-Z0-9_-]+)\](.*)', key)
            if len(match):
                assignment = findValue(value)
                thisData = prepareKey(match[0], assignment)
                newData.update(thisData)
            else:
                newData[key] = prepareValue(value)
    return newData

data = parse.unquote(data)
data = parse.parse_qs(data)
data = preparePost(data)
print(data)

它工作得很好,但在深度嵌套的值上失败了。

这是我正在使用的真正查询:foo=bar&cart%5Bcurrency%5D=USD&cart%5Banalytics%5D%5Blib%5D%5Bintegrations%5D%5B0%5D%5Boptions%5D%5BdefaultAttributes%5D%5BthemeId%5D=38654869555&cart%5Banalytics%5D%5Blib%5D%5Bintegrations%5D%5B0%5D%5Boptions%5D%5BdefaultAttributes%5D%5BcontentLanguage%5D=en

我可以做到,{'foo': 'bar', 'cart': {'currency': 'USD'}}但它失败了cart%5Banalytics%5D%5Blib%5D%5Bintegrations%5D%5B0%5D%5Boptions%5D%5BdefaultAttributes%5D%5BthemeId%5D=38654869555


解决方案

将 JSON 字符串化并发送正确的标头:

$.ajax({
    url: 'somewhere',
    type: 'POST',
    contentType: 'application/x-www-form-urlencoded',
    data: JSON.stringify({
        "foo": [
            "a",
            "b"
        ],
        "bar": [
            {
                "biz": [
                    "c",
                    "d"
                ]
            }
        ]
    }),
    success: function(response) {
        // something
    }
});

标签: pythonjsonpython-3.xformspost

解决方案


推荐阅读