Чтение файла иерархии JSON (количество подузлов может быть любым числом) с помощью Powershell

#json #powershell #recursion #automation #windows-scripting

#json #powershell #рекурсия #автоматизация #windows-скриптинг

Вопрос:

Чтение файла иерархии JSON (количество подузлов может быть любым числом) с помощью Powershell. Я мог бы сделать это для одного уровня, но мне нужно то же самое для N количества циклов, а вложенные циклы должны приводить к древовидному представлению, если это невозможно, то табличным способом с заголовком поверх корневой таблицы

Ниже приведен сценарий, который я разработал на данный момент:

 $Filepath = 'C:UsersLearnerTest2.JSON'
$JsonContent=gc $Filepath | ConvertFrom-Json
$RootNodeCount=$JsonContent.psobject.Properties.name.Count
$RootNodeName=$JsonContent.psobject.Properties.name
foreach ($Name in $RootNodeName) {Echo $Name-->  $JsonContent.$Name} 
  

Файл JSON

 {
    "foundation": {
        "network": {
            "resource_group_name": "rg-network-e2",
            "name": "nonprodvnet-e2"
        },
        "diagnostics": {
            "resource_group_name": "rg-mgmt-cu",
            "storage_account_name": "Sreacnt-e2"
        },
        "log_analytics": {
            "resource_group_name": "rg-mgmt-cu",
            "workspace_name": "la-sap-e2"
        },
        "recovery_vault": {
            "resource_group_name": "rg-mgmt-cu",
            "name": "rsv-sap-e2"
        },
        "windows_domain": {
            "domain_name": "dmn.local",
            "ou_path": "CN=Computers,DC=example,DC=com",
            "domain_user": "svc_domainjoin@dmn.local",
            "domain_password": "Pwd01"
        }
    },
    "control_flags": {
        "enable_boot_diagnostics": true,
        "enable_oms": false,
        "enable_backup": true,
        "windows_domain_join": false
    },
    "deployment": {
        "resource_group": {
            "name": "rg-sap-501-e2",
            "location": "eastus2"
        },
        "tags": {
            "owner": "for SAP"
        },
        "os_account": {
            "admin_username": "locadm"
        },
        "proximity_placement_groups": {
            "ppg-501": {}
        },
        "availability_sets": {
            "avset-cs-501": {
                "ppg_name": "ppg-501"
            },
            "avset-app-501": {
                "ppg_name": "ppg-501"
            },
            "avset-db-501": {
                "ppg_name": "ppg-501"
            }
        },
        "load_balancers": {
            "ilb-sap-501": {
                "dv2ascs": {
                    "ip_address": "192.0.18.20",
                    "probe_port": 62000,
                    "subnet": "app"
                },
                "dv2-ers": {
                    "ip_address": "192.0.18.21",
                    "probe_port": 62102,
                    "subnet": "app"
                }
            },
            "ilb-db-501": {
                "dv2-hana": {
                    "ip_address": "192.0.17.12",
                    "probe_port": 62503,
                    "subnet": "db"
                }
            }
        },
        "server_groups": {
            "ascs": {
                "os_type": "linux",
                "sku": "Standard_E4s_v3",
                "availability_set": "avset-cs-501",
                "backup_policy": "sap",
                "ppg_name": "ppg-501",
                "lb_refs": [
                    "dv2-ascs",
                    "dv2-ers"
                ],
                "os_disk_size": "30",
                "enable_accelerated_networking": true,
                "hosts": {
                    "vcs501-01": {
                        "nics": [
                            [
                                "192.0.18.18"
                            ]
                        ]
                    },
                    "vcs501-02": {
                        "nics": [
                            [
                                "192.0.18.19"
                            ]
                        ]
                    }
                },
                "subnet": "app",
                "image_details": {
                    "resource_id": null,
                    "marketplace_reference": {
                        "publisher" : "SUSE",
                        "offer"     : "sles-sap-15-sp1",
                        "sku"       : "gen1",
                        "version": "latest"
                    }
                },
                "disks": [
                    {
                        "name": "usrsap",
                        "disk_size": "128",
                        "number_of_disks": 1
                    }
                ]
            },
            "apps": {
                "type": "app_linux",
                "os_type": "linux",
                "sku": "Standard_E4s_v3",
                "availability_set": "avset-app-501",
                "backup_policy": "sap",
                "ppg_name": "ppg-501",
                "enable_accelerated_networking": true,
                "os_disk_size": "30",
                "hosts": {
                    "vas501-01": {
                        "nics": [
                            [
                                "192.0.18.16",
                                "192.0.18.26"
                            ]
                        ]
                    },
                    "vas501-02": {
                        "nics": [
                            [
                                "192.0.18.17",
                                "192.0.18.27"
                            ]
                        ]
                    }
                },
                "subnet": "app",
                "image_details": {
                    "resource_id": null,
                    "marketplace_reference": {
                        "publisher" : "SUSE",
                        "offer"     : "sles-15-sp1",
                        "sku"       : "gen1",
                        "version": "latest"
                    }
                },
                "disks": [
                    {
                        "name": "usrsap",
                        "disk_size": "128",
                        "number_of_disks": 1
                    }
                ]
            },
            "hana": {
                "os_type": "linux",
                "sku": "Standard_E32s_v3",
                "availability_set": "avset-db-501",
                "backup_policy": "sap",
                "ppg_name": "ppg-501",
                "os_disk_size": "30",
                "subnet": "db",
                "lb_refs": [
                    "dv2-hana"
                ],
                "hosts": {
                    "vhs501-01": {
                        "nics": [
                            [
                                "192.0.17.10"
                            ]
                        ]
                    },
                    "vhs501-02": {
                        "nics": [
                            [
                                "192.0.17.11"
                            ]
                        ]
                    }
                },
                "image_details": {
                    "resource_id": null,
                    "marketplace_reference": {
                        "publisher" : "SUSE",
                        "offer"     : "sles-sap-15-sp1",
                        "sku"       : "gen1",
                        "version": "latest"
                    }
                },
                "disks": [
                    {
                        "name": "usrsap",
                        "disk_size": "128",
                        "number_of_disks": 1
                    },
                    {
                        "name": "hanashared",
                        "disk_size": "128",
                        "number_of_disks": 1
                    },
                    {
                        "name": "hanadata",
                        "disk_size": "128",
                        "number_of_disks": 3
                    },
                    {
                        "name": "hanalog",
                        "disk_size": "128",
                        "number_of_disks": 2
                    },
                    {
                        "name": "hanabackup",
                        "disk_size": "512",
                        "number_of_disks": 1
                    }
                ]
            }
        }
    }
}
  

Ответ №1:

На самом деле вы читаете не Json файл, а иерархию объекта PowerShell, который может содержать множество типов объектов (.Net), но в данном случае это ограничено исходной структурой Json, которая состоит только из трех основных типов:

  • Массивы, содержащие несколько дочерних объектов
  • PSCustomObjects (если вы не используете ConvertFrom-Json -AsHashTable параметр), содержащий дочерние объекты, которым присвоено определенное имя.
  • Примитивы (включая строки), которые в основном представляют собой объект («лист«) без дочерних элементов.

Лучший способ прочитать иерархическую структуру неизвестной глубины — использовать recursive функцию, то есть функцию, которая вызывает саму себя. Чтобы дать вам пример для вашего конкретного вопроса:

 Function Show-Object ($Object, $Depth = 0, $Name) {
    $Indent = if ($Depth  ) { "    " * ($Depth - 2) }
    if ($Object -is [Array]) {
        If ($Name) { "$Indent$Name =" }
        foreach ($Item in $Object) {
            Show-Object $Item $Depth
        }
    }
    elseif ($Object -is [PSCustomObject]) {
        If ($Name) { "$Indent$Name =" }
        foreach ($Name in $Object.PSObject.Properties.Name) {
            Show-Object $Object.$Name $Depth $Name
        }
    }
    else {
        if ($Name) { "$Indent$Name = $Object" } else { "$Indent$Object" }
    }
}
  

Как вы можете видеть, там, где в структуре могут быть какие-либо дочерние объекты (в случае [Array] или an [PSCustomObject] ), Show-Object функция вызывает саму себя с дочерним объектом в качестве нового входного объекта и некоторыми дополнительными параметрами, например, для отслеживания текущего $Depth .

Вы можете вызвать функцию просто следующим образом:

 Show-Object $JsonContent
  

Или экспортируйте его в файл типа:

 Show-Object $JsonContent | Out-File .text1.txt
  

Для вашего $JsonContent это приведет к:

 foundation =
    network =
        resource_group_name = rg-network-e2
        name = nonprodvnet-e2
    diagnostics =
        resource_group_name = rg-mgmt-cu
        storage_account_name = Sreacnt-e2
    log_analytics =
        resource_group_name = rg-mgmt-cu
        workspace_name = la-sap-e2
    recovery_vault =
        resource_group_name = rg-mgmt-cu
        name = rsv-sap-e2
    windows_domain =
        domain_name = dmn.local
        ou_path = CN=Computers,DC=example,DC=com
        domain_user = svc_domainjoin@dmn.local
        domain_password = Pwd01
control_flags =
    enable_boot_diagnostics = True
    enable_oms = False
    enable_backup = True
    windows_domain_join = False
deployment =
    resource_group =
        name = rg-sap-501-e2
        location = eastus2
    tags =
        owner = for SAP
    os_account =
        admin_username = locadm
    proximity_placement_groups =
        ppg-501 =
    availability_sets =
        avset-cs-501 =
            ppg_name = ppg-501
        avset-app-501 =
            ppg_name = ppg-501
        avset-db-501 =
            ppg_name = ppg-501
    load_balancers =
        ilb-sap-501 =
            dv2ascs =
                ip_address = 192.0.18.20
                probe_port = 62000
                subnet = app
            dv2-ers =
                ip_address = 192.0.18.21
                probe_port = 62102
                subnet = app
        ilb-db-501 =
            dv2-hana =
                ip_address = 192.0.17.12
                probe_port = 62503
                subnet = db
    server_groups =
        ascs =
            os_type = linux
            sku = Standard_E4s_v3
            availability_set = avset-cs-501
            backup_policy = sap
            ppg_name = ppg-501
            lb_refs =
                dv2-ascs
                dv2-ers
            os_disk_size = 30
            enable_accelerated_networking = True
            hosts =
                vcs501-01 =
                    nics =
                            192.0.18.18
                vcs501-02 =
                    nics =
                            192.0.18.19
            subnet = app
            image_details =
                resource_id =
                marketplace_reference =
                    publisher = SUSE
                    offer = sles-sap-15-sp1
                    sku = gen1
                    version = latest
            disks =
                    name = usrsap
                    disk_size = 128
                    number_of_disks = 1
        apps =
            type = app_linux
            os_type = linux
            sku = Standard_E4s_v3
            availability_set = avset-app-501
            backup_policy = sap
            ppg_name = ppg-501
            enable_accelerated_networking = True
            os_disk_size = 30
            hosts =
                vas501-01 =
                    nics =
                            192.0.18.16
                            192.0.18.26
                vas501-02 =
                    nics =
                            192.0.18.17
                            192.0.18.27
            subnet = app
            image_details =
                resource_id =
                marketplace_reference =
                    publisher = SUSE
                    offer = sles-15-sp1
                    sku = gen1
                    version = latest
            disks =
                    name = usrsap
                    disk_size = 128
                    number_of_disks = 1
        hana =
            os_type = linux
            sku = Standard_E32s_v3
            availability_set = avset-db-501
            backup_policy = sap
            ppg_name = ppg-501
            os_disk_size = 30
            subnet = db
            lb_refs =
                dv2-hana
            hosts =
                vhs501-01 =
                    nics =
                            192.0.17.10
                vhs501-02 =
                    nics =
                            192.0.17.11
            image_details =
                resource_id =
                marketplace_reference =
                    publisher = SUSE
                    offer = sles-sap-15-sp1
                    sku = gen1
                    version = latest
            disks =
                    name = usrsap
                    disk_size = 128
                    number_of_disks = 1
                    name = hanashared
                    disk_size = 128
                    number_of_disks = 1
                    name = hanadata
                    disk_size = 128
                    number_of_disks = 3
                    name = hanalog
                    disk_size = 128
                    number_of_disks = 2
                    name = hanabackup
                    disk_size = 512
                    number_of_disks = 1
  

Комментарии:

1. Замечательно, не могли бы вы, пожалуйста, также помочь мне со способом экспорта этих данных в файл.

2. Вы можете просто экспортировать этот файл с помощью Out-File командлета: Show-Object $JsonContent | Out-File .MyFlie.txt

3. Хорошая рекурсия. Интересно, должен ли существовать другой объект сравнения, который больше похож на json diff, который рекурсивно перечисляет все различия, чего некоторые люди ожидают в первую очередь.

4. @js2010, спасибо за комментарии (пожалуйста, проголосуйте «за» ☺). Я думал о создании » Compare-ComplexObject » раньше, но я не думаю, что это относится к этому вопросу. Я еще немного подумаю над этим, и если я это напишу, я уведомлю вас.

5. @iRon Не могли бы вы, пожалуйста, добавить процедуру для представления ее в табличном виде