Получить абстрактное синтаксическое дерево строки JSON

описание проблемы

Я пишу простой анализатор 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» кажется немного шире, чем «виджет», по крайней мере, для меня.

tevemadar 18.07.2018 19:32

Кстати: как вы планируете изобразить дерево? Этот пример с KEY_STR и т. д. Не совсем Java.

tevemadar 19.07.2018 18:12

привет @tevemadar, Может я не так хорошо описал свою проблему, потому что немного запутался. Позвольте мне объяснить всю картину этого. Я получаю кучу строк JSON со случайной структурой. Моя первая цель - представить структуру JSON в общем формате. Я хочу этого, потому что хочу перебирать значения JSON и использовать собственное другое входное значение. Я думал, что дерево синтаксиса - это мощное представление для перебора json.

Manos Kirtas 19.07.2018 20:49

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

Manos Kirtas 19.07.2018 20:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
4
2 342
1

Ответы 1

Я понятия не имею, что будет экспортировать 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

Я обрезал вывод, потому что на самом деле никто не хочет обрабатывать дерево видеть. Теперь в дереве есть много «лишних» вещей, таких как расположение узла, номера строк исходного кода, которые можно легко удалить или проигнорировать.

Другие вопросы по теме