Power BI JSON取り込みのコツ:ネスト構造を“表”にするPower Query手順まとめ

Power BIでJSONを扱うとき、最初にぶつかる壁はだいたい同じです。
取り込めたのに「Record」「List」だらけで表にならない。展開したら列が増えすぎる。配列が二重三重で迷子になる。APIのJSONは日によって項目が増減してエラーになる。

でも、Power Queryにはネスト構造を表に変換するための“型”があります。
ポイントは、JSONの構造を見極めて「Recordは列に、Listは行に」を徹底し、段階的に整形すること。この記事では power bi json 取り込み の実務で使える、手順と設計のコツをまとめます。


まず押さえる:JSONは2種類の箱がある

Power QueryでJSONを読むと、だいたい次のどちらか(または混在)で出てきます。

Record

キーと値の集合。表でいうと「1行の横持ち」に近い存在です。
展開すると列が増えます。

List

配列。表でいうと「縦に並ぶ複数行」に近い存在です。
表に変換すると行が増えます。

ここを取り違えると、いつまで経っても表になりません。
迷ったら、最初にプレビューで Record / List の表示を見て、どっちを“列”にして、どっちを“行”にするか決めます。


取り込みの入り口:ファイルとAPIで考え方が少し違う

1) ローカルJSONファイルから取り込む

基本は「データの取得」からJSONを選ぶだけでOKです。
Power Queryの裏側では Json.Document が使われています。

2) Web APIのJSONから取り込む

Web.Contentsで取得してJson.Documentで解釈します。
APIの場合は、認証・ページング・レート制限・スキーマ変化が実務の論点になります。

最初のうちは、同じ変換ロジックでも「入力が安定しているファイル」から練習すると、理解が早いです。


手順全体の地図:ネストJSONを表にする標準フロー

Power Queryでの定番フローはこれです。

  1. JSONを読む(Json.Document)

  2. ルートのRecord/Listを確認する

  3. ListならTableに変換(Table.FromList)

  4. Recordなら列として展開(Table.ExpandRecordColumn)

  5. さらに内側にRecord/Listがあれば、同じことを繰り返す

  6. 必要な粒度まで展開できたら、列名・型・不要列削除を整える

  7. 参照用のディメンションと、明細用のファクトに分ける(必要なら)

この順番を守ると、作業が“破綻しにくい”です。逆に、型指定や列名整理を先にやると、後の展開でやり直しになりやすいです。


実践:よくあるJSONパターン別の変換手順

ここからは「どう展開するか」をパターンで整理します。


パターンA:ルートがList(配列)で、各要素がRecord

最もよくある形です。たとえばAPIが「ユーザー一覧」を返すようなケース。

変換の考え方

・Listは行になる
・要素のRecordを展開して列にする

手順

  1. Listをテーブル化

  2. できた1列(Column1など)をRecordとして展開

  3. 型と列名を整える

Mの例

let
Source = Json.Document(File.Contents("C:\data\users.json")),
AsTable = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
Expanded = Table.ExpandRecordColumn(AsTable, "Column1", {"id","name","email","createdAt"}, {"id","name","email","createdAt"})
in
Expanded

ここまでは簡単ですが、次のパターンから一気に難しく見えます。


パターンB:Recordの中にListがあり、さらにListの中にRecordがある

たとえば「注文(orders)」の中に「注文明細(items)」があるようなJSONです。

変換の考え方

・上位(注文)をまず表にする
・明細(items)は別テーブルにする発想が強い
・itemsはListなので行にする(展開すると注文明細行が増える)

手順(おすすめ構成)

  1. ordersを注文ヘッダとして表にする

  2. itemsは別クエリに参照して、注文明細として展開する

  3. 両者をOrderIdなどでリレーションする

注文ヘッダ側(例)

let
Source = Json.Document(File.Contents("C:\data\orders.json")),
Orders = Source[orders], // Recordの中からorders(List)を取り出す例
T0 = Table.FromList(Orders, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
T1 = Table.ExpandRecordColumn(T0, "Column1", {"orderId","orderDate","customer","items"}, {"orderId","orderDate","customer","items"}),
Customer = Table.ExpandRecordColumn(T1, "customer", {"customerId","customerName"}, {"customerId","customerName"})
in
Customer

この時点で items 列はまだListのまま残ります。ここで無理に同じクエリで全展開すると、編集も保守も重くなりがちです。明細は別クエリで作るのが安定します。

注文明細側(itemsを行にする例)

let
Source = Json.Document(File.Contents("C:\data\orders.json")),
Orders = Source[orders],
T0 = Table.FromList(Orders, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
T1 = Table.ExpandRecordColumn(T0, "Column1", {"orderId","items"}, {"orderId","items"}),

// items(List)を行に展開
ItemsExploded = Table.ExpandListColumn(T1, "items"),

// itemsの各要素(Record)を列に展開
ItemsExpanded = Table.ExpandRecordColumn(ItemsExploded, "items", {"sku","qty","price"}, {"sku","qty","price"})
in
ItemsExpanded

ここで大事なのは、Listの展開は行数を増やす操作だということです。
itemsをExpandListColumnした瞬間に「注文×明細」の粒度になります。これが“正しい粒度”なのか、先に判断してから進めます。


パターンC:Listの中にListがある(二重配列)

二重配列は、フラットな表にするときの落とし穴です。
どの階層を行にするかを決めないと、意図せず行数が爆発します。

コツ

・外側のListをまず行にする
・内側のListは「別テーブル」か「後で必要な列だけ拾う」
・どうしても1表にするなら、内側Listを展開して“最終粒度”に合わせる

Power Queryは展開が容易な反面、やりすぎると一瞬で巨大化します。目的の粒度を先に決めてから展開します。


パターンD:Recordのキーが可変(列が日によって増減する)

APIでありがちです。昨日はあったキーが今日は無い、今日だけ新キーが増えた、など。

失敗例

ExpandRecordColumnで固定のフィールド名を指定していると、キーが無い日にエラーになりやすい。

対策1:存在しないフィールドはnullにする

Recordから安全に取り出す関数を使います。

// Record.FieldOrDefaultを使う例(列追加で対応)
let
r = [Column1],
v = Record.FieldOrDefault(r, "newField", null)
in
v

対策2:列名リストを動的に作って展開する

全件を走査して、存在するキーを集めて展開します。

let
Source = Json.Document(File.Contents("C:\data\data.json")),
T0 = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
Records = Table.Column(T0, "Column1"),
AllFields = List.Union(List.Transform(Records, each Record.FieldNames(_))),
Expanded = Table.ExpandRecordColumn(T0, "Column1", AllFields, AllFields)
in
Expanded

この方法は強いですが、データ量が大きいと処理が重くなる場合があります。重いと感じたら「本当に必要なキーだけ」に絞る、または上流でスキーマを固定するのが現実的です。


パターンE:null・空配列・型ブレが混ざる

JSONは型がブレやすいです。ある行は数値、別の行は文字列、別の行はnull、など。

コツ

・型の変換は最後に寄せる
・変換は try で守る
・エラーをnullに落とすか、エラーログ列を作る

let
Added = Table.AddColumn(Prev, "qty_num", each try Number.From([qty]) otherwise null, type number)
in
Added

型変換エラーをそのまま放置すると、更新のたびに止まります。更新を止めない設計が大事です。


“表”にした後の整理で差がつく:設計のベストプラクティス

ここからが実務で効く部分です。JSONを展開できても、使えるモデルになっていなければ意味がありません。


1) 展開は段階的に、不要列は早めに捨てる

JSONを全展開してから削ると、処理が重くなります。
「使わない列」「使わない階層」は早めに切ります。

・まず上位Recordを展開
・必要な列だけ残す
・次の階層へ進む

この順番にすると、更新が速くなりやすいです。


2) 粒度を混ぜない:ヘッダと明細は分ける

注文ヘッダに明細を展開し続けると、同じヘッダ情報が行ごとに重複します。
Power BIのモデルとしては、ヘッダ(ディメンション寄り)と明細(ファクト)を分けたほうが自然です。

・orders(ヘッダ)テーブル
・order_items(明細)テーブル
・customers(顧客)テーブル

JSONの構造に引っ張られすぎず、分析しやすい形に寄せます。


3) 変換ステップに名前を付けて、壊れたときに直せるようにする

Power Queryは手順が増えがちです。
ステップ名が全部「Changed Type」だと、後で自分が困ります。

・Source
・RootExpanded
・ItemsExploded
・ItemsExpanded
・TypesApplied

こういう名前にしておくと、エラーの位置が一瞬で分かります。


4) 1つの巨大クエリにしない:参照クエリで分割する

おすすめの分割パターンです。

・Raw_JSON:Json.Documentまで(整形しない)
・Stg_Orders:注文ヘッダ向け
・Stg_OrderItems:注文明細向け
・Dim / Fact:モデル投入用(列名・型・キー整備)

Rawを残すと、スキーマ変化が起きたときの原因追跡が楽になります。


5) APIの場合の注意:更新の安定性を最優先にする

APIから取り込む場合、次が実務の地雷です。

・ページングがあるのに1ページしか取れていない
・認証が期限切れで止まる
・レート制限で更新が落ちる
・レスポンスが一時的に欠けている

Power Queryで頑張りすぎるより、次のような考え方が安定します。

・取得は最小限にして、整形はPower Queryでやる
・ページングは関数化して見通しを良くする
・エラーはtryで握り、欠損時は空テーブルを返す設計にする


つまずきポイントQ&A(現場で多い順)

Q1:展開したら列が増えすぎて訳が分からない

A:最終的に分析に必要な粒度を決めて、そこまでしか展開しない。上位3階層だけで十分なことが多いです。明細が必要なら別テーブルに分けます。

Q2:Expandでエラーになる日がある

A:スキーマ変化か欠損です。動的フィールドの展開、またはFieldOrDefaultでの防御を入れます。型変換も最後に回します。

Q3:更新が遅い

A:不要列を早めに削る、巨大な動的展開を避ける、参照クエリで分割する。APIなら取得回数を減らす(1回の呼び出しで必要分を取る)設計が効きます。

Q4:どこまで型を設定すべき?

A:分析で使う列だけでOKです。文字列のままでも問題ない列に無理な型変換をかけると、更新停止の原因になります。


まとめ:ルールはシンプル、勝負は手順と粒度

power bi json 取り込み を成功させるコツは、特殊な技よりも次の基本に尽きます。

・Recordは列にする
・Listは行にする
・展開は段階的に進める
・ヘッダと明細は分ける
・スキーマ変化と型ブレを前提に守る

この型を持っていれば、どんなネストJSONでも「どこを行にして、どこを列にして、どこで止めるか」が判断できるようになります。まずは、自分のJSONで一番内側の明細(List)を見つけて、そこを表にするところから始めてみてください。そこができると、あとは同じ手順の繰り返しです。

関連記事

この記事へのコメントはありません。

カテゴリー

アーカイブ