Как разобрать неверный JSON с помощью Lark? - PullRequest
0 голосов
/ 16 января 2019

Давайте начнем с рассмотрения простого парсера json с использованием lark:

import sys

from lark import Lark, Transformer, v_args

json_grammar = r"""
    ?start: value

    ?value: object
          | array
          | string
          | SIGNED_NUMBER      -> number
          | "true"             -> true
          | "false"            -> false
          | "null"             -> null

    array  : "[" [value ("," value)*] "]"
    object : "{" [pair ("," pair)*] "}"
    pair   : string ":" value

    string : ESCAPED_STRING

    %import common.ESCAPED_STRING
    %import common.SIGNED_NUMBER
    %import common.WS

    %ignore WS
"""


class TreeToJson(Transformer):
    @v_args(inline=True)
    def string(self, s):
        return s[1:-1].replace('\\"', '"')

    array = list
    pair = tuple
    object = dict
    number = v_args(inline=True)(float)

    def null(self, _): return None

    def true(self, _): return True

    def false(self, _): return False


if __name__ == '__main__':
    json_parser = Lark(json_grammar, parser='lalr', lexer='standard', transformer=TreeToJson())
    parse = json_parser.parse

    dct = parse('''
        {
            "empty_object" : {},
            "empty_array"  : [],
            "booleans"     : { "YES" : true, "NO" : false },
            "numbers"      : [ 0, 1, -2, 3.3, 4.4e5, 6.6e-7 ],
            "strings"      : [ "This", [ "And" , "That", "And a \\"b" ] ],
            "nothing"      : null
        }
    ''')
    print(dct)

Приведенный выше пример взят с официального сайта examples , и он может анализировать действительный json.

Пока все хорошо, но мой вопрос заключается в том, как я могу расширить эту грамматику и преобразователь, чтобы она также могла анализировать недопустимые строки json, такие как приведенная ниже:

dct = parse('''
    [
        // Item1
        { "key1": "value1" },
        // Item2
        { "key2": "value2", "key3": ["a","b",] },
        // Item3
        { "key4": [{"key5":"value5"},] },
    ]
''')

Моя главная цель - иметь возможность парсинга ресурсов SublimeText (которые являются надмножеством json), ST использует sublime_api.decode_value за кулисами ... но эта функция закрыта, поэтому я не могу ее использовать. Кроме того, я не нашел ни одной библиотеки pypi, которая бы работала из коробки для данных такого типа, поэтому я решил, что мне лучше всего будет попытаться написать собственный нестандартный парсер "invalid json".

1 Ответ

0 голосов
/ 16 января 2019

Библиотека demjson очень хорошо разбирает сомнительный json:

import demjson

str = '''
    [
        // Item1
        { "key1": "value1" },
        // Item2
        { "key2": "value2", "key3": ["a","b",] },
        // Item3
        { "key4": [{"key5":"value5"},] },
    ]
'''

print(demjson.decode(str))

Результат:

[{'key1': 'value1'}, {'key2': 'value2', 'key3': ['a', 'b']}, {'key4': [{'key5': 'value5'}]}]
...