Hi,
The case is as follows.
In my application i'm receiving text lines. Each lines looks like:
/aaa/bbb/xxx
/aaa/bbb/yyy
/aaa/bbb/zzz
That would be the key structure. The values are also provided. Lets say xxx, yyy, zzz get values of 1, 2, and 3.
This should result in a JSON document that looks like (the parsing i do should make it look like that):
{
"aaa" : {
"bbb" : {
"xxx" : 1,
"yyy" : 2,
"zzz" : 3,
}
}
But i just can't seem to get this done. I must be missing something obvious here.
What i try to do is per input line (say /aaa/bbb/xxx) i split it on "/".
Then i say (somewhat like this):
json jsonDoc;
json &temp = jsonDoc;
for(auto node : {"aaa", "bbb", "xxx"})
{
temp[node] = {};
temp = temp[node];
}
As temp is a reference to jsonDoc i'm expecting it to modify the jsonDoc internally (aka, no copies). The output i would expect is:
{
"aaa" : {
"bbb" : {
"xxx" : 1,
}
}
But instead i get:
Any idea what i might be doing wrong here? And, how to fix it :)
temp is always a reference to the same json object as jsonDoc so each of the assignments set the whole object to {}.
If you want to keep the code more or less the same, you could use a pointer temp instead of a reference.
@garethsb-sony I don;t think i get it..
I am doing:
temp = temp[node];
For the very reason for temp to not be the same object and basically walk deeper at every iteration.
An assignment to a C++ reference doesn't change the object to which the reference refers. That line of code is exactly the same as jsonDoc = jsonDoc[node];
Not related to your actual problem: If your text lines/index are really in the format: /aaa/bbb/xxx you could use a json_pointer.
(code not tested).
json json;
json["/aaa/bbb/xxx"_json_pointer] = 1;
// or
std::string s = "/aaa/bbb/xxx";
json[json_pointer(s)] = 1;
@garethsb-sony Do you have an example for that? As the code looks quite different of pointers are used.
@pboettch That works but gives me an output i'm not looking for:
{
"/aaa/bbb/ccc" : 1
}
Not the intention i'm looking for.
#include <nlohmann/json.hpp>
#include <iomanip>
#include <iostream>
using nlohmann::json;
int main(void)
{
json j;
for (auto &p : {"/aaa/bbb/xxx", "/aaa/bbb/yyy", "/aaa/bbb/zzz"})
j[json::json_pointer(p)] = 1;
std::cout << std::setw(2) << j << "\n";
return 0;
}
gives:
{
"aaa": {
"bbb": {
"xxx": 1,
"yyy": 1,
"zzz": 1
}
}
}
It really didn't ought to look very different, if you insist on keeping your current approach.
Untested:
json jsonDoc;
json *temp = &jsonDoc;
for(auto node : {"aaa", "bbb", "xxx"})
{
(*temp)[node] = {};
temp = &(*temp)[node];
}
But if you have an input format using json-pointer, @pboettch has shown how easy that is to use.
@pboettch Thank you very much! I did try it with "/xxx/yyy/zzz"_json_pointer and i'm fairly sure that ended up with what i said before. Also, that logic didn't work if i had to use input variables (obviously). But i didn't know about the function version and that seems to work fine.
@garethsb-sony ouch! I try to prevent writing code that looks like that :) I'm going for the much neater json_pointer way.
Thank you both a lot for the help! Also, it might be worth pointing this out on the main json overview page. Even though it might be a bit of a specific corner case.
// closed
Care has to be taken when using your index as a json-pointer. How are / escaped in your "index"-field if they are part of a key?
Care has to be taken when using your index as a json-pointer. How are
/escaped in your "index"-field if they are part of a key?
That's no problem as i control the generated data. There is a character being used as seperator and that happens to be "/" for this application.
Most helpful comment
gives: