Skip to content

Instantly share code, notes, and snippets.

@hohlick
Forked from Hugoberry/JSON2table.m
Created February 28, 2017 13:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hohlick/7bd3846a8cc53a6d9f1464ecbc217ba6 to your computer and use it in GitHub Desktop.
Save hohlick/7bd3846a8cc53a6d9f1464ecbc217ba6 to your computer and use it in GitHub Desktop.
JSON to Table in Power Query M
(json) =>
let
//List the expandable columns
expandableColumns = (_) => List.Accumulate(
Table.ColumnNames(_),
{},
(s,c)=>s&(if Type.Is(Value.Type(Record.Field(_{0},c)), type record)
or Type.Is(Value.Type(Record.Field(_{0},c)), type list)
then {c}
else {})
),
// Do the record columns have a concictent structure?
columnHasConsistentType = (T,Cname) =>
let
columnTypes = List.Accumulate(Table.Column(T,Cname),
{},
(s,c)=>s&{Type.RecordFields(Value.Type(c))})
in not (List.Count(List.Distinct(columnTypes)) = List.Count(columnTypes)),
// Expand the consistent typed column based on their primitive type
expandConsistentColumn = (T,Cname) => if Table.Column(T,Cname){0} is record
then expandRecordColumn(T,Cname)
else Table.ExpandListColumn(T,Cname),
// Expand the record column
expandRecordColumn = (T,Cname) => let
fields = Record.FieldNames(Table.Column(T,Cname){0})
in Table.ExpandRecordColumn(T,Cname,fields),
// expand the table column with prefixing the column names with the parent column name
expandTableColumn = (T,Cname) => Table.ExpandTableColumn(
Table.TransformColumns(T,{Cname,Record.ToTable}),
Cname,{"Name","Value"},{Cname&".Name",Cname&".Value"}),
// expand all available columns in the table T
expand = (T) => List.Accumulate(expandableColumns(T),T,(s,c)=> if columnHasConsistentType(s,c)
then expandConsistentColumn(s,c)
else expandTableColumn(s,c)),
// initialize the table structure based on the JSON object
table_ini = if json is record
then Record.ToTable(json)
else Table.FromList(json, Splitter.SplitByNothing()),
// kick off the iteration to expandd all columns form the table based JSON object
iterator = List.Generate(
()=> [expandable = true,
table_chain = table_ini],
each [expandable],
each [expandable = List.Count(expandableColumns([table_chain]))>0,
table_chain = expand([table_chain])],
each [table_chain]),
// output only the last iteration
out = List.Last(iterator)
in
out
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment