Issue
I'm looking for some advice on what's the best way of implementing a set of data value only 'interfaces' in Python that are equivalent to their typescript counterpart (we've got a project where we use both, and want to enforce a consistent interface for their communication, which would be via serialising the python into json to pull into the TS component)
The interfaces will be compositions to keep things modular and simple.
Given a set of TS interfaces defined as:
interface TestOutput {
phantom: string
testDateTime: datetime
author: string
result: boolean
report_summaryFile?: string // the '?' means this field is optional
// ... more values
series: Array<Series>
soloImages: Array<Images>
}
interface Series {
number: number
filter: string
kernel: string
// ... more values
images: Array<TestImage>
}
I was thinking of using dataclasses and doing the following:
from dataclasses import dataclass
from typing import List
import datetime
@dataclass
class TestSeries:
seriesNum: int
modality: str
description: str = ''
@dataclass
class TestOutput:
phantom: str
testDateTime: datetime.datetime
author: str
result: bool
series: List[TestSeries]
soloImages: List[Images]
report_summaryFile: str = ''
Is dataclasses the best approach for this?
Solution
pydantic is a good library.
I did something similar, but only for dataclasses - ValidatedDC:
from dataclasses import dataclass
from typing import List
from validated_dc import ValidatedDC
import json
@dataclass
class Series(ValidatedDC):
series_num: int
modality: str
description: str = ''
@dataclass
class Output(ValidatedDC):
phantom: str
date_time: str
author: str
result: bool
series: List[Series]
report_summary_file: str = ''
# For example, by API we got a JSON string:
input_json_string = '''
{
"phantom": "test_phantom",
"date_time": "2020.01.01",
"author": "Peter",
"result": true,
"series": [{
"series_num": 1,
"modality": "test_modality"
}]
}
'''
# Load the string into the dictionary:
input_data = json.loads(input_json_string)
# Then create a dataclass to check the types of values and for the
# convenience of further work with data:
output = Output(**input_data)
# Since valid data were obtained, there are no errors
assert output.get_errors() is None
# Let's say we got data with an error:
input_data['series'][0]['series_num'] = '1' # The string is not an integer!
output = Output(**input_data)
assert output.get_errors()
print(output.get_errors())
# {
# 'series': [
# InstanceValidationError(
# value_repr="{'series_num': '1', 'modal...}",
# value_type=<class 'dict'>,
# annotation=<class '__main__.Series'>, exception=None,
# errors={
# 'series_num': [
# BasicValidationError(
# value_repr='1', value_type=<class 'str'>,
# annotation=<class 'int'>, exception=None
# )
# ]
# }
# ),
# ListValidationError(
# item_index=0, item_repr="{'series_num': '1', 'modal...}",
# item_type=<class 'dict'>, annotation=<class '__main__.Series'>
# )
# ]
# }
See here for more details:
https://github.com/EvgeniyBurdin/validated_dc
Answered By - Evgeniy_Burdin
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.