jq transform JSON структура путем нахождения выходных значений во входном вложенном массиве - PullRequest
0 голосов
/ 27 февраля 2020

Прежде всего, извините за заголовок. Хотя английский sh не является моим родным языком, я даже не знаю, как назвать то, что я пытаюсь сделать, на своем родном языке sh.

Что я пытаюсь сделать это взять входные данные (автоматически генерируемые путем загрузки страницы с curl, затем преобразованные из HTML в JSON очень грубым способом с использованием pup) и преобразовать их во что-то, с чем было бы легче работать позже , Входные данные выглядят так:

[
 {
  "children": [
   {
    "class": "label label-info",
    "tag": "span",
    "text": "Lesson"
   },
   {
    "tag": "h2",
    "text": "Is That So?"
   },
   {
    "tag": "p",
    "text": "Learn how to provide shortened answers with そうです and stay in the conversation with そうですか."
   },
   {
    "class": "btn btn-primary",
    "href": "https://www.nihongomaster.com/japanese/lessons/view/62/is-that-so",
    "tag": "a",
    "text": "Read Lesson"
   }
  ],
  "class": "row col-sm-12",
  "tag": "div"
 },
 {
  "children": [
   {
    "class": "label label-warning",
    "tag": "span",
    "text": "Drills"
   },
   {
    "tag": "h2",
    "text": "Yes, That Is So."
   },
   {
    "tag": "p",
    "text": "Practice the phrases and vocab from the lesson, Is That So?"
   }
  ],
  "class": "row col-sm-12",
  "tag": "div"
 }
]

И мой желаемый вывод будет извлекать различные значения из массива children каждого объекта в нечто вроде этого:

[
  {
    "title": "Is That So?", // <-- in other words, find "tag" == "h2" and output "text" value
    "perex": "Learn how to provide shortened answers with そうです and stay in the conversation with そうですか.", // "tag" == "p", "text" value
    "type": "lesson", // "tag" == "span", "text" value (lowercased if possible? Not needed though)
    "link": "https://www.nihongomaster.com/japanese/lessons/view/62/is-that-so" // "tag" == "a", "href" value
  },
  {
    "title": "Yes, That Is So."
    "perex": "Practice the phrases and vocab from the lesson, Is That So?",
    "type": "drills",
    "link": null // Can be missing!
  }
]

Я пробовал различные эксперименты с select, но не дал ни одного полезного результата, поэтому я не уверен, стоит ли делиться своими попытками.

Ответы [ 2 ]

1 голос
/ 27 февраля 2020

Вот простое решение исходной проблемы:

[
  .[]
  | .children
  | { title: [.[] | select(.tag == "h2") | .text][0],
      perex: [.[] | select(.tag == "p") | .text][0],
      type:  [.[] | select(.tag == "span") | .text | ascii_downcase][0],
      link:  [.[] | select(.tag == "a") | .href][0] }
]

Ключевым моментом здесь является использование идиомы [...][0] для обработки всех возможностей в отношении количества элементов в ... ( в том числе 0).

0 голосов
/ 27 февраля 2020

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

select действительно является ключом, но я не использовал его в правильный способ на момент написания вопроса. Вот полная команда jq для выполнения sh моих потребностей, демонстрирующая все вышеперечисленные требования:

  • как выбрать вложенные значения на основе поиска в массиве children;
  • как прописать значение type;
  • как справиться с иногда пропущенными link значениями;
  • (а я тогда не понимал, но иногда мне хочется чтобы изменить форму link, поэтому я также добавил это).
def format(link): if link | tostring | startswith("/") then "https://www.nihongomaster.com" + link else link end;

[.[] | { title: .children[] | select(.tag == "h2").text, type: .children[] | select(.tag == "span").text | ascii_downcase, perex: .children[] | select(.tag == "p").text, link: format(((.children[] | select(.tag == "a").href) // null)) }]

Нет ничего лучше, чем отладка из резиновой утки.

...