Давайте начнем с рассмотрения простого парсера 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".