Add support for RapidJSON DOM members
ecorm opened this issue · comments
I would find it useful to be able to deserialize the "static" part of a JSON object into a C++ struct, but still have access to members of complex, dynamic types. For example, for this JSON definition:
{
"name": "Record",
"members":
[
["std::string", "id", {"required": true}],
["unsigned long", "revision"],
["rapidjson::Document", "document"]
]
}
the resulting C++ struct would look like this:
struct Record
{
std::string key;
unsigned long revision;
rapidjson::Document document;
};
The document
member above would allow me to treat the "document" sub-object as a dynamic JSON value.
But this is still doable. I can write my own handler, bypassing the internals of rapidjson. But I need to know if there are any other types that you think should be supported as dynamic JSON objects. That way, I may come up with a more general approach so it can be extended easily.
Implemented in 253eabf, along with to_document
and from_document
.
Thank you, it's working nicely so far. I had attempted to write my own SAXEventHandler, but yours is much nicer. :-)
With regards to other dynamic types that can model JSON, you might consider:
- recursive boost::variant
- composite boost::any
For the boost::variant approach, I've seen forum postings where they say boost::container helps them get around the problem of standard containers not supporting incomplete types.
If I try to parse into a std::vector<Record>
(see first post for an example of Record
), I get the following error:
.../autojsoncxx/array_types.hpp:57: error: use of deleted function 'Record& operator=(Record&&)'
current = ElementType();
^
.../record.hpp:30: 'Record& operator=(Record&&)' is implicitly deleted because the default definition would be ill-formed:
struct Record {
^
I'm guessing that Record
's move assignment operator was implicitly deleted because in rapidjson::Document
, it is also implicitly deleted. rapidjson::Document
currently does not support move semantics. See Tencent/rapidjson#123.
I was able to work around this problem by parsing into a std::vector<std::unique_ptr<Record>>
. Is it possible for autojsoncxx to provide some workaround that doesn't force the Record
to be dynamically allocated by std::unique_ptr
?
Instead of wasting time on workarounds, I decided to go ahead and implement move semantics for rapidjson::Document
. I should be making a pull request to RapidJSON's maintainer in the next few days.
Fix on my part is not possible, because if this line is fixed, you will still get a compile time error when the element is inserted into the container. Both push_back
and emplace_back
requires the element type to be MoveConstructible or CopyConstructible because they may expand the vector.
Smart pointers and patching rapidjson::Document
are indeed the only two recourses.
I case anyone's interested, the RapidJSON pull request is now pending: Tencent/rapidjson#173
My pull request has been merged in Tencent/rapidjson@1950efd.
rapidjson::GenericDocument
now supports move semantics!
struct Record
{
std::string key;
unsigned long revision;
rapidjson::Document document;
};
Are you sure this class can be handled by autojsoncxx
? I didn't specialize SAXEventHandler
or Serializer
for unsigned long
types.
That Record
struct wasn't the actual one I used for testing; it was a simplified one I "made up" for discussion purposes. The one I'm actually using has an integer type autojsoncxx recognizes.