0

I have the following classes and function.

class Address:
    def __init__(self, a):
        self.transactions = [Transaction(tx) for tx in a['txs']]
    def __repr__(self):
        return "{"f'"transaction": {self.transactions}'"}"

class Transaction:
    def __init__(self, t):
        self.time = t['time']
        self.size = t['size']
    def __repr__(self):
        return f'[{self.time}, ' + f'{self.size}]'

def get_address(address):
    resource = 'address/{0}?format=json'.format(address)
    response = util.call_api(resource)
    json_response = json.loads(response)
    return Address(json_response)

I validated if the output is JSON with the following link https://jsonlint.com/.

the output:

{"transaction": [[1593700974, 225], [1593700792, 226], [1593700643, 224], [1593700521, 223], [1593700188, 225], [1593700128, 225], [1593700006, 225], [1593699937, 323], [1593699855, 387], [1593699795, 546], [1593699734, 226], [1593699672, 351], [1593699521, 226], [1593699180, 224], [1593698457, 257], [1593698215, 256], [1593697822, 225], [1593697762, 257], [1593697430, 226], [1593696633, 223], [1593696030, 288], [1593695968, 225], [1593695908, 294], [1593695697, 257], [1593695515, 225], [1593695364, 225], [1593695302, 223], [1593694913, 223], [1593694459, 223], [1593694186, 258], [1593693858, 223], [1593693664, 225], [1593693246, 224], [1593693002, 223], [1593692791, 223], [1593692067, 223], [1593691674, 223], [1593691554, 225], [1593690881, 225], [1593690759, 255], [1593690277, 223], [1593689883, 226], [1593689701, 226], [1593689640, 225], [1593689097, 224], [1593688967, 226], [1593688576, 224], [1593688515, 259], [1593688454, 224], [1593688302, 226]]}

But the following code throw an error.

p = get_address('*******************')
frame = pd.read_json(json.dumps(p))

The error:

Traceback (most recent call last):
  File "test_explo.py", line 9, in <module>
    frame = pd.DataFrame(json.dumps(p))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Address is not JSON serializable

Any help would be super appreciated please.

delalma
  • 838
  • 3
  • 12
  • 24
  • 1
    Does this answer your question? [How to make a class JSON serializable](https://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializable) – revliscano Jul 03 '20 at 01:26
  • 1
    "I validated if the output" **what output**? Your code doesn't do anything except define a couple of classes then a function. – juanpa.arrivillaga Jul 03 '20 at 02:07

1 Answers1

1

You're attempting to call json.dumps on an instance of Address which the json library does not know how to handle. One simple solution is to add methods on each of your classes to make the conversion.

import json

class Address(object):
    def __init__(self, a):
        self.transactions = [Transaction(tx) for tx in a['txs']]
    
    def to_json(self, **kwargs) -> str:
        transactions = [{'time': t.time, 'size': t.size} for t in self.transactions]
        return json.dumps({'txs': transactions}, **kwargs)

class Transaction(object):
    def __init__(self, t):
        self.time = t['time']
        self.size = t['size']


a = Address({'txs': [{'time': 1, 'size': 2}, {'time': 3, 'size': 4}]})
print(a.to_json(indent=2, sort_keys=True))

Which prints:

{
  "txs": [
    {
      "size": 2,
      "time": 1
    },
    {
      "size": 4,
      "time": 3
    }
  ]
}
kingkupps
  • 3,284
  • 2
  • 16
  • 28
  • thank you so much. I spent so many hours trying to understand and make it work. It is still not clear enough to me. The JSON format has to be defined in the class anyway? Because the function calling the class also use json. – delalma Jul 03 '20 at 01:52
  • It doesn't necessarily need to be defined in the class, but the default `json` library does not know by default how to handle developer-defined classes. You could also create your own JSON decoder as @revliscano referenced in their comment but you still have to define how your class gets serialized in a similar way. – kingkupps Jul 03 '20 at 01:57
  • Thanks. I have another issue when i want to add a JSON object or array into the JSON you helped to def above. Something like `transactions = [{'time': t.time, 'size': t.size, {'input': t.inputs}} for t in self.transactions]` with inputs coming from a third class called by the class `Transaction`. Any hint please? – delalma Jul 03 '20 at 02:49
  • Can you edit your question with these new details? I'll try my best to update my answer to help. – kingkupps Jul 03 '20 at 04:22