def json_normalize(data, record_path=None, meta=None,<EOL>meta_prefix=None,<EOL>record_prefix=None,<EOL>errors='<STR_LIT>',<EOL>sep='<STR_LIT:.>'):
def _pull_field(js, spec):<EOL><INDENT>result = js<EOL>if isinstance(spec, list):<EOL><INDENT>for field in spec:<EOL><INDENT>result = result[field]<EOL><DEDENT><DEDENT>else:<EOL><INDENT>result = result[spec]<EOL><DEDENT>return result<EOL><DEDENT>if isinstance(data, list) and not data:<EOL><INDENT>return DataFrame()<EOL><DEDENT>if isinstance(data, dict):<EOL><INDENT>data = [data]<EOL><DEDENT>if record_path is None:<EOL><INDENT>if any([isinstance(x, dict) for x in y.values()] for y in data):<EOL><INDENT>data = nested_to_record(data, sep=sep)<EOL><DEDENT>return DataFrame(data)<EOL><DEDENT>elif not isinstance(record_path, list):<EOL><INDENT>record_path = [record_path]<EOL><DEDENT>if meta is None:<EOL><INDENT>meta = []<EOL><DEDENT>elif not isinstance(meta, list):<EOL><INDENT>meta = [meta]<EOL><DEDENT>meta = [m if isinstance(m, list) else [m] for m in meta]<EOL>records = []<EOL>lengths = []<EOL>meta_vals = defaultdict(list)<EOL>if not isinstance(sep, str):<EOL><INDENT>sep = str(sep)<EOL><DEDENT>meta_keys = [sep.join(val) for val in meta]<EOL>def _recursive_extract(data, path, seen_meta, level=<NUM_LIT:0>):<EOL><INDENT>if isinstance(data, dict):<EOL><INDENT>data = [data]<EOL><DEDENT>if len(path) > <NUM_LIT:1>:<EOL><INDENT>for obj in data:<EOL><INDENT>for val, key in zip(meta, meta_keys):<EOL><INDENT>if level + <NUM_LIT:1> == len(val):<EOL><INDENT>seen_meta[key] = _pull_field(obj, val[-<NUM_LIT:1>])<EOL><DEDENT><DEDENT>_recursive_extract(obj[path[<NUM_LIT:0>]], path[<NUM_LIT:1>:],<EOL>seen_meta, level=level + <NUM_LIT:1>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>for obj in data:<EOL><INDENT>recs = _pull_field(obj, path[<NUM_LIT:0>])<EOL>lengths.append(len(recs))<EOL>for val, key in zip(meta, meta_keys):<EOL><INDENT>if level + <NUM_LIT:1> > len(val):<EOL><INDENT>meta_val = seen_meta[key]<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>meta_val = _pull_field(obj, val[level:])<EOL><DEDENT>except KeyError as e:<EOL><INDENT>if errors == '<STR_LIT:ignore>':<EOL><INDENT>meta_val = np.nan<EOL><DEDENT>else:<EOL><INDENT>raise KeyError("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>.format(err=e))<EOL><DEDENT><DEDENT><DEDENT>meta_vals[key].append(meta_val)<EOL><DEDENT>records.extend(recs)<EOL><DEDENT><DEDENT><DEDENT>_recursive_extract(data, record_path, {}, level=<NUM_LIT:0>)<EOL>result = DataFrame(records)<EOL>if record_prefix is not None:<EOL><INDENT>result = result.rename(<EOL>columns=lambda x: "<STR_LIT>".format(p=record_prefix, c=x))<EOL><DEDENT>for k, v in meta_vals.items():<EOL><INDENT>if meta_prefix is not None:<EOL><INDENT>k = meta_prefix + k<EOL><DEDENT>if k in result:<EOL><INDENT>raise ValueError('<STR_LIT>'<EOL>'<STR_LIT>'.format(name=k))<EOL><DEDENT>result[k] = np.array(v, dtype=object).repeat(lengths)<EOL><DEDENT>return result<EOL>
Normalize semi-structured JSON data into a flat table.

Parameters
----------
data : dict or list of dicts
    Unserialized JSON objects
record_path : string or list of strings, default None
    Path in each object to list of records. If not passed, data will be
    assumed to be an array of records
meta : list of paths (string or list of strings), default None
    Fields to use as metadata for each record in resulting table
meta_prefix : string, default None
record_prefix : string, default None
    If True, prefix records with dotted (?) path, e.g. foo.bar.field if
    path to records is ['foo', 'bar']
errors : {'raise', 'ignore'}, default 'raise'

    * 'ignore' : will ignore KeyError if keys listed in meta are not
      always present
    * 'raise' : will raise KeyError if keys listed in meta are not
      always present

    .. versionadded:: 0.20.0

sep : string, default '.'
    Nested records will generate names separated by sep,
    e.g., for sep='.', { 'foo' : { 'bar' : 0 } } -> foo.bar

    .. versionadded:: 0.20.0

Returns
-------
frame : DataFrame

Examples
--------

>>> from pandas.io.json import json_normalize
>>> data = [{'id': 1, 'name': {'first': 'Coleen', 'last': 'Volk'}},
...         {'name': {'given': 'Mose', 'family': 'Regner'}},
...         {'id': 2, 'name': 'Faye Raker'}]
>>> json_normalize(data)
    id        name name.family name.first name.given name.last
0  1.0         NaN         NaN     Coleen        NaN      Volk
1  NaN         NaN      Regner        NaN       Mose       NaN
2  2.0  Faye Raker         NaN        NaN        NaN       NaN

>>> data = [{'state': 'Florida',
...          'shortname': 'FL',
...          'info': {
...               'governor': 'Rick Scott'
...          },
...          'counties': [{'name': 'Dade', 'population': 12345},
...                      {'name': 'Broward', 'population': 40000},
...                      {'name': 'Palm Beach', 'population': 60000}]},
...         {'state': 'Ohio',
...          'shortname': 'OH',
...          'info': {
...               'governor': 'John Kasich'
...          },
...          'counties': [{'name': 'Summit', 'population': 1234},
...                       {'name': 'Cuyahoga', 'population': 1337}]}]
>>> result = json_normalize(data, 'counties', ['state', 'shortname',
...                                           ['info', 'governor']])
>>> result
         name  population info.governor    state shortname
0        Dade       12345    Rick Scott  Florida        FL
1     Broward       40000    Rick Scott  Florida        FL
2  Palm Beach       60000    Rick Scott  Florida        FL
3      Summit        1234   John Kasich     Ohio        OH
4    Cuyahoga        1337   John Kasich     Ohio        OH

>>> data = {'A': [1, 2]}
>>> json_normalize(data, 'A', record_prefix='Prefix.')
    Prefix.0
0          1
1          2