Power Queryでは、Json.Document
を用いてJSONを読み込み、レコードのリストを表に変換できます。ここでは、ローカルJSONと入れ子構造のJSONを扱う代表的なパターンをご紹介いたします。変数名やファイル名は本記事用に変更しております。
目次
1. ルートが「レコードのリスト」のJSONを読み込む例
JSON の先頭階層が配列で、各要素がレコードである一般的な形式を想定します。
let
// JSONの読み込み
SourceBinary = File.Contents("C:\Data\sales_data.json"),
ParsedJson = Json.Document(SourceBinary),
// レコードのリストを表へ変換
AsTable = Table.FromRecords(ParsedJson),
// 必要に応じて列を限定
Selected = Table.SelectColumns(AsTable, {"OrderId", "OrderDate", "Customer", "Amount"}),
// 型を明示
Typed = Table.TransformColumnTypes(
Selected,
{
{"OrderId", Int64.Type},
{"OrderDate", type date},
{"Customer", type text},
{"Amount", type number}
}
)
in
Typed
要点
Table.FromRecords
は、レコードのリストをそのままテーブルにできます。- 並べ替えや集計を行う前に、
Table.TransformColumnTypes
で型を確定させると安定いたします。
2. ルートがオブジェクトで、中に配列があるJSONを読み込む例
多くのAPIでは、{ "items": [ ... ] }
のように配列が入れ子になっています。
let
// JSONの読み込み
SourceBinary = File.Contents("C:\Data\orders_nested.json"),
ParsedJson = Json.Document(SourceBinary),
// オブジェクト配下の items 配列を取得
ItemsList = ParsedJson[items],
// レコードのリストを表へ
AsTable = Table.FromRecords(ItemsList),
// 入れ子のレコード列がある場合は展開(例: customer 列をフラット化)
Expanded = if Table.HasColumns(AsTable, {"customer"})
then Table.ExpandRecordColumn(
AsTable,
"customer",
{"name", "id"},
{"customer.name", "customer.id"}
)
else AsTable,
// 型を明示
Typed = Table.TransformColumnTypes(
Expanded,
{
{"date", type datetime},
{"amount", type number},
{"customer.name", type text},
{"customer.id", type text}
}
)
in
Typed
要点
- 入れ子の列は
Table.ExpandRecordColumn
やTable.ExpandListColumn
で段階的に展開いたします。 - 実データの列名に合わせて
{"name","id"}
などの項目を調整してください。
3. Web上のJSONを直接取り込む例
認証不要のAPIや公開JSONであれば、Web.Contents
と組み合わせて同様に扱えます。
let
ApiBinary = Web.Contents("https://api.example.org/v1/public/orders?limit=100"),
ApiJson = Json.Document(ApiBinary),
DataList = ApiJson[data],
AsTable = Table.FromRecords(DataList),
Typed = Table.TransformColumnTypes(AsTable, {{"id", Int64.Type}, {"createdAt", type datetime}})
in
Typed
注意点
- 組織のデータ接続設定やプライバシーレベルにより、接続方法の指定が必要な場合がございます。
- 文字コードの指定はCSVと異なり不要です。
File.Contents
とJson.Document
の組み合わせで問題なく解釈されるのが一般的です。
4. 例外に強くするための簡易対策
列の存在有無や欠損を考慮し、try ... otherwise
で安全に取り出すと、API変更時の耐性が向上します。
let
SourceBinary = File.Contents("C:\Data\samples.json"),
ParsedJson = Json.Document(SourceBinary),
ListSafe = try ParsedJson otherwise {},
AsTable = Table.FromRecords(ListSafe),
// 欠損列があっても落ちにくくする
Cols = {"id","date","value"},
AddedCols = List.Accumulate(
Cols,
AsTable,
(state, col) => if Table.HasColumns(state, {col})
then state
else Table.AddColumn(state, col, each null)
)
in
AddedCols
まとめ
- ルートが配列なら
Table.FromRecords
が最短経路です。 - 入れ子構造は
Table.ExpandRecordColumn
とTable.ExpandListColumn
で段階的にフラット化します。 - 型定義を早めに行うことで、後続処理の安定性が高まります。
- APIやフィードの仕様変更に備え、列存在チェックや
try ... otherwise
を取り入れると保守性が向上いたします。