-
Notifications
You must be signed in to change notification settings - Fork 150
Description
I am exploring using this library to generate Zod Schemas (which is a Typescript validation library).
The current JSON Schema generation implementation was a great starting point, but I've encountered some limitations particularly regarding tagged unions and enum representations.
The main issues I found are the following:
- Zod is not a format but only a schema so I had to create an empty Reader and Writer;
- rfl::TaggedUnions are converted to rfl::parsing::schema::Type::Anyof (losing type information);
- enums are always interpreted as rfl::parsing::schema::Type::Integer (if your parser is Schemaful) or StringEnum;
This could be a sketch of a potential API:
- TaggedUnions with StringEnums
// Tagged unions with enums
enum class ShapesTags{
Circle,
Rectangle,
Square,
};
struct Circle {
// here we could make a specialization of rfl::Literal
// that convert the enum case to the string
using Tag = rfl::Literal<ShapesTags::Circle>;
double radius;
};
struct Rectangle {
using Tag = rfl::Literal<ShapesTags::Rectangle>;
double height;
double width;
};
struct Square {
using Tag = rfl::Literal<ShapesTags::Square>;
double width;
};
using Shapes = rfl::TaggedUnion<"shape", Circle, Square, Rectangle>;- TaggedUnions with IntegerEnums
struct Circle {
// we should use a NumberLiteral which can be also useful
// for other stuff and makes this change backward-compatible
using Tag = rfl::NumberLiteral<ShapesTags::Circle>;
double radius;
};
struct Rectangle {
using Tag = rfl::NumberLiteral<ShapesTags::Rectangle>;
double height;
double width;
};
struct Square {
using Tag = rfl::NumberLiteral<ShapesTags::Square>;
double width;
};
using Shapes = rfl::TaggedUnion<"shape", Circle, Square, Rectangle>;- using Enums underlying value
enum class ShapesEnum{
Circle,
Rectangle,
Square,
};
// this could be used to set flags for further options
// could also be aliased to apply the same options when you use this
using Shapes = rfl::Enum<ShapesEnum>;
struct MyType {
Shapes shape;
}- adding TaggedUnion to schema types
struct IntegerTagged {
std::string field_;
std::vector<std::pair<int, rfl::parsing::schema::Type>> types_;
};
struct StringTagged {
std::string field_;
std::vector<std::pair<std::string, rfl::parsing::schema::Type>> types_;
};The problem rfl::Enum would solve cannot be solved with a simple ReflectionType to an int because:
- we lose the constraints on valid enum values
- we lose the schema enum definition entirely
Also, the problem is not solved by the preprocessor flag rfl::UnderlyingEnum because when generating a schema you may have many enums in one structure with different flags needed.
How an enum should be (de)serialized should be a property of that type (but this is just my opinion so I can understand others may not agree).
For now I was able to achieve something like this without editing the sources by making specific template specializations to my rfl::zod::Parser but I feel like those basic ideas would be useful to the library.
I would gladly contribute with some guidance if the proposal is accepted.