ConvertTo-Json в объекте с массивом в качестве значения свойства

В Windows Powershell у меня есть простой запрос Invoke-SqlCmd который возвращает следующую таблицу:

ID Text
-- ----
 1 FOO 
 2 BAR 
 3 SPAM

Трубопровод это | ConvertTo-Json -Depth 1 | ConvertTo-Json -Depth 1 дает следующий результат:

[
    {
        "RowError":  "",
        "RowState":  1,
        "Table":  "",
        "ItemArray":  "1 FOO",
        "HasErrors":  false,
        "ID":  1,
        "Text":  "FOO"
    },
    {
        "RowError":  "",
        "RowState":  1,
        "Table":  "",
        "ItemArray":  "2 BAR",
        "HasErrors":  false,
        "ID":  2,
        "Text":  "BAR"
    },
    {
        "RowError":  "",
        "RowState":  1,
        "Table":  "",
        "ItemArray":  "3 SPAM",
        "HasErrors":  false,
        "ID":  3,
        "Text":  "SPAM"
    }
]

Мой желаемый результат - не этот пустой массив, а объект, имеющий единственное свойство, имеющее «Products» в качестве имени и массив в качестве значения.

Кроме того, я хотел бы, чтобы мои записи массива были объектами, имеющими только столбцы таблицы SQL в качестве свойств.

То есть мой желаемый результат будет:

{
    "Products": [
        {
            "ID": 1,
            "Text": "FOO"
        },
        {
            "ID": 2,
            "Text": "BAR"
        },
        {
            "ID": 3,
            "Text": "SPAM"
        }
    ]
}

Как мне этого добиться?


РЕДАКТИРОВАТЬ: запрос и его результат из SQL Server Management Studio следующие: Запрос и результат в SSMS

Всего 1 ответ


Предполагая, что $queryResult содержит результат вашего вызова Invoke-SqlCmd :

[pscustomobject] @{ 
  Products = @($queryResult | Select-Object ID, Text)
} | ConvertTo-Json
  • Select-Object создает экземпляры [pscustomobject] которые содержат свойства, представляющие только фактические столбцы таблицы, жестко закодированные в этом случае.

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

  • [pscustomobject] @{ ... } является синтаксическим сахаром для создания экземпляра оболочки [pscustomobject] , единственное свойство которого Products , содержит массив объектов только для значений столбцов.

  • ConvertTo-Json преобразует полученный пользовательский объект обратно в JSON.

    • Хотя здесь это не проблема, обратите внимание, что глубина рекурсии по умолчанию ограничена 2 , что требует явного использования -Depth для предотвращения потери данных - см. Этот пост .

Определение имен столбцов динамически:

Матиас Р. Джессен , при поддержке Фрая Симпсона , разработал это решение.

Посредством вызова Invoke-SqlCmd вернуть экземпляр System.Data.Table
Через -OutputAs DataTables , .Column.ColumnNames можно использовать для извлечения имен столбцов запроса в виде массива:

# Note the use of `-OutputAs DataTables`; `-As DataTables` should work too.
$queryResult = Invoke-SqlCmd -OutputAs DataTables -Query "SELECT * FROM Schema1.dbo.Table_1" -ServerInstance $instanceName -Database $databaseName  

[pscustomobject] @{ 
  Products = @($queryResult | Select-Object $queryResult.Columns.ColumnName) 
} | ConvertTo-Json 

По умолчанию Invovke-SqlCmd возвращает поток отдельных экземпляров System.Data.DataRow .

Обратите внимание на использование, даже когда $queryResult содержит экземпляр System.Data.DataTable , его строки неявно отправляются через конвейер; другими словами: $queryResult | ... $queryResult | ... совпадает с $queryResult.Rows | ... $queryResult.Rows | ... , поведение, встроенное в PowerShell.


Есть идеи?

10000