-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to declare recursive self referencing data structure? #421
Comments
Do you have any example JSON for this? It seems like the shared_ptr in this case could only be an int/bool and because the mapping is an alias there is no class alternative at this point. I am not fully understanding |
Probably not quite right using Example JSON would be [
true,
false,
42,
[
1,
2,
3,
[
true,
[
1,
false
]
]
]
] The JSON schema I am trying to implement is as follows {
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"value": {
"oneOf": [
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"$ref": "#/definitions/value"
}
}
]
}
},
"allOf": [
{
"$ref": "#/definitions/value"
}
]
} |
I think this needs to go into the raw mapping type. So something like https://jsonlink.godbolt.org/z/nnoT8ssqY #include <daw/json/daw_json_link.h>
#include <cassert>
#include <string>
#include <utility>
#include <variant>
#include <vector>
struct Variant {
std::variant<int, bool, std::vector<Variant>> value;
};
struct VariantCtor {
Variant operator()(char const *ptr, std::size_t sz) const {
auto value = daw::json::json_value(std::string_view(ptr, sz));
return operator()(value);
}
Variant operator()(daw::json::json_value value) const {
using namespace daw::json;
switch (value.type()) {
case JsonBaseParseTypes::Number:
return Variant{from_json<int>(value)};
case JsonBaseParseTypes::Bool:
return Variant{from_json<bool>(value)};
case JsonBaseParseTypes::Array: {
auto res = std::vector<Variant>();
for (auto jp : value) {
res.push_back(operator()(jp.value));
}
return Variant{std::move(res)};
}
default:
std::abort();
}
}
};
namespace daw::json {
template <>
struct json_data_contract<Variant> {
using type = json_type_alias<json_raw_no_name<
std::variant<int, bool, std::vector<Variant>>, VariantCtor>>;
static auto to_json_data(const Variant &value) { return value.value; }
};
} // namespace daw::json
int main() {
{
constexpr std::string_view json_doc = "5";
auto i = daw::json::from_json<Variant>(json_doc);
assert(i.value.index() == 0);
}
{
constexpr std::string_view json_doc = "false";
auto b0 = daw::json::from_json<Variant>(json_doc);
assert(b0.value.index() == 1);
}
{
constexpr std::string_view json_doc = "true";
auto b1 = daw::json::from_json<Variant>(json_doc);
assert(b1.value.index() == 1);
}
{
constexpr std::string_view json_doc =
"[1, true, false, [1, false, []]]";
auto ary = daw::json::from_json<Variant>(json_doc);
assert(ary.value.index() == 2);
}
} |
Serialization of that currently needs more manual than I would like though. |
Does the constructor and json_value approach cover serialization? |
Unfortunately, I don't see an easy path here. recursive DS's isn't something that has been considered and should get better support in the future. |
This will have to be a separate thing for recursive DS's as it's unbounded at compile time. The depth/length isn't known until the data is parsed. |
I have been exploring the use of Thinking about using the alternative mappings feature to use json_value for parsing and json_custom for serialization. |
An advantage of using the conversion class in the json_custom approach is that when splitting conversion operator into declaration before data contracts are declared and definition into after they have been declared is that the definition can now use the established contract to call to_json on data like itself. Maybe that might be an approach for recursive structures in general -- somehow using the definition/declaration split around the contract to be able to refer back to itself. |
I think a generalized recursive approach will need an explicit stack for when the depth gets deep there isn't a stack overflow. There have been attacks that hit JSON libraries like this in the past. That hasn't been needed so far as everything is bounded by the type systems limits. |
Trying to declare the data contract for a variant type that can have itself as one of the alternatives.
A
std::shared_ptr
has to be used as the compiler complains about incomplete type otherwise.Calling
With the following contract all call to
to_json
does not compile (parse_to_t
missing).Are these type of data structures supported?
(Using MSVC 19.37.32825)
The text was updated successfully, but these errors were encountered: