'Encoding and Decoding Class Objects between Python and JSON
I'm encoding and decoding inherited classes between Python 2.7 and a JSON file. This works, but I'm concerned that as I add types, I will need to keep expanding the encoder and decoder to check every type. Is there a more automatic way to convert the class to JSON and back again? It doesn't necessarily need to be an enum.
More specifically, I'm trying to encode and decode a list of equipment objects which all inherit from the Equipment class. Right now, I'm encoding by looking at the isinstance variable, and if it matches one of the subclasses (Transformer, GeneralEquipment, or Motor), I'm adding an extra enum key to the JSON for the equipment type. Then when I decode, the same check happens in reverse. But this means expanding that check for every sub-class I create, and there may be 10-20 equipment types when I'm done.
import json
import math
from enum import Enum
class EquipType(str, Enum):
GeneralEquipment = 'GENERAL_EQUIPMENT'
Transformer = 'TRANSFORMER'
Motor = 'MOTOR'
class Equipment:
VA = None
def __init__(self, tag='', volts=0, phases=1, fla=0):
self.tag = tag
self.volts = volts
self.phases = phases
self.fla = fla
def volt_amps(self):
if self.phases == 3:
self.VA = self.volts*self.fla*math.sqrt(3)
else:
self.VA = self.volts*self.fla
def wire_size(self):
print "calculated as if this were equipment."
class GeneralEquipment(Equipment):
def wire_size(self):
print "calculated as if this were general equipment."
class Transformer(Equipment):
def wire_size(self):
print "calculated as if this were a transformer."
class Motor(Equipment):
def wire_size(self):
print "calculated as if this were a motor."
class EquipmentEncoder(json.JSONEncoder):
def default(self, z):
if isinstance(z, GeneralEquipment):
return {"equiptype" : EquipType.GeneralEquipment, "tag" : z.tag, "volts" : z.volts, "phases" : z.phases, "fla" : z.fla}
elif isinstance(z, Transformer):
return {"equiptype" : EquipType.Transformer, "tag" : z.tag, "volts" : z.volts, "phases" : z.phases, "fla" : z.fla}
elif isinstance(z, Motor):
return {"equiptype" : EquipType.Motor, "tag" : z.tag, "volts" : z.volts, "phases" : z.phases, "fla" : z.fla}
else:
return super().default(z)
def EquipmentDecoder(dct):
if dct['equiptype'] == EquipType.GeneralEquipment:
return Equipment(dct['tag'],dct['volts'],dct['phases'],dct['fla'])
elif dct['equiptype'] == EquipType.Transformer:
return Transformer(dct['tag'],dct['volts'],dct['phases'],dct['fla'])
elif dct['equiptype'] == EquipType.Motor:
return Motor(dct['tag'],dct['volts'],dct['phases'],dct['fla'])
MyEquipList = [GeneralEquipment('EF-1 (Bathroom fan)',120,1,5),Transformer('XMFR-2',208,3,5),Motor('EF-23',480,3,24)]
print(MyEquipList)
print(MyEquipList[0].tag)
file_path = 'C:\\data2.json'
with open(file_path, 'w') as dataFile:
json.dump(MyEquipList, dataFile, cls = EquipmentEncoder)
print ("data dumped")
with open(file_path, 'r') as dataFile:
MyEquipList = json.load(dataFile,object_hook = EquipmentDecoder)
print ("data loaded")
print(MyEquipList[0].tag)
for e in
MyEquipList
===========
:
e.volt_amps()
e.wire_size()
print (e.tag, e.VA)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
