Package: json-kit
Installationfrom python package indexpipinstalljson_kitdownload package and run setup.pypythonsetup.pyinstallUsageUse SimpleJSONEncoder to serialize Enum and customized classfromenumimportEnumfromjson_kitimportSimpleJSONEncoderclassJob(Enum):Teacher=0Engineer=1Doctor=2hobbies=["Swimming","Video Games","Fishing"]# If reference keeping is not required, no need to impl __hash__, __eq__classPerson:def__init__(self,name,age,job,hobbies):self.name=nameself.age=ageself.job=jobself.hobbies=hobbiesjack=Person('Jack',33,Job.Teacher)withopen(json_path,'w')asfp:json.dump(jack,fp,cls=SimpleJSONEncoder)# output string# {"name": "Jack", "age": 33, "job": 0, "hobbies": ["Swimming", "Video Games", "Fishing"]}Use RefJSONEncoder to serialize and preserve customized class referenceimplement __hash__ and __eq__ for class to preserve its referencesbuilt-in collecionts such list/dict/set/tuple's references are not preservedfromjson_kitimportRefJSONEncoder,is_customized_class,hashable,to_hashable# Should implement __hash__ and __eq__ for certain custom class# if its reference keeping is intended;# and don't impl both __hash__ and __eq__ for classes# if reference keeping is not intended (when using RefJSONEncoder or AllRefJSONEncoder)classPerson:def__init__(self,name,age,job,hobbies):self.name=nameself.age=ageself.job=jobself.hobbies=hobbiesdef__hash__(self):data=[(k,v)ifhashable(v)else(k,to_hashable(v))fork,vinself.__dict__.items()]data.sort(key=lambdax:x[0])data=tuple(data)returnhash(data)def__eq__(self,other):ifnotis_customized_class(other)ornothashable(other):returnFalsereturnself.__class__==other.__class__andself.__hash__()==other.__hash__()jack=Person('Jack',33,Job.Doctor)another_jack=Person('Jack',33,Job.Doctor)jacks=[jack,another_jack]withopen(json_path,'w')asfp:json.dump(jacks,fp,cls=RefJSONEncoder)# output string:# [{"$id": "1", "name": "Jack", "age": 33, "job": 0, "hobbies": ["Swimming", "Video Games", "Fishing"]}, {"$ref": "1"}]Use AllRefJSONEncoder to serialize and preserve references of customized class, list(set/tuple), dictimplement __hash__ and __eq__ for class to preserve its referencesbuilt-in collecionts such list/dict/set/tuple's references are preserved (set/tuple are converted into lists).use IList/IDictionary instead of IReadOnlyList/IReadOnlyDictionary in C#, otherwise Json.net won't be able to presever builtin collection reference when deserializing.fromjson_kitimportRefJSONEncoder,is_customized_class,hashable,to_hashable# Should implement __hash__ and __eq__ for certain custom class# if its reference keeping is intendedclassPerson:def__init__(self,name,age,job,hobbies):self.name=nameself.age=ageself.job=jobself.hobbies=hobbiesdef__hash__(self):data=[(k,v)ifhashable(v)else(k,to_hashable(v))fork,vinself.__dict__.items()]data.sort(key=lambdax:x[0])data=tuple(data)returnhash(data)def__eq__(self,other):ifnotis_customized_class(other)ornothashable(other):returnFalsereturnself.__class__==other.__class__andself.__hash__()==other.__hash__()jack=Person('Jack',33,Job.Teacher,hobbies)another_jack=Person('Jack',33,Job.Teacher,hobbies)mike=Person('Mike',24,Job.Doctor,hobbies)persons=[jack,another_jack,mike]withopen(json_path,'w')asfp:json.dump(persons,fp,cls=AllRefJSONEncoder)# output text:# [{"$id": "1", "name": "Jack", "age": 33, "job": 0, "hobbies": {"$id": "2", "$values": ["Swimming", "Video Games", "Fishing"]}}, {"$ref": "1"}, {"name": "Mike", "age": 24, "job": 2, "hobbies": {"$ref": "2"}}]Disable skip_none_fields to preserve null fields# Note# None fields in cusomized classes are skipped in default.# Set Encoder.skip_none_fields = False to preserve none fields.person=Person('Jack',Job.Teacher,hobbies)person.age=Nonejstr=json.dumps(obj,cls=SimpleJSONEncoder)# output string# {"name": "Jack", "job": 0, "hobbies": ["Swimming", "Video Games", "Fishing"]}SimpleJSONEncoder.skip_none_fieds=Falsejstr=json.dumps(obj,cls=SimpleJSONEncoder)# output string# {"name": "Jack", "age": null, "job": 0, "hobbies": ["Swimming", "Video Games", "Fishing"]}Use serialize_only_annotated to serialize only annotated fieldsTo serialize only part of instance fields, annotate those to be serialize on class levelIf no annotation exists on class level, all instance fields will be serializedfromtypingimportListfromjson_kitimportSimpleJSONEncoderclassPerson:name:strage:intjob:Jobhobbies:List[str]def__init__(self,name,age,job,hobbies,address):self.name=nameself.age=ageself.job=jobself.hobbies=hobbiesself.address=addressperson=Person('Jack',33,Job.Teacher,hobbies,'Chengdu')SimpleJSONEncoder.serialize_only_annotated=Truejstr=json.dumps(person,cls=SimpleJSONEncoder)# output string# {"name": "Jack", "age": 33, "job": 0, "hobbies": ["Swimming", "Video Games", "Fishing"]}# if no annotation is provided, then all fields will be serialized, including 'address' field.Use load_json_file for auto encoding detectionfromjson_kitimportload_json_filefilename="./sample.json"obj=load_json_file(filename)