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

getting clean string from it.key() #748

Closed
sqwunkly opened this issue Sep 19, 2017 · 20 comments
Closed

getting clean string from it.key() #748

sqwunkly opened this issue Sep 19, 2017 · 20 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@sqwunkly
Copy link

I need to a string or char * copy of the iterator key().. I've not been able to find a way of outputting it.key() in a correct format.. the best method I've found is key().dump().. however the result is a string with a backslash at the beginning and end of the string.. the code is below and the cursor is on the line where I'm using dump().. it's not producing a clean string.

image

Below is the it.key().dump() result in debugger.. as you can see it has backslash characters in front and end of the string.. how do I obtain a clean string? .. my apologies if I'm overlooking a simply solution on my part.

image

@gregmarr
Copy link
Contributor

it.key() is already std::string, not json. You're storing a string back into a json object, and then dumping it, so you're getting the string representation of a json string. This should fix your problem:

auto j_key = it.key();

@sqwunkly
Copy link
Author

hello gregmarr.. thanks for explaining, I didn't realize.

I've now got this more or less working.. it seems to be do the right thing. I'd like to obtain names of objects quickly as in comment (at cursor) in the code below.. at that point in the code it would be nice to quickly get the text/string name of the j_groups[0] object and use it for building the json object query string. Is there a way to do something similar to:-

string name = j_groups[0].toString();

image

@gregmarr
Copy link
Contributor

This isn't a json object query string, it just a chaining together of object lookup on different json objects. j_groups[i] is itself a json object. You then get another object using the [group_names_chars[i]] index, but you don't need to do that, as you already have that as it_next. You then index that with [it.key()], but you don't need to do that either as that is simply it.value().

Also, since all you're doing is lookups, you should be using references instead of copying objects, for performance reasons.

 auto const &it_next = it.value();

I would also recommend that you don't cast the key() to a char *, unless you absolutely can't change addSchedule to take a std::string const & or at least const char *.

@gregmarr
Copy link
Contributor

FYI, it's easier to give suggestions if you post code rather than images.

@sqwunkly
Copy link
Author

Thanks gregmarr for your continuing help on this.. I've been struggling a lot, sorry if my questions are basic.. hopefully I'm not wasting your's or anyone else's time.

I don't know how to interpret/implement your suggestions above.. I've tried using them but they're not drop in replacements for ["arbitary unknown schedule name"] which is what I am presently doing.

What I am doing presently is this, perhaps it's not the best way, but it works:-

node_ptr->period.start.mins = j_groups[i]["arbitary unknown schedule name"][it.key()]["time"]["start"]["hours"];

I'd like to obtain that "arbitary unknown schedule name" on the fly from the root object I am querying (j_groups[i]).. at the moment I am obtaining the "arbitary unknown schedule name" earlier and saving it away to use (in my code above).. this works but is convoluted.

Here are your suggestions and my comments.. sorry if I am missing something basic and obvious.. what you are suggesting is likely to be something very simple, nevertheless I don't know in what context you are meaning to apply your suggestions.

RE: "You then get another object using the [group_names_chars[i]] index
but you don't need to do that, as you already have that as it_next "
My reply: I don't understand how to apply your suggestion above, evidently you are not suggesting to use 'it_next' as a replacement for "["group_names_chars[i]"]" (as below it doesn't work)

node_ptr->period.start.hours = j_groups[i][it_next][it.key()]["time"]["start"]["hours"];

RE: "but you don't need to do that either as that is simply it.value()".
My Reply: This also doesn't work with my existing code
node_ptr->period.start.hours = j_groups[i][it.value()][it.key()]["time"]["start"]["hours"];

Clearly I am misunderstanding what you are suggesting.. my apologies for being slow to understand, could you please show me how to implement your suggestions. Evidently you are not suggesting to use them as drop in replacements for ["arbitary unknown schedule name"] as below:-

node_ptr->period.start.mins = j_groups[i]["arbitary unknown schedule name"][it.key()]["time"]["start"]["hours"];

Me confused!

@sqwunkly
Copy link
Author

Much thanks for this suggestion of using references, I'll change my code over to using references.. much better.. I didn't know I could do that here.

Cheers,

@gregmarr
Copy link
Contributor

gregmarr commented Sep 20, 2017

for (auto& group : json::iterator_wrapper(j_groups[i])) {
    for (auto& schedule : json::iterator_wrapper(group.value())) {
        auto const &time = schedule.value()["time"];
        node_ptr->period.start.hours = time["start"]["hours"];
        node_ptr->period.start.mins = time["start"]["mins"];

@gregmarr
Copy link
Contributor

j_groups[i][group_names_chars[i]] is the same thing as it_next.

it_next[it.key()] is the same thing as it.value().

So you can replace j_groups[i][group_names_chars[i]][it.key()] with it.value().

@sqwunkly
Copy link
Author

Hello gregmarr, much thanks for your retailed reply!! Yes, it works as you demonstrated.. and is much a better of doing it than what I was doing it.. I was struggling to know and find out what values the objects and iterators were representing.. I could see in debugger what the values were, but it wasn't straight forward for me to determine what/how those values in the debugger were correlated with the code.. which is one big reason I was searching around for an equivalent of a json.toString() or iterator.toString() option, as I could then have determined quickly and precisely what each value was definitely representing.. it got pretty confusing diving down through layers of objects, wondering which of those was values was actually being represented by the code.. anyway, I understand it now with your help.. you've helped lot.. it would have taken me days.. a long time.. to work out what you've shown me.

so.. much thanks!!

@gregmarr
Copy link
Contributor

You're welcome. Glad I was able to help.

@sqwunkly
Copy link
Author

sqwunkly commented Sep 20, 2017

.. I'd posted a question.. the answer was simple and I've deleted my post.

@sqwunkly
Copy link
Author

sqwunkly commented Sep 20, 2017

this is how I've obtained those top level names.. I did it in an earlier function.. I saved off the "group 1", "group 2", etc names into strings and char arrays for later use.. but it is a clumsy way of doing it.. it is however the only way I've found to date.

Is there a more convenient 'on the fly' method of obtaining top level object names quickly?

I've pasted image of the code as I think more understandable seeing the code in it's entirely rather than a typed out snippet... can enlarge by clicking on image. I hope that is okay.. . the relevant code is highlighted.. I assume there is a better way of doing this.. I don't know how though.. .

image

@sqwunkly
Copy link
Author

ditto

@sqwunkly
Copy link
Author

sqwunkly commented Sep 20, 2017

this solves it.

string MyJson::getObjectName(NlmJson object) {
nlohmann::iterator it = object.begin();
return it.key();
}

@gregmarr
Copy link
Contributor

Having the code as text means that we can copy and paste, modify. With an image, we would have to type it out again.

@gregmarr
Copy link
Contributor

Note that what you have is not the name of the object, the object doesn't have a name. It's the name of the first child of the object.

I don't understand what you're trying to do here. It looks like you're taking a structure like this:

{
  "group1": "data1",
  "group2": "data2",
  "group3": "data3",
  ...
}

and turning it into this:

[
  { "group1", "data1" },
  { "group2": "data2" },
  { "group3": "data3" },
  ...
]

and then a separate array of "group1", "group2", "group3", .... What is the purpose of this? Why not just save the JSON exactly as you read it? What are you doing later that requires this separation?

@sqwunkly
Copy link
Author

sqwunkly commented Sep 21, 2017

hi gregmarr.. thanks for your's and Niel's help. I posted a reply to your question and deleted it a couple days later as this is probably not the right place for the indepth description i'd given.

@sqwunkly
Copy link
Author

sqwunkly commented Sep 21, 2017

deleted..

@nlohmann
Copy link
Owner

Can I close this issue?

@sqwunkly
Copy link
Author

sqwunkly commented Sep 23, 2017 via email

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Sep 23, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

3 participants