Though I've read many threads describing JSON to Python object conversion, I could not find anything about the specific issue I'm trying to deal with. I'm new to Python so please excuse me in advance if I'm asking a dumb question or if I'm overexplaining in this post.
What I'm trying to accomplish: I'm writing a script that listens to & handles events emitted by a smart contract, which then retrieves the event data in JSON format and converts it to Python object for further additional processing.
The problem:
The data received from the smart contract is unable to pass through the __init__():
function that converts it due to the way it's formatted with the extra keyword ' "args": ' wrapped around the data, which causes a TypeError. I need to know how to change the formatting of my function to accommodate this.
Possible Solution: It would seem that rather than declaring the arguments that pass through the conversion function individually, I should be passing "args": through as list containing the individual pieces of data enclosed within it. I am simply unfamiliar with how this is done. And I'm not sure if there's something else that I'm missing as well...
An example: Here is a sample of some JSON data that would pass through the function. It's the very first word that is getting in my way. If I manually remove the ' "args": ' wrapping and then manually pass data through the function, it works as intended. But this is not possible when data is received directly from the contract.
{"args": {"host": "0x22892249CC60D7e17B12e2944Ae399eA33b4cc31", "bettor": "0x6D9224B34A72F4a59FD144Ad27fc78C12282242f", "requestId": 74240729112436359689875643194069807893866473208010485695632547688542158919953, "amountSettled": 91200000000000000, "didUserWin": true}, "event": "SettledCoinFlip", "logIndex": 0, "transactionIndex": 0, "transactionHash": "0x6df3ed3d1188394c2c39d8f27ca857d311dc6a473cd198154530002f229f095e", "address": "0x41071889D63E3Dd45b362C14ac71E3FF137Fbee7", "blockHash": "0x8313afdf3abd8a71112f3dd784477fdaebd5ec4c5de3807e1ac2e48c20b5d60b", "blockNumber": 19677422}
Here is the code for the function I'm trying to pass the data through:
def handle_event(event):
print('<Event Detected, Receiving JSON Data>...')
json_string = Web3.toJSON(event)
print(Web3.toJSON(event))
print('<Converting JSON Data>...')
class Bet:
def __init__(self, host, bettor, requestId, amountSettled, didUserWin, event, logIndex, transactionIndex, transactionHash, address, blockHash, blockNumber):
self.host = host
self.bettor = bettor
self.requestId = requestId
self.amountWagered = amountWagered
self.didUserWin = didUserWin
@classmethod
def from_json(cls, json_string):
json_dict = json.loads(json_string)
return cls(**json_dict)
def __repr__(self):
return f'<Bet ID: { self.requestId }>'
bet = Bet.from_json(json_string)
print(bet)
print(bet.host)
print(bet.bettor)
print(bet.amountSettled)
print(bet.didUserWin)
print('<Conversion Complete>')
CodePudding user response:
You could flatten the dictionary by unpacking first the pop
ped args
sub-dictionary and then the remainder of the dictionary i.e.
{ **json_dict.pop('args'), **json_dict }