Serialization with to_dict and to_json
Serialization with .to_dict()
or .to_json()
¶
In order to serialize Epure object we need to use .to_dict()
or .to_json()
Lets look at example:
Example with nested Epure values
from epure import epure, Elist, Eset
@epure()
class SomeRandEpure:
someint:int = 777
somecomplexval:complex = 3 + 4j
@epure()
class SomeEpure:
str_val:str = "keen"
int_val:int = 80
someRandEpureVal:SomeRandEpure = SomeRandEpure()
@epure()
class ExampleCls:
someEpureVal:SomeEpure = SomeEpure()
some_val:str = "To the moon!"
ex1 = ExampleCls()
ex2 = ExampleCls()
@epure()
class ToDictEx:
elist_val:Elist[ExampleCls] = Elist[ExampleCls]([ex1, ex2])
eset_val:Eset[ExampleCls]= Eset[ExampleCls]([ex1, ex2])
epure_val:SomeEpure = SomeEpure()
str_val:str = "In Tech we trust"
int_val:int = 424
complex_val:complex = 3 + 4j
generic_list:List[str] = ["cat", "dog", "yak"]
UPCASE_VAL:str = "Some UPcase val"
to_dict_ex_inst = ToDictEx()
Now when we created necessary classes we can serialize epure object to a dict:
1. .to_dict()
¶
def to_dict(
self,
full=False, # (1)!
lambda_func: Callable
= lambda field_name, field_value, field_type, parent_value, rec_depth: # (2)!
rec_depth < 1 or isinstance(type(parent_value), ECollectionMetacls),
_rec_depth=0, # (3)!
) -> Dict[str, Any]:
full
is parameter that you can pass asTrue
if you want object to be serialized fully, to its end. Check out example herelambda_func
is explained more below in note section_rec_depth
is purely private field for.to_dict()
. Please avoid using it.
Let's look more closely to the parameters for .to_dict()
:
to_dict()
parameters
-
full
This
bool
parameter specifies that you want to serialize Epure object fully, all its children. Example here. -
lambda_func
This
lambda
parameter is used to specify what fields of Epure object you want to serialize asdict
orUUID
in resulting dictionary.By default
lambda_func
is set to serialize fields of object's first level that are of typeEpure
,Elist
orEset
toUUID
value. If you specify them explicitly inlambda_func
they will be serialized asdict
.If you want to use your own custom
lambda
function and pass it to.to_dict()
- it must follow some requirements:-
It must return
bool
value -
It must have only this one signature with these 5 arguments (field_name, field_value, field_type, parent_value, rec_depth) e.g.:
Right lambda_func
Warning
Using
lambda
function with different signature or different return type will not work with.to_dict()
Let's look at parameters by which you can modify
lambda_func
:field_name
- name of fieldfield_value
- value that is assigned to the fieldparent_value
- parent value of that field-
rec_depth
- the depth of serialization of Epure type fields of this object to dict, starts count from 0, i.e. "ground" level of object attrs.For example: if
rec_depth == 0
it will serialize objects of type Epure for first base level onlyAnd
rec_depth < 2
will serialize children of object (of type Epure) and children of children (that are of type Epure as well)
Example
More examples for using custom lambdas here
-
Warning
to_dict()
will serialize only fields that were defined in class, assigned new members of class won't be serialized
Lets look at four case scenarious with .to_dict()
1.1 .to_dict()
when object is saved¶
Now if we save object and we want to serialize it, we will get dict where epure instances will be represented by UUID data_id
identifiers
- Check out more about
.save()
method here
And then result will be:
Result when object is saved
to_dict_ex_inst.to_dict() # ->
"{
"data_id": "12e3d625-64bf-479b-927e-27f69cfc4872",
"elist_val": [
{
"data_id": "96067115-e35a-4654-910c-8746596e77d7",
"someEpureVal": "b68c45a7-0268-4709-ae9b-818fa75d2976",
"some_val": "To the moon!",
},
{
"data_id": "9fc82b6d-a251-4de4-9313-19d0bd33a4b4",
"someEpureVal": "b68c45a7-0268-4709-ae9b-818fa75d2976",
"some_val": "To the moon!",
},
],
"eset_val": [
{
"data_id": "96067115-e35a-4654-910c-8746596e77d7",
"someEpureVal": "b68c45a7-0268-4709-ae9b-818fa75d2976",
"some_val": "To the moon!",
},
{
"data_id": "9fc82b6d-a251-4de4-9313-19d0bd33a4b4",
"someEpureVal": "b68c45a7-0268-4709-ae9b-818fa75d2976",
"some_val": "To the moon!",
},
],
"epure_val": {
"data_id": "0f07af91-9e11-45b4-99bd-ae91921be11d",
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": "8bf57d49-17d6-4168-9cca-d22536710673",
},
"str_val": "In Tech we trust",
"int_val": 424,
"complex_val": 3 + 4j,
"generic_list": ["cat", "dog", "yak"],
"UPCASE_VAL": "Some UPcase val",
}"
1.2 .to_dict()
when object is not saved¶
Info
When we serialize object that was not saved, fields that were not included in lambda function criteria - will be None
in resulting dict.
Result when object is not saved
to_dict_ex_inst.to_dict() # ->
"{
"elist_val": [
{"someEpureVal": None, "some_val": "To the moon!"},
{"someEpureVal": None, "some_val": "To the moon!"},
],
"eset_val": [
{"someEpureVal": None, "some_val": "To the moon!"},
{"someEpureVal": None, "some_val": "To the moon!"},
],
"epure_val": {
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": None
},
"str_val": "In Tech we trust",
"int_val": 424,
"complex_val": 3 + 4j,
"generic_list": ["cat", "dog", "yak"],
"UPCASE_VAL": "Some UPcase val",
}"
1.3 passing custom lambda
function to .to_dict()
¶
So for example we want to get serialized dict
where:
-
All children of object of type
Elist
to be serialized not asdict
, but asUUID
. -
First and second level children of object of type
Epure
to be serialized asdict
and notUUID
.
result = to_dict_ex_inst.to_dict(lambda_func =
lambda field_name, field_value, field_type, parent_value, rec_depth:
field_type != Elist and rec_depth <= 1
)
The result will be:
Result
result # ->
"{
"data_id": "2681b947-e7e7-4ac5-ad02-5cdaf6145f08", # 1 level child
"elist_val": "fb3bc534-e54d-4a01-8d0b-3d527c67ae44", # 1 level child
"eset_val": [ # 1 level child
{
"data_id": "9dd8d28b-c660-4fa1-a5bd-11636e4d3b45", # 2 level child
"someEpureVal": { # 2 level child
"data_id": "e1d0fa2f-fa6a-4c7a-bd6c-0566b651f955", # 3 level child
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": "8ae6f23e-108b-41c3-a3ae-282adb0e77cc",
},
"some_val": "To the moon!", # 2 level child
},
{
"data_id": "3ab7589d-1a0f-4da9-b66a-3af2a1183902", # 2 level child
"someEpureVal": { # 2 level child
"data_id": "e1d0fa2f-fa6a-4c7a-bd6c-0566b651f955", # 3 level child
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": "8ae6f23e-108b-41c3-a3ae-282adb0e77cc",
},
"some_val": "To the moon!", # 2 level child
},
],
"epure_val": { # 1 level child
"data_id": "08be3fe4-c4a7-407e-a447-0f9b7b4e57bc", # 2 level child
"str_val": "keen", # 2 level child
"int_val": 80, # 2 level child
"someRandEpureVal": { # 2 level child
"data_id": "8ae6f23e-108b-41c3-a3ae-282adb0e77cc", # 3 level child
"someint": 777,
"somecomplexval": 3 + 4j,
},
},
"str_val": "In Tech we trust", # 1 level child
"int_val": 424, # 1 level child
"complex_val": 3 + 4j, # 1 level child
"generic_list": ["cat", "dog", "yak"], # 1 level child
"UPCASE_VAL": "Some UPcase val", # 1 level child
}"
As you can see elist_val became UUID, and children until 3 level of type Epure became dict
Note
Please note that full
parameter has higher priority than lambda_function
parameter. If full
is True - then every Epure, Elist or Eset value will be serialized to dict
no matter what was specified in lambda
function.
1.4 using .to_dict()
with full = True
¶
Parameter full
can be seen as a sort of short-cut to fully serialize whole object to dict
.
Because of full
parameter higher priority than lambda_func
, these expressions
and
result = to_dict_ex_inst.to_dict(
full = True,
lambda_func = lambda field_name, field_value,\
field_type, parent_value, rec_depth:
...
)
Will give same result:
Result
result #->
"{
"data_id": "2681b947-e7e7-4ac5-ad02-5cdaf6145f08",
"elist_val": [
{
"data_id": "b98e0c51-ed27-49b1-a94b-619dc4c084e1",
"someEpureVal": {
"data_id": "e1d0fa2f-fa6a-4c7a-bd6c-0566b651f955",
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": {
"data_id": "8ae6f23e-108b-41c3-a3ae-282adb0e77cc",
"someint": 777,
"somecomplexval": 3 + 4j,
},
},
"some_val": "To the moon!",
},
{
"data_id": "63ae35e8-671c-4e91-823b-9cc8dfcc0c83",
"someEpureVal": {
"data_id": "e1d0fa2f-fa6a-4c7a-bd6c-0566b651f955",
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": {
"data_id": "8ae6f23e-108b-41c3-a3ae-282adb0e77cc",
"someint": 777,
"somecomplexval": 3 + 4j,
},
},
"some_val": "To the moon!",
},
],
"eset_val": [
{
"data_id": "9dd8d28b-c660-4fa1-a5bd-11636e4d3b45",
"someEpureVal": {
"data_id": "e1d0fa2f-fa6a-4c7a-bd6c-0566b651f955",
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": {
"data_id": "8ae6f23e-108b-41c3-a3ae-282adb0e77cc",
"someint": 777,
"somecomplexval": 3 + 4j,
},
},
"some_val": "To the moon!",
},
{
"data_id": "3ab7589d-1a0f-4da9-b66a-3af2a1183902",
"someEpureVal": {
"data_id": "e1d0fa2f-fa6a-4c7a-bd6c-0566b651f955",
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": {
"data_id": "8ae6f23e-108b-41c3-a3ae-282adb0e77cc",
"someint": 777,
"somecomplexval": 3 + 4j,
},
},
"some_val": "To the moon!",
},
],
"epure_val": {
"data_id": "08be3fe4-c4a7-407e-a447-0f9b7b4e57bc",
"str_val": "keen",
"int_val": 80,
"someRandEpureVal": {
"data_id": "8ae6f23e-108b-41c3-a3ae-282adb0e77cc",
"someint": 777,
"somecomplexval": 3 + 4j,
},
},
"str_val": "In Tech we trust",
"int_val": 424,
"complex_val": 3 + 4j,
"generic_list": ["cat", "dog", "yak"],
"UPCASE_VAL": "Some UPcase val",
}"
2. to_json()
¶
def to_json(
self,
full=False,
lambda_func: Callable = lambda field_name, field_value, field_type, parent_value, rec_depth: rec_depth
< 1
or isinstance(type(parent_value), ECollectionMetacls),
_rec_depth=0,
encoder: Callable = jsonpickle.encode,
) -> str:
to_json()
can be treated just as an wrapper for .to_dict()
, that takes json serializer function by additional encoder
argument and returns already serialized json string. By default encoder is jsonpickle encoder