Created
June 20, 2019 19:28
-
-
Save neolitec/5400b919a4b62903c00f52e82bfb97a8 to your computer and use it in GitHub Desktop.
Python JSON Serializer / Deserializer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from .BaseDecoder import * | |
from .BaseEncoder import * | |
import json | |
def attributes(attrs): | |
def decorator(Cls): | |
class ThisDecoder(BaseDecoder): | |
ATTRIBUTES = attrs | |
def __init__(self, *args, **kwargs): | |
BaseDecoder.__init__(self, Cls) | |
class ThisEncoder(BaseEncoder): | |
ATTRIBUTES = attrs | |
def __init__(self, *args, **kwargs): | |
BaseEncoder.__init__(self, Cls) | |
Cls.Decoder = ThisDecoder | |
Cls.Encoder = ThisEncoder | |
Cls.from_json = staticmethod(lambda stringJson: json.loads(stringJson, cls=ThisDecoder)) | |
Cls.to_json = lambda self: json.dumps(self, cls=ThisEncoder) | |
Cls.__str__ = lambda self: str(self.__dict__) | |
return Cls | |
return decorator |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
class BaseDecoder: | |
def __init__(self, clazz): | |
json.JSONDecoder.__init__(self) | |
self.clazz = clazz | |
def decode(self, dct): | |
if type(dct) is str: | |
dct = json.loads(dct) | |
return self.decode_dict(dct) | |
def decode_dict(self, dct): | |
o = self.clazz() | |
for attr_name, attr_type in self.ATTRIBUTES.items(): | |
value = dct.get(attr_name) | |
if value is None: | |
continue | |
if type(value) is dict: | |
value = dct.get(attr_name, {}) | |
if type(attr_type) is list and type(value) is list and len(attr_type) and len(value): | |
item_type = attr_type[0] | |
setattr(o, attr_name, list(map(lambda item: get_converted_object(item_type, item), value))) | |
else: | |
setattr(o, attr_name, get_converted_object(attr_type, value)) | |
return o | |
def get_converted_object(attr_type, value): | |
if hasattr(attr_type, 'Decoder'): | |
decoder = attr_type.Decoder() | |
return decoder.decode_dict(value) | |
else: | |
return value |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
class BaseEncoder(json.JSONEncoder): | |
def __init__(self, clazz): | |
json.JSONEncoder.__init__(self) | |
self.clazz = clazz | |
def default(self, obj): | |
d = dict() | |
for attr_name, attr_type in self.ATTRIBUTES.items(): | |
value = getattr(obj, attr_name, None) | |
if value is None: | |
continue | |
if type(attr_type) is list and len(attr_type) and len(value): | |
item_type = attr_type[0] | |
d[attr_name] = list(map(lambda item: get_converted_object(item_type, item), value)) | |
else: | |
d[attr_name] = get_converted_object(attr_type, value) | |
return d | |
def get_converted_object(attr_type, value): | |
if hasattr(attr_type, 'Encoder'): | |
encoder = attr_type.Encoder() | |
return encoder.default(value) | |
else: | |
return value |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from models import * | |
json_string = """{ | |
"name": "x3.large", | |
"tags": [{ | |
"name": "foo" | |
}], | |
"network": { | |
"name": "eth0", | |
"speed": "1000" | |
}, | |
"storage": { | |
"type": "ssd", | |
"size": "1TB" | |
} | |
}""" | |
@attributes({ | |
'name': str, | |
'speed': str | |
}) | |
class Network: | |
pass | |
@attributes({ | |
'type': str, | |
'size': str | |
}) | |
class Storage: | |
pass | |
@attributes({ | |
'name': str | |
}) | |
class Tag: | |
pass | |
@attributes({ | |
'name': str, | |
'tags': [Tag], | |
'network': Network, | |
'storage': Storage | |
}) | |
class Server: | |
pass | |
s = Server.from_json(json_string) | |
print(s) | |
print(s.network) | |
json = s.to_json() | |
print(json) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment