Преобразование необработанного текста в данные JSON - PullRequest
0 голосов
/ 24 июня 2019

Я пытаюсь реализовать синтаксический анализатор, который преобразует необработанные текстовые данные в формат JSON. Текст будет представлен следующим образом.

(пример)

  • # Название меню
  • ## Название раздела
  • ### Название товара
  • > Описание
  • > Цена
  • > URL изображения (необязательно)

  • ### Название товара 2

  • > Описание
  • > Цена
  • > URL изображения (необязательно)

Порядок элементов будет в заданном порядке.

Нужный вывод, который я хочу, выглядит следующим образом:

{
 name: "menu name",
 sections: [
  {
     name: "Section name",
     items: [{
        name: "item name",
        description: "description",
        price: 23.00
     },
     {
        name: "item name",
        description: "description",
        price: 43.00
     },
    ]
   }
 ]
}

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

Я попробовал решение, использующее разбор строк, и оно работает нормально, но я хотел знать стандартный метод выполнения этой задачи.

1 Ответ

1 голос
/ 24 июня 2019

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

Программа, представленная ниже, создаст один объект JSON для каждого «меню» (т. Е. Каждое вхождение строки «# Имя меню»).

menus.jq

# The next key name in an item
def keyname:
  if (.description | not) then "description"
  elif (.price | not) then "price"
  elif (.url | not) then "url"
  else length|tostring
  end;

def menu_name($s):
  . += [{name: $s}];
def section_name($s):
  .[-1].sections += [{name: $s}];
def item_name($s):
  .[-1].sections[-1].items += [{name: $s}];
def item_description($s):
  (.[-1].sections[-1].items[-1]|keyname) as $key
  | .[-1].sections[-1].items[-1][$key] = $s;

reduce inputs as $in ([];
  if $in|test("^ *$") then .       # ignore blank lines
  else ($in|split(" ")) as $tokens
  | ($in|sub("[^ ]* *";"")) as $phrase
  | if $tokens[0] == "#"     then menu_name( $phrase )
    elif $tokens[0] == "##"  then section_name( $phrase )
    elif $tokens[0] == "###" then item_name( $phrase )
    elif $tokens[0] == ">"   then item_description( $phrase )
    else .
    end
  end )
| .[]  # stream the menus

1010 * Воззвание * Выше используется inputs, поэтому крайне важен параметр командной строки -n: jq -n -f menus.jq input.txt выход

С вводом образца:

{
  "name": "Menu Name",
  "sections": [
    {
      "name": "Section Name",
      "items": [
        {
          "name": "Item Name",
          "description": "Description",
          "price": "Price",
          "url": "Image URL (optional)"
        },
        {
          "name": "Item Name 2",
          "description": "Description",
          "price": "Price",
          "url": "Image URL (optional)"
        }
      ]
    }
  ]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...