Skip to content
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 insert document as node into another DOM tree? #366

Closed
mloskot opened this issue Jun 25, 2015 · 3 comments
Closed

How to insert document as node into another DOM tree? #366

mloskot opened this issue Jun 25, 2015 · 3 comments

Comments

@mloskot
Copy link
Contributor

mloskot commented Jun 25, 2015

Let's take two Document objects created by parsing the following .json files:

  • person.json
{ "person": { "name": { "first": "Adam", "last": "Thomas" } } }
  • address.json
{ "address": { "city": "Moscow", "street": "Quiet" } }

What is the best way to insert the whole "address" node into the "person" DOM tree as a sibling node of the "name"?

So, the final document it reads

{
  "person": {
    "name": { "first": "Adam", "last": "Thomas" },
    "address": { "city": "Moscow", "street": "Quiet" }
  }
}

Here is code that creates instances of the two DOM trees:

Document person;
person.Parse("{\"person\":{\"name\":{\"first\":\"Adam\",\"last\":\"Thomas\"}}}");
RAPIDJSON_ASSERT(!person.HasParseError());

Document address;
address.Parse("{\"address\":{\"city\":\"Moscow\",\"street\":\"Quiet\"}}");
RAPIDJSON_ASSERT(!address.HasParseError());

followed by two possible solutions I was able to come up with:

  1. Requires to know name of the node in the source DOM - inconvenient, impractical:

    person["person"].AddMember("address", address["address"], person.GetAllocator());
    
  2. Requires use of iterators - not bad, but don't feel like suitable tool in this context:

    auto srcRoot = address.MemberBegin();
    person["person"].AddMember(srcRoot->name, srcRoot->value, person.GetAllocator());
    

Is there another, better way to achieve the same?

@miloyip
Copy link
Collaborator

miloyip commented Jun 28, 2015

The example code may have problem that two Documents have their own allocators. So you must ensure the two Document co-exist when using them, otherwise dangling pointer may happen.

I think your first solution is better, because it states that the address document contains the address key explicitly. I don't know if there may be other keys in future in the JSON and the order of keys should not be sensitive, therefore the 2nd solution may cause problem.

To prevent the life-cycle issue, you can deep-clone the value in address document:

Value addressValue = Value(addres["address"], person.GetAllocator());
person["person"].AddMember("address", addressValue, person.GetAllocator());

Or, to prevent the deep-cloning, you can use the same allocator for both Document:

Documnet address(person.GetAllocator());
// ...

@mloskot
Copy link
Contributor Author

mloskot commented Jul 2, 2015

@miloyip Thanks for the explanation and pointing at the possible issues, very informative.

@bryant-ferguson
Copy link
Contributor

Note that the recommendation above to use the same allocator in the second document has a small typo. You must pass the allocator as a pointer:

Document address(&person.GetAllocator());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants