0

I am trying to extract some data from a JSON object generated by a graphql API response. My thought was to write a python class for the "parent" object, and then establish each piece of required data as an attribute.

For example, if I were to get the JSON object:

{
    'order_id': 'A1234567',
    'quantity': 4,
    'price': 100.99
    'carrier': 'USPS'
    'tracking_id': 'ABC987654321',
    'fulfillment_status': 'FULFILLED'
}

I would assign each value as self.order_id, self.quantity, etc. in the class. I wanted to approach it this way because some of the json response is deeply nested and it seemed like a cleaner way to access and use the data rather than using a dictionary approach.

I suppose I could also just create variables for each datum, but the JSON object will almost always be a list of orders, and my thought was to make a list of instantiations of the class and then loop through them to "do stuff" with each instance.

The problem I have is that in some cases the API will not return a value for some of the keys, so I then cannot assign it to an attribute. I thought I could write try/except clauses for each attribute in the class, and assign None if there is no value, but that seemed insane (there are about 20 potential attributes that could/would need to be assigned for each instance).

I will then have some logic in the program afterwards to only do certain actions for 'fulfillment_status': 'Fulfilled', for example, that would not occur for 'fulfillment_status': 'UNFULFILLED', and either do something (or ignore) instances of the class that had None as the value for certain attributes.

Am I thinking about this the wrong way? It feels like it.

martineau
  • 119,623
  • 25
  • 170
  • 301
jlo2207
  • 5
  • 1
  • It's possible to define a class which is a dictionary that has attributes that correspond to its contents — the best of both worlds. See [How to access items of dictionary as attributes and vice versa](https://stackoverflow.com/questions/15105468/how-to-access-items-of-dictionary-as-attributes-and-vice-versa). – martineau Dec 15 '20 at 08:59

2 Answers2

1

dataclass can work for you (it supports default values)

from dataclasses import dataclass

data = {
    'order_id': 'A1234567',
    'quantity': 4,
    'price': 100.99,
    'carrier': 'USPS',
    'tracking_id': 'ABC987654321',
    'fulfillment_status': 'FULFILLED'
}


@dataclass
class OrderDetails:
    order_id: str
    quantity: int
    price: float
    carrier: str
    tracking_id: str
    fulfillment_status: str


order_details = OrderDetails(**data)
print(order_details)

output

OrderDetails(order_id='A1234567', quantity=4, price=100.99, carrier='USPS', tracking_id='ABC987654321', fulfillment_status='FULFILLED')
balderman
  • 22,927
  • 7
  • 34
  • 52
0

To me it seems like a solid idea and I definitely encourage working with classes instead of raw JSON data or plain dictionaries. You can get the values from the JSON objects with self.attribute = json_obj.get('attribute', 'default') method. This way if the attribute is absent or null, you can declare a default value to go well with whatever logic you have in place for processing the data. It also doesn't require any try/except blocks to implement.

LTJ
  • 1,197
  • 3
  • 16