Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
539 views
in Technique[技术] by (71.8m points)

python - How to flatten a nested JSON recursively, with flatten_json

This question is specific to using flatten_json from GitHub Repo: flatten

  • The package is on pypi flatten-json 0.1.7 and can be installed with pip install flatten-json
  • This question is specific to the following component of the package:
def flatten_json(nested_json: dict, exclude: list=[''], sep: str='_') -> dict:
    """
    Flatten a list of nested dicts.
    """
    out = dict()
    def flatten(x: (list, dict, str), name: str='', exclude=exclude):
        if type(x) is dict:
            for a in x:
                if a not in exclude:
                    flatten(x[a], f'{name}{a}{sep}')
        elif type(x) is list:
            i = 0
            for a in x:
                flatten(a, f'{name}{i}{sep}')
                i += 1
        else:
            out[name[:-1]] = x

    flatten(nested_json)
    return out

Use recursion to flatten nested dicts

How nested can data be?:

  • flatten_json has been used to unpack a file that ended up being over 100000 columns

Can the flattened JSON, be unflattened?:

  • Yes, this question doesn't cover that. However, if you install the flatten package, there is an unflatten method, but I haven't tested it.
Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

How to flatten a JSON or dict is a common question, to which there are many answers.

  • This answer focuses on using flatten_json to recursively flatten a nested dict or JSON.

Assumptions:

  • This answer assumes you already have the JSON or dict loaded into some variable (e.g. file, api, etc.)
    • In this case we will use data

How is data loaded into flatten_json:

  • It accepts a dict, as shown by the function type hint.

The most common forms of data:

  • Just a dict: {}
    • flatten_json(data)
  • List of dicts: [{}, {}, {}]
    • [flatten_json(x) for x in data]
  • JSON with with top level keys, where the values repeat: {1: {}, 2: {}, 3: {}}
    • [flatten_json(data[key]) for key in data.keys()]
  • Other
    • {'key': [{}, {}, {}]}: [flatten_json(x) for x in data['key']]

Practical Examples:

  • I typically flatten data into a pandas.DataFrame for further analysis.
    • Load pandas with import pandas as pd
  • flatten_json returns a dict, which can be saved directly using the csv packages.

Data 1:

{
    "id": 1,
    "class": "c1",
    "owner": "myself",
    "metadata": {
        "m1": {
            "value": "m1_1",
            "timestamp": "d1"
        },
        "m2": {
            "value": "m1_2",
            "timestamp": "d2"
        },
        "m3": {
            "value": "m1_3",
            "timestamp": "d3"
        },
        "m4": {
            "value": "m1_4",
            "timestamp": "d4"
        }
    },
    "a1": {
        "a11": [

        ]
    },
    "m1": {},
    "comm1": "COMM1",
    "comm2": "COMM21529089656387",
    "share": "xxx",
    "share1": "yyy",
    "hub1": "h1",
    "hub2": "h2",
    "context": [

    ]
}

Flatten 1:

df = pd.DataFrame([flatten_json(data)])

 id class   owner metadata_m1_value metadata_m1_timestamp metadata_m2_value metadata_m2_timestamp metadata_m3_value metadata_m3_timestamp metadata_m4_value metadata_m4_timestamp  comm1               comm2 share share1 hub1 hub2
  1    c1  myself              m1_1                    d1              m1_2                    d2              m1_3                    d3              m1_4                    d4  COMM1  COMM21529089656387   xxx    yyy   h1   h2

Data 2:

[{
        'accuracy': 17,
        'activity': [{
                'activity': [{
                        'confidence': 100,
                        'type': 'STILL'
                    }
                ],
                'timestampMs': '1542652'
            }
        ],
        'altitude': -10,
        'latitudeE7': 3777321,
        'longitudeE7': -122423125,
        'timestampMs': '1542654',
        'verticalAccuracy': 2
    }, {
        'accuracy': 17,
        'activity': [{
                'activity': [{
                        'confidence': 100,
                        'type': 'STILL'
                    }
                ],
                'timestampMs': '1542652'
            }
        ],
        'altitude': -10,
        'latitudeE7': 3777321,
        'longitudeE7': -122423125,
        'timestampMs': '1542654',
        'verticalAccuracy': 2
    }, {
        'accuracy': 17,
        'activity': [{
                'activity': [{
                        'confidence': 100,
                        'type': 'STILL'
                    }
                ],
                'timestampMs': '1542652'
            }
        ],
        'altitude': -10,
        'latitudeE7': 3777321,
        'longitudeE7': -122423125,
        'timestampMs': '1542654',
        'verticalAccuracy': 2
    }
]

Flatten 2:

df = pd.DataFrame([flatten_json(x) for x in data])

 accuracy  activity_0_activity_0_confidence activity_0_activity_0_type activity_0_timestampMs  altitude  latitudeE7  longitudeE7 timestampMs  verticalAccuracy
       17                               100                      STILL                1542652       -10     3777321   -122423125     1542654                 2
       17                               100                      STILL                1542652       -10     3777321   -122423125     1542654                 2
       17                               100                      STILL                1542652       -10     3777321   -122423125     1542654                 2

Data 3:

{
    "1": {
        "VENUE": "JOEBURG",
        "COUNTRY": "HAE",
        "ITW": "XAD",
        "RACES": {
            "1": {
                "NO": 1,
                "TIME": "12:35"
            },
            "2": {
                "NO": 2,
                "TIME": "13:10"
            },
            "3": {
                "NO": 3,
                "TIME": "13:40"
            },
            "4": {
                "NO": 4,
                "TIME": "14:10"
            },
            "5": {
                "NO": 5,
                "TIME": "14:55"
            },
            "6": {
                "NO": 6,
                "TIME": "15:30"
            },
            "7": {
                "NO": 7,
                "TIME": "16:05"
            },
            "8": {
                "NO": 8,
                "TIME": "16:40"
            }
        }
    },
    "2": {
        "VENUE": "FOOBURG",
        "COUNTRY": "ABA",
        "ITW": "XAD",
        "RACES": {
            "1": {
                "NO": 1,
                "TIME": "12:35"
            },
            "2": {
                "NO": 2,
                "TIME": "13:10"
            },
            "3": {
                "NO": 3,
                "TIME": "13:40"
            },
            "4": {
                "NO": 4,
                "TIME": "14:10"
            },
            "5": {
                "NO": 5,
                "TIME": "14:55"
            },
            "6": {
                "NO": 6,
                "TIME": "15:30"
            },
            "7": {
                "NO": 7,
                "TIME": "16:05"
            },
            "8": {
                "NO": 8,
                "TIME": "16:40"
            }
        }
    }
}

Flatten 3:

df = pd.DataFrame([flatten_json(data[key]) for key in data.keys()])

   VENUE COUNTRY  ITW  RACES_1_NO RACES_1_TIME  RACES_2_NO RACES_2_TIME  RACES_3_NO RACES_3_TIME  RACES_4_NO RACES_4_TIME  RACES_5_NO RACES_5_TIME  RACES_6_NO RACES_6_TIME  RACES_7_NO RACES_7_TIME  RACES_8_NO RACES_8_TIME
 JOEBURG     HAE  XAD           1        12:35           2        13:10           3        13:40           4        14:10           5        14:55           6        15:30           7        16:05           8        16:40
 FOOBURG     ABA  XAD           1        12:35           2        13:10           3        13:40           4        14:10           5        14:55           6        15:30           7        16:05           8        16:40

Other Examples:

  1. Python Pandas - Flatten Nested JSON
  2. handling nested json in pandas
  3. How to flatten a nested JSON from the NASA Weather Insight API in Python

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...