Преобразование рекурсивных данных POST в объект JSON - PullRequest
0 голосов
/ 03 мая 2019

Я POST отправляю JSON через javascript до конечной точки в виде данных формы, а не в теле. Я делаю это, чтобы избежать дополнительного поиска 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


Решение

Stringify 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
    }
});

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...