Package: jsonstar
JSON* is an extensible json module to serialize all objects!jsonstarextends Python's standard JSON encoder and decoder to easily handle your custom types.This means you won't have to transform your custom types into dictionaries with primitive types before encoding them to
JSON. And you won't have to parse back the encoded strings into your custom types after decoding them from JSON.How to install it?pipinstalljsonstarHow to start using it?Thejsonstarmodule provides the same API as the standardjsonmodule, so you can use it as a drop in replacement.Simply change your import fromimport jsontoimport jsonstar as jsonand you're good to go.Why use it?Consider you have a pydanticEmployeeclass that you want to serialize to JSON.fromdecimalimportDecimalfromdatetimeimportdatefrompydanticimportBaseModelclassEmployee(BaseModel):name:strsalary:Decimalbirthday:dateroles:setemployee=Employee(name="John Doe",salary=Decimal("1000.00"),birthday=date(1990,1,1),roles={"A","B","C"},)The standardjsonmodule can't serialize theemployeeinstance, requiring you to call itsdictmethod.
This will not sufice, because the standardjsonmodule don't know how to encodeDecimal,dateandset.
Your solution would include some trasnfomation of theemployeeinstance and its attributes before encoding it to JSON.That is wherejsonstarshines by providing default encoder for common types likepydantic.BaseModel,decimal.Decimal,datetime.dateandset. And allowing you to easily add your own encoders.fromjsonstarasjsonprint(json.dumps(employee))# {"name": "John Doe", "salary": "1000.00", "birthday": "1990-01-01", "roles": ["A", "B", "C"]}What default encoders are provided?By default,jsonstarprovides encoders for the following types:attrsclassesdataclasses.dataclassclassesdatetime.datedatetime.datetimedatetime.timedatetime.timedeltadecimal.Decimalfrozensetpydantic.BaseModelsetuuid.UUIDConfigurable default encodersFor some complex types like Django Models, an opinionated default encoder would not work for everyone.This is why instead of providing a default encoder for Django Models,jsonstarprovides you a configurable
encoder class to allow you to define the desired encoding behavior.importjsonstarasjsonfromjsonstarimportDjangoModelEncoderjson.register_default_encoder(Model,DjangoModelEncoder(exclude=[DjangoModelEncoder.RELATIONSHIPS]))The above code will register a default encoder for theModelclass that will return all fields, excluding
relationships.Canjsonstaradd more default encoders?Yes. If you think that a default encoder for a common type is missing, please open an issue or a pull request.
See theHow to contributesection for more details.How do I add my own encoder?First you need to decide if you want your encoder to be available everywhere on your project or just for a specific
code block.Default encodersare globally available and will be used anywhere in your project.Instance encodersare available only for theJSONEncoderStarinstance that you register them.Also you have two types of encoders to choose from:Typed encodersare used to encode a specific type identified byisinstance.Functional encodersare used to encode an object based on arbitraty logic.How to add a default encoder?To add a default encoder use theregister_default_encoderfunction on thejsonstarmodule.importjsonstarasjsonfromdecimalimportDecimaldeftwo_decimals_encoder(obj):"""Encodes a decimal with only two decimal places."""returnstr(obj.quantize(Decimal("1.00")))json.register_default_encoder(Decimal,two_decimals_encoder)How to add an instance encoder?An instance encoder can be added in three ways:Using theregistermethod on theJSONEncoderStarinstance.Passing the encoder to theJSONEncoderStarinitialization.Passing the encoder to thedumpsfunction.importjsonstarasjsonfromdecimalimportDecimaldeftwo_decimals_encoder(obj):"""Encodes a decimal with only two decimal places."""returnstr(obj.quantize(Decimal("1.00")))# 1. Using the `register` method on the `JSONEncoderStar` instance.encoder1=json.JSONEncoderStar()encoder1.register(two_decimals_encoder,Decimal)# 2. Passing the encoder to the `JSONEncoderStar` initialization.encoder2=json.JSONEncoderStar(typed_encoders={Decimal:two_decimals_encoder})# 3. Passing the encoder to the `dumps` function.print(json.dumps(data,cls={Decimal:two_decimas_encoder}))How to add a typed encoder?Typed encodersare specific to a type and it's inherited types.When registering a typed encoder, you simply pass the encoder and the type to the chosen registration method.When you add a typed encoder,jsonstarwill check if any base class already has a registered encoder make sure the
more generic encoder is used last, respecting Python's Method Resolution Order (MRO).How to add a functional encoder?Functional encodersare used to encode an object based on arbitraty logic and not specific to a type.To register a functional encoder, you simply pass the encoder to the chosen registration method omiting the type.All functional encoders are called only for objects that do not have a registered typed encoder.ContributingPull requests are welcome and must have associated tests.For major changes, please open an issue first to discuss what you would like to change.LicenseMITAuthorHenrique Bastoshenrique@bastos.netProject linksHomepageRepositoryDocumentation