Consider you have the following schema being "integer" or "number"
{
"id": "http://json-schema.org/geo",
"$schema": "http://json-schema.org/draft-06/schema#",
"description": "A geographical coordinate",
"type": ["integer", "number"]
}
then - at least when generating code for Python 3.7 - the generated code will be
from typing import Union, Any
def from_float(x: Any) -> float:
assert isinstance(x, (float, int)) and not isinstance(x, bool)
return float(x)
def from_int(x: Any) -> int:
assert isinstance(x, int) and not isinstance(x, bool)
return x
def from_union(fs, x):
for f in fs:
try:
return f(x)
except:
pass
assert False
def to_float(x: Any) -> float:
assert isinstance(x, float)
return x
def coordinate_from_dict(s: Any) -> Union[float, int]:
return from_union([from_float, from_int], s)
def coordinate_to_dict(x: Union[float, int]) -> Any:
return from_union([to_float, from_int], x)
As you can see, in coordinate_from_dict the function from_int will not have any effect because it is placed behind from_float and that one already handles floats and integers. While this basically seems to be acceptable on the first glance because number is the supertype of integer, I consider this a problem because:
- Messages can grow by an additional factor of 3: Imagine you are sending a large array of integers and numbers from the range [0-9.99] but due to some reason right now you just need numbers. Each integer, e.g. 1, will become a number, e.g. 1.0, which has a length of 300% per number compared to an encoding without decimal point.
- No bijective functions: Users should be able to expect that
coordinate_to_dict(coordinate_from_dict(some_input)) results in an identical dictionary when comparing to the original input.
- List entry without effect: The
from_int within from_union([from_float, from_int], s) is useless.
- More code generated than needed: An additional function is needed (
from_float and to_float).
- Inconsistency to other code generation: It is inconsistent to other code generation where datatypes are more relevant than in Python. e.g. in C++ it is
inline void from_json(const json & j, boost::variant<double, int64_t> & x) {
if (j.is_number_integer())
x = j.get<int64_t>();
else if (j.is_number())
x = j.get<double>();
else throw "Could not deserialize";
}
Consider you have the following schema being "integer" or "number"
then - at least when generating code for Python 3.7 - the generated code will be
As you can see, in
coordinate_from_dictthe functionfrom_intwill not have any effect because it is placed behindfrom_floatand that one already handles floats and integers. While this basically seems to be acceptable on the first glance because number is the supertype of integer, I consider this a problem because:coordinate_to_dict(coordinate_from_dict(some_input))results in an identical dictionary when comparing to the original input.from_intwithinfrom_union([from_float, from_int], s)is useless.from_floatandto_float).