2

Вопрос по parsing, json, python, javascript – Python: анализ JSON-подобных структур данных Javascript (с запятыми)

Я хотел бы проанализировать JSON-подобные строки. Их единственное отличие от обычного JSON - это наличиеcontiguous commas в массивах. Когда есть две такие запятые, это неявно означает, чтоnull должен быть вставлен между ними. Пример:

       JSON-like:  ["foo",,,"bar",[1,,3,4]]
      Javascript:  ["foo",null,null,"bar",[1,null,3,4]]
Decoded (Python):  ["foo", None, None, "bar", [1, None, 3, 4]]

Роднойjson.JSONDecoder Класс не позволяет мне изменить поведение парсинга массива. Я могу изменить парсер только для объектов (dicts), int, float, strings (предоставив функции kwargsJSONDecoder(), посмотри пожалуйстадокумент).

Так значит ли это, что я должен написать JSON-парсер с нуля? Код Pythonjson доступно, но это довольно беспорядок. Я бы предпочел использовать его внутренности вместо дублирования кода!

  • Error: User Rate Limit ExceedednullError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от zopieux
  • Error: User Rate Limit Exceededre.sub(r'(?<=,)\s*,', ' null,')Error: User Rate Limit Exceededre.sub(r'(?<=,),', ' null,', s).

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded,,Error: User Rate Limit Exceeded,null,Error: User Rate Limit Exceeded,,,Error: User Rate Limit Exceeded,null,,Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded,null,,Error: User Rate Limit Exceeded

    от zopieux
  • Error: User Rate Limit Exceededmy answerError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от zopieux
  • Error: User Rate Limit ExceedednullError: User Rate Limit Exceeded

    от
  • Проверьте мой вопрос, чтобы увидеть, как я его решил, и следуйте по нему для более быстрых способов:stackoverflow.com/questions/17901156/…

    от Joren Van Severen
6 ответов
  • 1

    Это хакерский способ сделать это

    но одно решение состоит в том, чтобы просто сделать некоторую модификацию строки в данных JSON-иша, чтобы привести их в соответствие перед синтаксическим анализом.

    import re
    import json
    
    not_quite_json = '["foo",,,"bar",[1,,3,4]]'
    not_json = True
    while not_json:
        not_quite_json, not_json = re.subn(r',\s*,', ', null, ', not_quite_json)
    

    Что оставляет нас с:

    '["foo", null, null, "bar",[1, null, 3,4]]'
    

    Затем мы можем сделать:

    json.loads(not_quite_json)
    

    Давать нам:

    ['foo', None, None, 'bar', [1, None, 3, 4]]
    

    Обратите внимание, что это не так просто, как замена, так как замена также вставляет запятые, которые могут нуждаться в замене. Учитывая это, вы должны проходить циклы до тех пор, пока больше не будет сделано никаких замен. Здесь я использовал простое регулярное выражение, чтобы сделать работу.

  • 3

    Маленький & amp; простой обходной путь, чтобы попробовать:

    Convert JSON-like data to strings. Replace ",," with ",null,". Convert it to whatever is your representation.

    Let JSONDecoder(), do the heavy lifting.

    & 3. can be omitted if you already deal with strings.

    (И если преобразование в строку нецелесообразно, обновите ваш вопрос этой информацией!)

  • 1

    Я посмотрел рекомендации Taymon

    pyparsing и успешно взломал приведенный пример.Вот чтобы удовлетворить мои потребности. Хорошо работает при симуляции Javascripteval() ноfails one situation: запятые. Там должна быть дополнительная запятая & # x2013; см. тесты ниже & # x2013; но я не могу найти какой-либо правильный способ реализовать это.

    from pyparsing import *
    
    TRUE = Keyword("true").setParseAction(replaceWith(True))
    FALSE = Keyword("false").setParseAction(replaceWith(False))
    NULL = Keyword("null").setParseAction(replaceWith(None))
    
    jsonString = dblQuotedString.setParseAction(removeQuotes)
    jsonNumber = Combine(Optional('-') + ('0' | Word('123456789', nums)) +
                        Optional('.' + Word(nums)) +
                        Optional(Word('eE', exact=1) + Word(nums + '+-', nums)))
    
    jsonObject = Forward()
    jsonValue = Forward()
    # black magic begins
    commaToNull = Word(',,', exact=1).setParseAction(replaceWith(None))
    jsonElements = ZeroOrMore(commaToNull) + Optional(jsonValue) + ZeroOrMore((Suppress(',') + jsonValue) | commaToNull)
    # black magic ends
    jsonArray = Group(Suppress('[') + Optional(jsonElements) + Suppress(']'))
    jsonValue << (jsonString | jsonNumber | Group(jsonObject) | jsonArray | TRUE | FALSE | NULL)
    memberDef = Group(jsonString + Suppress(':') + jsonValue)
    jsonMembers = delimitedList(memberDef)
    jsonObject << Dict(Suppress('{') + Optional(jsonMembers) + Suppress('}'))
    
    jsonComment = cppStyleComment
    jsonObject.ignore(jsonComment)
    
    def convertNumbers(s, l, toks):
        n = toks[0]
        try:
            return int(n)
        except ValueError:
            return float(n)
    
    jsonNumber.setParseAction(convertNumbers)
    
    def test():
        tests = (
            '[1,2]',       # ok
            '[,]',         # ok
            '[,,]',        # ok
            '[  , ,  , ]', # ok
            '[,1]',        # ok
            '[,,1]',       # ok
            '[1,,2]',      # ok
            '[1,]',        # failure, I got [1, None], I should have [1]
            '[1,,]',       # failure, I got [1, None, None], I should have [1, None]
        )
        for test in tests:
            results = jsonArray.parseString(test)
            print(results.asList())
    

  • 2

    Вы можете сделать запятую замену

    Lattyware & APOS; s/przemo_li & APOS; s ответы за один проход с использованием выражения lookbehind, то есть "заменить все запятые, которым предшествует просто запятая":

    >>> s = '["foo",,,"bar",[1,,3,4]]'
    
    >>> re.sub(r'(?<=,)\s*,', ' null,', s)
    '["foo", null, null,"bar",[1, null,3,4]]'
    

    Обратите внимание, что это будет работать для небольших вещей, когда можно предположить, что в строковых литералах, например, нет последовательных запятых. Как правило, регулярных выражений недостаточно для решения этой проблемы, иПодход Таймона использование реального парсера - единственное полностью правильное решение.

  • 5

    Поскольку то

    что вы пытаетесь проанализировать, не является JSONper seно, скорее, на другом языке, который очень похож на JSON, вам может понадобиться собственный синтаксический анализатор.

    К счастью, это не так сложно, как кажется. Вы можете использовать генератор парсера Python какPyparsing, JSON может быть полностью определен с помощью довольно простой контекстно-свободной грамматики (я нашел однуВот), так что вы должны иметь возможность изменить его в соответствии со своими потребностями.

  • 0

    Для тех

    кто ищет что-то быстрое и грязное, чтобы преобразовать общие объекты JS (в dicts). Некоторая часть страницы одного реального сайта дает мне объект, который я хотел бы решить. Есть "новые" конструкции для дат, и они в одной строке, без пробелов между ними, поэтому достаточно двух строк:

    data=sub(r'new Date\(([^)])*\)', r'\1', data)
    data=sub(r'([,{])(\w*):', r'\1"\2":', data)
    

    Тогда json.loads () работал нормально. Ваш пробег может варьироваться :)