Skip to content

Commit

Permalink
Expanded documentation and added force flag to functional interface
Browse files Browse the repository at this point in the history
  • Loading branch information
dkraczkowski committed Nov 8, 2023
1 parent b75276e commit beb4817
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 5 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ encoded = encode(my_pet, Pet)
assert encoded == {"name": "Max", "age": 3, "breed": "Golden Retriever"}
```

> `chili.encode` function by default only encodes `@encodable` objects, this behavior might be amended with the `force` flag.
## Decoding
To decode an object, you need to create an instance of the `chili.Decoder` class, and then call the `decode()` method, passing the dictionary to be decoded as an argument.

Expand Down Expand Up @@ -107,6 +109,8 @@ decoded = decode(data, Pet)
assert isinstance(decoded, Pet)
```

> `chili.decode` function by default only decodes `@decodable` objects, this behavior might be amended with the `force` flag.
## Missing Properties
If a property is not present in the dictionary when decoding, the `chili.Decoder` class will not fill in the property value, unless there is a default value defined in the type annotation. Similarly, if a property is not defined on the class, the `chili.Encoder` class will hide the property in the resulting dictionary.

Expand Down Expand Up @@ -206,7 +210,7 @@ encoded = serializer.encode(my_pet)
decoded = serializer.decode(encoded)
```

> Note: that you should only use the `@serializable` decorator for objects that are both encodable and decodable.
> Note: that you should only use the `@serializable` decorator for objects that are both @encodable and @decodable.

## JSON Serialization
Expand Down Expand Up @@ -235,6 +239,32 @@ The `decoded` value will be an instance of a Pet object.

> Functional interface is also available through the `chili.json_encode`, `chili.json_decode` functions.
## Private properties
Chili recognizes private attributes within a class, enabling it to serialize these attributes when a class specifies a getter for an attribute and an associated private storage (must be denoted with a `_` prefix).

Here is an example:

```python
from chili import encodable, encode

@encodable
class Pet:
name: str

def __init__(self, name: str) -> None:
self._name = name

@property
def name(self) -> str:
return self._name

pet = Pet("Bobik")
data = encode(pet)
assert data == {
"name": "Bobik",
}
```

## Mapping

Mapping allows you to remap keys, apply functions to the values, and even change the structure of the input dictionary. This is particularly useful when you need to convert data from one format to another, such as when interacting with different APIs or data sources that use different naming conventions.
Expand Down
3 changes: 2 additions & 1 deletion chili/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,11 +603,12 @@ def decode(
obj: StateObject,
a_type: Type[T],
decoders: Union[TypeDecoders, Dict[Any, TypeDecoder]] = None,
force: bool = False
) -> T:
if decoders and not isinstance(decoders, TypeDecoders):
decoders = TypeDecoders(decoders)

decoder = build_type_decoder(a_type, extra_decoders=decoders) # type: ignore
decoder = build_type_decoder(a_type, extra_decoders=decoders, force=force) # type: ignore
if decoder is None:
raise DecoderError.invalid_type

Expand Down
5 changes: 3 additions & 2 deletions chili/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,14 +505,15 @@ def encode(
obj: Any,
type_hint: Type = None,
encoders: Union[TypeEncoders, Dict[Any, TypeEncoder]] = None,
force: bool = False,
) -> StateObject:
if encoders and not isinstance(encoders, TypeEncoders):
encoders = TypeEncoders(encoders)

if type_hint is not None:
encoder = build_type_encoder(type_hint, extra_encoders=encoders) # type: ignore
encoder = build_type_encoder(type_hint, extra_encoders=encoders, force=force) # type: ignore
else:
encoder = build_type_encoder(type(obj), extra_encoders=encoders) # type: ignore
encoder = build_type_encoder(type(obj), extra_encoders=encoders, force=force) # type: ignore

if encoder is None:
raise EncoderError.invalid_input
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ license = "MIT"
name = "chili"
readme = "README.md"
repository = "https://github.com/kodemore/chili"
version = "2.6.0"
version = "2.7.0"

[tool.poetry.dependencies]
gaffe = ">=0.3.0"
Expand Down

0 comments on commit beb4817

Please sign in to comment.