genomoncology / related

Nested Object Models in Python with dictionary, YAML, and JSON transformation support
MIT License
198 stars 15 forks source link

API Function Serialize & Deserialize #12

Closed imaurer closed 6 years ago

imaurer commented 6 years ago

When building out APIs that use related for function parameters and return objects, I want a simple way of transforming input dictionaries into nested objects and then output objects into a nested dictionary.

Should work in 2.7 or 3+ using a decorator argument AND work with 3.6 type annotation decorators.

Python 2.7-safe

import related
from .models import InputModel, OutputModel

@related.serializer(input=InputModel)
def my_function(input):
    return OutputModel(
        upper_case=input.lower_case.upper(),
        negative_number=input.positive_number * -1,
        shared=input.shared
    )

3.6 with Type Annotations


import related
from .models import InputModel, OutputModel

@related.serializer
def my_function(input: InputModel):
    return OutputModel(
        upper_case=input.lower_case.upper(),
        negative_number=input.positive_number * -1,
        shared=input.shared
    )

Model:

import related

@related.immutable
class SharedModel(object):
    name = related.StringField()
    some_date = related.DateField()

@related.immutable
class InputModel(object):
    lower_case = related.StringField()
    positive_number = related.IntegerField()
    shared = related.MappingField(SharedModel, "name")

@related.immutable
class OutputModel(object):
    upper_case = related.StringField()
    negative_number = related.IntegerField()
    shared = related.MappingField(SharedModel, "name")

Test case:

def test_serialization():
    result = my_function(
        input=dict(
            lower_case="hello world.",
            positive_number=123,
            shared=dict(
                one=dict(name="one", some_date="2001-01-01"),
                two=dict(name="two", some_date="2002-02-02"),
            )
        )
    )

    assert result == dict(
        upper_case="HELLO WORLD.",
        negative_number=-123,
        shared=dict(
            one=dict(name="one", some_date="2001-01-01"),
            two=dict(name="two", some_date="2002-02-02"),
        )
    )
imaurer commented 6 years ago

Done.