Search code examples
pythonjsonrecursioniterationflatten

How to flatten a list of objects in python


I have a list of objects :

[
  {
    "person": "abc",
    "city": "united states",
    "facebooklink": "link",
    "address": "united states",
    "united states": [
      {
        "person": "cdf",
        "city": "ohio",
        "facebooklink": "link",
        "address": "united states/ohio",
        "ohio": [
          {
            "person": "efg",
            "city": "clevland",
            "facebooklink": "link",
            "address": "united states/ohio/clevland",
            "clevland": [
              {
                "person": "jkl",
                "city": "Street A",
                "facebooklink": "link",
                "address": "united states/ohio/clevland/Street A",
                "Street A": [
                  {
                    "person": "jkl",
                    "city": "House 1",
                    "facebooklink": "link",
                    "address": "united states/ohio/clevland/Street A/House 1"
                  }
                ]
              }
            ]
          },
          {
            "person": "ghi",
            "city": "columbus",
            "facebooklink": "link",
            "address": "united states/ohio/columbus"
          }
        ]
      },
      {
        "person": "abc",
        "city": "washington",
        "facebooklink": "link",
        "address": "united states/washington"
      }
    ]
  }
]

How can I flatten it to

[
  {
    "person": "abc",
    "city": "united states",
    "facebooklink": "link",
    "address": "united states"
  },
  {
    "person": "cdf",
    "city": "ohio",
    "facebooklink": "link",
    "address": "united states/ohio"
  },
  {
    "person": "efg",
    "city": "clevland",
    "facebooklink": "link",
    "address": "united states/ohio/clevland"
  },
  {
    "person": "jkl",
    "city": "Street A",
    "facebooklink": "link",
    "address": "united states/ohio/clevland/Street A"
  },
  {
    "person": "jkl",
    "city": "House 1",
    "facebooklink": "link",
    "address": "united states/ohio/clevland/Street A/House 1"
  },
  {
    "person": "ghi",
    "city": "columbus",
    "facebooklink": "link",
    "address": "united states/ohio/columbus"
  },
  {
    "person": "abc",
    "city": "washington",
    "facebooklink": "link",
    "address": "united states/washington"
  }
]

I am trying to achieve the same using flatten from flatten_json


Solution

  • Here's one approach by defining "custom" recursive function that takes two arguments the list of objects (or a single object) and a list to accumulate the flattened objects, where for each object we create a new dictionary - only containing the keys we want to keep, after that you'd obviously append this to the accumulator list, then check if the object contain a nested list which can be done by iterating over the keys of the object, in case there's a nested list call the function recursively with this list.

    def flatten_objects(objects, flattened=None):
        if flattened is None:
            flattened = []
    
        # Convert a single dict to a list for consistency
        if isinstance(objects, dict):
            objects = [objects]
    
        for obj in objects:
            # assuming keys exist, extract them
            flat_obj = {key: obj[key] for key in ['person', 'city', 'facebooklink', 'address']}
            flattened.append(flat_obj)
    
            # Recursively process any nested lists
            for key, value in obj.items():
                if isinstance(value, list):  
                    flatten_objects(value, flattened)
    
        return flattened
    
    nested_objects= [
      {
        "person": "abc",
        "city": "united states",
        "facebooklink": "link",
        "address": "united states",
        "united states": [
          {
            "person": "cdf",
            "city": "ohio",
            "facebooklink": "link",
            "address": "united states/ohio",
            "ohio": [
              {
                "person": "efg",
                "city": "clevland",
                "facebooklink": "link",
                "address": "united states/ohio/clevland",
                "clevland": [
                  {
                    "person": "jkl",
                    "city": "Street A",
                    "facebooklink": "link",
                    "address": "united states/ohio/clevland/Street A",
                    "Street A": [
                      {
                        "person": "jkl",
                        "city": "House 1",
                        "facebooklink": "link",
                        "address": "united states/ohio/clevland/Street A/House 1"
                      }
                    ]
                  }
                ]
              },
              {
                "person": "ghi",
                "city": "columbus",
                "facebooklink": "link",
                "address": "united states/ohio/columbus"
              }
            ]
          },
          {
            "person": "abc",
            "city": "washington",
            "facebooklink": "link",
            "address": "united states/washington"
          }
        ]
      }
    ]
    flattened_list = flatten_objects(nested_objects)
    print(flattened_list)
    

    Results by running this (output as follows):

    [
       {
          "person":"abc",
          "city":"united states",
          "facebooklink":"link",
          "address":"united states"
       },
       {
          "person":"cdf",
          "city":"ohio",
          "facebooklink":"link",
          "address":"united states/ohio"
       },
       {
          "person":"efg",
          "city":"clevland",
          "facebooklink":"link",
          "address":"united states/ohio/clevland"
       },
       {
          "person":"jkl",
          "city":"Street A",
          "facebooklink":"link",
          "address":"united states/ohio/clevland/Street A"
       },
       {
          "person":"jkl",
          "city":"House 1",
          "facebooklink":"link",
          "address":"united states/ohio/clevland/Street A/House 1"
       },
       {
          "person":"ghi",
          "city":"columbus",
          "facebooklink":"link",
          "address":"united states/ohio/columbus"
       },
       {
          "person":"abc",
          "city":"washington",
          "facebooklink":"link",
          "address":"united states/washington"
       }
    ]