Как сохранить древовидную структуру при разборе json? - PullRequest
0 голосов
/ 02 октября 2018

Мой json:

{
    "catalogs": {
        "name": "catalog 1C",
        "children": [{
                "name": "Philips",
                "children": {}
            },
            {
                "name": "BenQ",
                "children": [{
                    "name": "Monitor",
                    "children": [{
                        "name": "19 inches",
                        "children": [{"name": "IPS", "children": {}}, 
                                     {"name": "TFT","children": {}}] 
                     },
                     {
                         "name": "24 inches",
                         "children": {} }]
                }]
            }
        ]
    }
}

У Json одинаковые ключи и уровни вложенности друг в друге.
сhildren может иметь много каталогов (например, IPS , TFT ).

Это меню, в котором некоторые элементы должны находиться на одном уровне.Я использую гем родословная

Я написал рекурсивную функцию (в контроллере):

def call
  # file - inside the json to parse
  data_hash = JSON.parse(file)

  data_hash["catalogs"]["children"].each do |k|
    ancestry = Category.create_with(name: k["name"]).find_or_create_by!(uid_catalog: k["uid_catalog"])

    if k["children"].present?
      k["children"].each do |parent|
        parent["children"].each do |child|
          walk_tree(child, ancestry)
        end
      end
    end
  end
end

def walk_tree(root, ancestry)
  ancestry = ancestry.children.find_or_create_by!(name: root["name"])

  root["children"].each do |child|
    ancestry = ancestry.children.find_or_create_by!(name: child["name"])
    walk_tree(child["children"], ancestry) if child["children"].present?
  end
end

В настоящее время функция выводит:

  - BenQ
    - 19 inches
      - IPS
        - TFT

Я хочу, чтобы это было так (не хватает одного уровня Monitor):

  - BenQ
    - Monitor
       - 19 inches
         - IPS
         - TFT
       - 24 inches 

1 Ответ

0 голосов
/ 03 октября 2018

Причина проблемы раскрывается после быстрой отладки.Взгляните на этот кусок кода.Обратите внимание на мои комментарии:

data_hash["catalogs"]["children"].each do |k|
  # k == { "name": "BenQ", "children": [...] }
  ancestry = Category.create_with(name: k["name"]).
    find_or_create_by!(uid_catalog: k["uid_catalog"])

  if k["children"].present?
    k["children"].each do |parent|
      # parent == { "name": "Monitor", "children": [...] }
      parent["children"].each do |child|
        # child == { "name": "19 inches", "children": [...] }
        walk_tree(child, ancestry)
      end
    end
  end
end

Так что вы не обрабатываете parent как отдельный узел;вместо этого ваш код немедленно погружается глубже в parent["children"].Вот почему отсутствует один уровень вложенности.

Я думаю, вам нужно удалить внутренний итератор и переписать его как:

data_hash["catalogs"]["children"].each do |k|
  ancestry = Category.create_with(name: k["name"]).
    find_or_create_by!(uid_catalog: k["uid_catalog"])

  if k["children"].present?
    k["children"].each do |child|
      walk_tree(child, ancestry)
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...