описание проблемы
Я пишу простой анализатор JSON, чтобы выполнить синтаксический анализ строк JSON. Я получаю строки JSON со случайной структурой и хочу экспортировать синтаксическую структуру. В результате я хочу получить древовидную структуру, которая описывает формат строки JSON (ключ, значение, массивы и т. д.) И типы каждого элемента. Я уже нашел определение синтаксиса JSON (описано ниже)
object
{}
{ members }
members
pair
pair , members
pair
string : value
array
[]
[ elements ]
elements
value
value , elements
value
string
number
object
array
true
false
null
Пример
Строка JSON:
{"widget": {
"null": null,
"window": {
153: "This is string",
"boolean": true,
"int": 500,
"float": 5.555
}
}}
И я хочу получить что-то вроде:
{ KEY_STR : {
KEY_STR : null
KEY_ARRAY : {
KEY_INT: VALUE_STR,
KEY_STR: VALUE_BOOL,
KEY_STR: VALUE_INT,
KEY_STR: VALUE_FLOAT
}
}}
Я использую JAVA с библиотекой GSON.
Как я хочу это использовать
Мне интересно экспортировать абстрактное дерево, чтобы автоматически создавать свои собственные сообщения
Мой вопрос
Я начал реализовывать это с помощью JsonParser. Я разбираю объект JSON, а затем определяю для каждого ключа и значения типа. Но мне интересно, нахожусь ли я на правильном пути или открываю колесо. Есть ли что-нибудь для экспорта абстрактного синтаксического дерева, или я должен реализовать это сам?
Кстати: как вы планируете изобразить дерево? Этот пример с KEY_STR и т. д. Не совсем Java.
привет @tevemadar, Может я не так хорошо описал свою проблему, потому что немного запутался. Позвольте мне объяснить всю картину этого. Я получаю кучу строк JSON со случайной структурой. Моя первая цель - представить структуру JSON в общем формате. Я хочу этого, потому что хочу перебирать значения JSON и использовать собственное другое входное значение. Я думал, что дерево синтаксиса - это мощное представление для перебора json.
Кроме того, я хочу изменить имена / ключи JSON, чтобы заменить их своим собственным набором ключей. С помощью двух слов я просто хочу сохранить структуру всех этих JSON и перебирать их с другим набором значений и ключа. Возможно, лучший подход - каждый раз создавать новый JSON из существующего и заменять все, что я хочу. По этой причине я ищу здесь, может это поможет




Я понятия не имею, что будет экспортировать JsonParser. Но в целом анализ чего-либо, затем экспорт формы AST из структуры данных AST, чтение AST и последующее извлечение значений из прочитанного AST кажутся просто огромными накладными расходами, которые нужно создавать и поддерживать.
Что вам нужно сделать, так это встроить синтаксический анализатор JSON в свое приложение, проанализировать JSON в структуре данных AST и просто обработать эту структуру AST напрямую. Откровенно говоря, JSON достаточно прост, чтобы вы могли написать свой собственный парсер рекурсивного спуска для синтаксического анализа JSON и построения AST, что вернет вас к первому решению. См. https://stackoverflow.com/a/2336769/120163
Если вы абсолютно настаивать при экспорте, вы можете найти инструменты, которые сделают это на полке. Наш набор инструментов для реинжиниринга программного обеспечения DMS сделает это, хотя может быть немного тяжеловесным для такого рода приложений.
Одна из приятных особенностей JSON - простая грамматика. Вот грамматика, которую использует DMS:
-- JSON.atg: JSON domain grammar for DMS
-- Copyright (C) 2011-2018 Semantic Designs, Inc.; All Rights Reserved
--
-- Update history:
-- Date Initials Changes Made
-- 2011/09/02 CW Created
--
-- Note that dangling commas in lists are off-spec
-- but I (CW) hate dealing with them
--
-- I'm not sure if JSON is supposed to have more than one entity per file
-- but I'm allowing it for robustness
--
-- TODO: name/value pair lists should be associative-commutative
JSON_text = ;
JSON_text = JSON_text object ;
JSON_text = JSON_text array ;
-- unordered set of name/value pairs
-- should be able to use an associative-commutative property directive
object = '{' name_value_pair_list '}' ;
-- empty production is for empty list, but will also allow multiple commas
name_value_pair_list = ;
name_value_pair_list = name_value_pair_list ',' ;
name_value_pair_list = name_value_pair_list name_value_pair ;
name_value_pair = STRING ':' value ;
-- ordered collection of values
array = '[' value_list ']' ;
value_list = value ;
value_list = value_list ',' value ;
value_list = value_list ',' value ',' ;
value = STRING ;
value = NUMBER_INT ;
value = NUMBER_FLOAT ;
value = object ;
value = array ;
value = 'true' ;
value = 'false' ;
value = 'null' ;
Да, это почти точно соответствует абстрактной грамматике, предоставленной OP.
Теперь вы можете попросить DMS проанализировать файл и экспортировать его AST с помощью этой команды:
run ..\DomainParser +AST ..\..\..\Examples\One.js
Для файла JSON One.js, содержащего этот текст:
{
"from": "http://json.org/example.html"
}
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
<rest of file snipped>
Парсер выдает S-выражение:
(JSON_text@JSON=2#59406e0^0 Line 1 Column 1 File C:/DMS/Domains/JSON/Examples/One.js
(JSON_text@JSON=2#2199f60^1#59406e0:1 Line 1 Column 1 File C:/DMS/Domains/JSON/Examples/One.js
(JSON_text@JSON=2#21912a0^1#2199f60:1 Line 1 Column 1 File C:/DMS/Domains/JSON/Examples/One.js
(JSON_text@JSON=2#593df00^1#21912a0:1 Line 1 Column 1 File C:/DMS/Domains/JSON/Examples/One.js
|(JSON_text@JSON=2#593d420^1#593df00:1 Line 1 Column 1 File C:/DMS/Domains/JSON/Examples/One.js
| (JSON_text@JSON=2#593c580^1#593d420:1 Line 1 Column 1 File C:/DMS/Domains/JSON/Examples/One.js
| (JSON_text@JSON=1#593bec0^1#593c580:1 Line 1 Column 1 File C:/DMS/Domains/JSON/Examples/One.js)JSON_text
| (object@JSON=4#593c560^1#593c580:2 Line 1 Column 1 File C:/DMS/Domains/JSON/Examples/One.js
| (name_value_pair_list@JSON=7#593c520^1#593c560:1 Line 2 Column 5 File C:/DMS/Domains/JSON/Examples/One.js
| |(name_value_pair_list@JSON=5#593c420^1#593c520:1 Line 2 Column 5 File C:/DMS/Domains/JSON/Examples/One.js)name_value_pair_list
| |(name_value_pair@JSON=8#593c4e0^1#593c520:2 Line 2 Column 5 File C:/DMS/Domains/JSON/Examples/One.js
| | (STRING@JSON=24#593c400^1#593c4e0:1[`from'] Line 2 Column 5 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | (STRING@JSON=24#593c480^1#593c4e0:2[`http://json.org/example.html'] Line 2 Column 13 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| |)name_value_pair#593c4e0
| )name_value_pair_list#593c520
| )object#593c560
| )JSON_text#593c580
| (object@JSON=4#593d400^1#593d420:2 Line 5 Column 1 File C:/DMS/Domains/JSON/Examples/One.js
| (name_value_pair_list@JSON=7#593d3c0^1#593d400:1 Line 6 Column 5 File C:/DMS/Domains/JSON/Examples/One.js
| (name_value_pair_list@JSON=5#593c5c0^1#593d3c0:1 Line 6 Column 5 File C:/DMS/Domains/JSON/Examples/One.js)name_value_pair_list
| (name_value_pair@JSON=8#593d380^1#593d3c0:2 Line 6 Column 5 File C:/DMS/Domains/JSON/Examples/One.js
| |(STRING@JSON=24#593c5a0^1#593d380:1[`glossary'] Line 6 Column 5 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| |(object@JSON=4#593d360^1#593d380:2 Line 6 Column 17 File C:/DMS/Domains/JSON/Examples/One.js
| | (name_value_pair_list@JSON=7#593d340^1#593d360:1 Line 7 Column 9 File C:/DMS/Domains/JSON/Examples/One.js
| | (name_value_pair_list@JSON=6#593c720^1#593d340:1 Line 7 Column 9 File C:/DMS/Domains/JSON/Examples/One.js
| | (name_value_pair_list@JSON=7#593c6c0^1#593c720:1 Line 7 Column 9 File C:/DMS/Domains/JSON/Examples/One.js
| | |(name_value_pair_list@JSON=5#593c600^1#593c6c0:1 Line 7 Column 9 File C:/DMS/Domains/JSON/Examples/One.js)name_value_pair_list
| | |(name_value_pair@JSON=8#593c640^1#593c6c0:2 Line 7 Column 9 File C:/DMS/Domains/JSON/Examples/One.js
| | | (STRING@JSON=24#593c5e0^1#593c640:1[`title'] Line 7 Column 9 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | (STRING@JSON=24#593c620^1#593c640:2[`example glossary'] Line 7 Column 18 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | |)name_value_pair#593c640
| | )name_value_pair_list#593c6c0
| | )name_value_pair_list#593c720
| | (name_value_pair@JSON=8#593d320^1#593d340:2 Line 8 Column 17 File C:/DMS/Domains/JSON/Examples/One.js
| | (STRING@JSON=24#593c700^1#593d320:1[`GlossDiv'] Line 8 Column 17 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | (object@JSON=4#593d300^1#593d320:2 Line 8 Column 29 File C:/DMS/Domains/JSON/Examples/One.js
| | |(name_value_pair_list@JSON=7#593d2e0^1#593d300:1 Line 9 Column 13 File C:/DMS/Domains/JSON/Examples/One.js
| | | (name_value_pair_list@JSON=6#593c880^1#593d2e0:1 Line 9 Column 13 File C:/DMS/Domains/JSON/Examples/One.js
| | | (name_value_pair_list@JSON=7#593c820^1#593c880:1 Line 9 Column 13 File C:/DMS/Domains/JSON/Examples/One.js
| | | (name_value_pair_list@JSON=5#593c760^1#593c820:1 Line 9 Column 13 File C:/DMS/Domains/JSON/Examples/One.js)name_value_pair_list
| | | (name_value_pair@JSON=8#593c7e0^1#593c820:2 Line 9 Column 13 File C:/DMS/Domains/JSON/Examples/One.js
| | | |(STRING@JSON=24#593c740^1#593c7e0:1[`title'] Line 9 Column 13 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | |(STRING@JSON=24#593c780^1#593c7e0:2[`S'] Line 9 Column 22 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | )name_value_pair#593c7e0
| | | )name_value_pair_list#593c820
| | | )name_value_pair_list#593c880
| | | (name_value_pair@JSON=8#593d2c0^1#593d2e0:2 Line 10 Column 25 File C:/DMS/Domains/JSON/Examples/One.js
| | | (STRING@JSON=24#593c860^1#593d2c0:1[`GlossList'] Line 10 Column 25 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | (object@JSON=4#593d2a0^1#593d2c0:2 Line 10 Column 38 File C:/DMS/Domains/JSON/Examples/One.js
| | | (name_value_pair_list@JSON=7#593d280^1#593d2a0:1 Line 11 Column 17 File C:/DMS/Domains/JSON/Examples/One.js
| | | |(name_value_pair_list@JSON=5#593c8c0^1#593d280:1 Line 11 Column 17 File C:/DMS/Domains/JSON/Examples/One.js)name_value_pair_list
| | | |(name_value_pair@JSON=8#593d260^1#593d280:2 Line 11 Column 17 File C:/DMS/Domains/JSON/Examples/One.js
| | | | (STRING@JSON=24#593c8a0^1#593d260:1[`GlossEntry'] Line 11 Column 17 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | | (object@JSON=4#593d240^1#593d260:2 Line 11 Column 31 File C:/DMS/Domains/JSON/Examples/One.js
| | | | (name_value_pair_list@JSON=7#593d200^1#593d240:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | (name_value_pair_list@JSON=6#593d160^1#593d200:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | |(name_value_pair_list@JSON=7#593d120^1#593d160:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | (name_value_pair_list@JSON=6#593cde0^1#593d120:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | (name_value_pair_list@JSON=7#593cd60^1#593cde0:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | (name_value_pair_list@JSON=6#593cca0^1#593cd60:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | |(name_value_pair_list@JSON=7#593cc60^1#593cca0:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | (name_value_pair_list@JSON=6#593cc00^1#593cc60:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | (name_value_pair_list@JSON=7#593cb80^1#593cc00:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | (name_value_pair_list@JSON=6#593cb00^1#593cb80:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | |(name_value_pair_list@JSON=7#593cac0^1#593cb00:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | | (name_value_pair_list@JSON=6#593ca60^1#593cac0:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | | (name_value_pair_list@JSON=7#593ca00^1#593ca60:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | | (name_value_pair_list@JSON=5#593c900^1#593ca00:1 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js)name_value_pair_list
| | | | | | | (name_value_pair@JSON=8#593c9c0^1#593ca00:2 Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | | |(STRING@JSON=24#593c8e0^1#593c9c0:1[`ID'] Line 12 Column 21 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | | | | | |(STRING@JSON=24#593c920^1#593c9c0:2[`SGML'] Line 12 Column 27 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | | | | | )name_value_pair#593c9c0
| | | | | | | )name_value_pair_list#593ca00
| | | | | | | )name_value_pair_list#593ca60
| | | | | | | (name_value_pair@JSON=8#593caa0^1#593cac0:2 Line 13 Column 41 File C:/DMS/Domains/JSON/Examples/One.js
| | | | | | | (STRING@JSON=24#593ca40^1#593caa0:1[`SortAs'] Line 13 Column 41 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | | | | | (STRING@JSON=24#593ca80^1#593caa0:2[`SGML'] Line 13 Column 51 File C:/DMS/Domains/JSON/Examples/One.js)STRING
| | | | | | | )name_value_pair#593caa0
| | | | | | |)name_value_pair_list#593cac0
Я обрезал вывод, потому что на самом деле никто не хочет обрабатывать дерево видеть. Теперь в дереве есть много «лишних» вещей, таких как расположение узла, номера строк исходного кода, которые можно легко удалить или проигнорировать.
В чем смысл? «Создавать мои собственные сообщения автоматически» не кажется очень жизнеспособным на основе примера вывода, поскольку «KEY_STR» кажется немного шире, чем «виджет», по крайней мере, для меня.