将递归POST数据转换为JSON对象

时间:2019-05-03 19:19:02

标签: python json python-3.x forms post

我正在通过JavaScript POST将JSON作为表单数据(而不是正文)发送到端点。我这样做是为了避免进行额外的CORS OPTIONS查找。 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
    }
});

0 个答案:

没有答案