Keerikkattu Chellappan
Keerikkattu Chellappan

Reputation: 515

Python List to Nested Json

I am having the following problem.

class Inventory:
    def __init__(self,project_no,country,category,product,count):
        self.project_no = project_no
        self.country = country
        self.category = category
        self.product = product
        self.count = count
inventory_list = []
inventory_list.append(Inventory(1,'USA','Beverages','Milk',2))
inventory_list.append(Inventory(1,'USA','Beverages','Juice',5))
inventory_list.append(Inventory(1,'USA','Snacks','Potato Chips',2))
inventory_list.append(Inventory(1,'USA','Oils','Canola',5))
inventory_list.append(Inventory(1,'USA','Oils','Olive',8))
inventory_list.append(Inventory(1,'CAN','Beverages','Milk',7))
inventory_list.append(Inventory(1,'CAN','Beverages','Juice',8))
inventory_list.append(Inventory(1,'CAN','Snacks','Potato Chips',8))
inventory_list.append(Inventory(1,'CAN','Oils','Canola',3))
inventory_list.append(Inventory(1,'CAN','Oils','Olive',4))

{'Inventory': [{'Country': inv.country , 'Category' : [{inv.category : [{'Product' : inv.product}]}] }  for inv in inventory_list]}

This code is giving me the following output.

{'Inventory': [{'Country': 'USA',
   'Category': [{'Beverages': [{'Product': 'Milk'}]}]},
  {'Country': 'USA', 'Category': [{'Beverages': [{'Product': 'Juice'}]}]},
  {'Country': 'USA', 'Category': [{'Snacks': [{'Product': 'Potato Chips'}]}]},
  {'Country': 'USA', 'Category': [{'Oils': [{'Product': 'Canola'}]}]},
  {'Country': 'USA', 'Category': [{'Oils': [{'Product': 'Olive'}]}]},
  {'Country': 'CAN', 'Category': [{'Beverages': [{'Product': 'Milk'}]}]},
  {'Country': 'CAN', 'Category': [{'Beverages': [{'Product': 'Juice'}]}]},
  {'Country': 'CAN', 'Category': [{'Snacks': [{'Product': 'Potato Chips'}]}]},
  {'Country': 'CAN', 'Category': [{'Oils': [{'Product': 'Canola'}]}]},
  {'Country': 'CAN', 'Category': [{'Oils': [{'Product': 'Olive'}]}]}]}

What I actually need is more like below.

{
  "Inventory": [{
          "country": "USA",
          "category": [{
              "Beverages": [{
                  "product": "Milk",
                  "count": 2
              }, {
                  "product": "Juice",
                  "count": 5
              }]
          }, {
              "Snacks": [{
                  "product": "Potato Chips",
                  "count": 2
              }]
          }, {
              "Oils": [{
                  "product": "Canola",
                  "count": 5
              }, {
                  "product": "Olive",
                  "count": 8
              }]
          }]

      }, {
          "country": "CAN",
          "category": [{
              "Beverages": [{
                  "product": "Milk",
                  "count": 7
              }, {
                  "product": "Juice",
                  "count": 8
              }]
          }, {
              "Snacks": [{
                  "product": "Potato Chips",
                  "count": 8
              }]
          }, {
              "Oils": [{
                  "product": "Canola",
                  "count": 3
              }, {
                  "product": "Olive",
                  "count": 4
              }]
          }]
      }

  ]
}

How to do this? I thought list comprehension is the way to go. But I am having trouble beyond this point. I thought this should be really easy for a python coder. With my limited python I could only reach this far. If anyone can help.

Upvotes: 0

Views: 98

Answers (2)

Joseph Carney
Joseph Carney

Reputation: 71

I would suggest you try serializing your Inventory class using the json module. However, it looks like you'll want to reorganize your data a bit. From what I can tell, you want to have an inventory that has a collection of countries which contain a set of products separated into categories.

First, let's define the Product class:

class Product(object):
    def __init__(self, name, count):
        self.product = name
        self.count = count

Next, we can define the Country class as a container for a set Products, arranged in a dictionary using the category name as the key.

class Country(object):
    def __init__(self, name):
        self.name = name
        self.categories = dict()

    def add_product_to_category(self, category, product):
        if category not in self.categories:
            self.categories[category] = []
        self.categories[category].append(product)

Then, we can re-define the Inventory class as a container for a set of Country objects.

class Inventory(object):
    def __init__(self, project_no):
        self.project_no = project_no
        self.countries = []

Next, we can use simple methods to fill out our classes with the required data.

inv = Inventory(1)

us_set = Country('USA')
us_set.add_product_to_category('Beverages', Product('Milk', 2))
us_set.add_product_to_category('Beverages', Product('Juice', 5))
us_set.add_product_to_category('Snacks', Product('Potato Chips', 2))
us_set.add_product_to_category('Oils', Product('Canola', 5))
us_set.add_product_to_category('Oils', Product('Olive', 8))

canada_set = Country('CAN')
canada_set.add_product_to_category('Beverages', Product('Milk', 7))
canada_set.add_product_to_category('Beverages', Product('Juice', 8))
canada_set.add_product_to_category('Snacks', Product('Potato Chips', 8))
canada_set.add_product_to_category('Oils', Product('Canola', 3))
canada_set.add_product_to_category('Oils', Product('Olive', 4))

inv.countries.append(us_set)
inv.countries.append(canada_set)

Finally, (to actually answer your question, lul) to serialize the Inventory class, we have to define an encoder to use:

class MyEncoder(json.JSONEncoder):
    def default(self, o):
        return o.__dict__

Now, we can just call json.dumps() to get a string output of our serialized Inventory.

json.dumps(inv, indent=2, cls=MyEncoder)

The output isn't exactly what you laid out, but I think this method will work well for you.

{
  "project_no": 1, 
  "countries": [
    {
      "name": "USA", 
      "categories": {
        "Beverages": [
          {
            "count": 2, 
            "product": "Milk"
          }, 
          {
            "count": 5, 
            "product": "Juice"
          }
        ], 
        "Oils": [
          {
            "count": 5, 
            "product": "Canola"
          }, 
          {
            "count": 8, 
            "product": "Olive"
          }
        ], 
        "Snacks": [
          {
            "count": 2, 
            "product": "Potato Chips"
          }
        ]
      }
    }, 
    {
      "name": "CAN", 
      "categories": {
        "Beverages": [
          {
            "count": 7, 
            "product": "Milk"
          }, 
          {
            "count": 8, 
            "product": "Juice"
          }
        ], 
        "Oils": [
          {
            "count": 3, 
            "product": "Canola"
          }, 
          {
            "count": 4, 
            "product": "Olive"
          }
        ], 
        "Snacks": [
          {
            "count": 8, 
            "product": "Potato Chips"
          }
        ]
      }
    }
  ]
}

Upvotes: 2

Areeb Malik
Areeb Malik

Reputation: 66

try using the json module, e.g.

import json
...
inv_json = {'Inventory': [{'Country': inv.country , 'Category' : [{inv.category : [{'Product' : inv.product}]}] }  for inv in inventory_list]}
json_formatted_str = json.dumps(x, indent=2)
print(json_formatted_str)

https://www.journaldev.com/33302/python-pretty-print-json

Upvotes: 0

Related Questions