What is the easiest way to parse a json file using rapidjson? - c++

So I am just getting familiar with rapidjson.h but I can't find this one basic piece of example code of parsing the *.json file.
I found the official [turorial][1].
But here however they parse the json stored in a C string. I know how this string is supposed to look like but I'm lazy to make a custom Parser just to convert my file to this string. I mean I was kinda hoping that rapidjson is supposed to do that for me. Please correct me if I'm wrong.
The closest thing I found to what I need is here How to read json file using rapidjson and output to std::string?
Therefore I was really surprised that I can't just do something like this (with *.json file being in the same folder as my program):
rapidjson::Document d;
d.Parse("myJson.json");
My 1. question is:
Do I have to use std::ifstream and rapidjson::IStreamWrapper to get my Document like in the example above and what other as simple as possible alternatives there are?
My 2. question is: (this one would be much easier to ask if i could comment the post above)
What does the R mean in std::ifstream ifs { R"(C:\Test\Test.json)" }; and how
do I change the C:\Test\Test.json string to const char* variable?
Because this isn't working.
const char* str = "C:\Test\Test.json";
std::ifstream ifs { R"(str)" }; //error
std::ifstream ifs { R(str) }; //error
std::ifstream ifs{ (str) }; //ok but I don't like it
[1]: https://rapidjson.org/md_doc_tutorial.html

You can use FileReadStream and ParseStream instead of the IStreamWrapper. According to the documentation, FileReadStream is much faster than IStreamWrapper.
The R means that it's a raw string literal. Without it, the backslashes are interpreted as the start of escape sequences and you would have to write it like this to make it correct:
"C:\\Test\\Test.json"
Or you could use forward slashes:
"C:/Test/Test.json"

Related

How can I put a small bit of a string in a another string?

I have a Question. I want to copy something from a string. I have this:
string buffer = "
{"clientToken":"clientToken","accessToken":"abdjuhsdhjsksdnasfldafgkuadbkghubdfhlujgbdfhulgdfbhugfdbgujhlfdanhjgkhdfanhnjkgbafdhkugbadcjgfdabhgfdabgjhdfabkhgfdbghujfdabghkjfdabghujfadbgfdjhaugbafdhjujgjbfuhkgbf
dhugdbfauhgbfaluhgbdafilgbdfhgfdigujladbijfbghdufjbvgfbhgadbfgbdfjgfbgjfdbjflbgjedfbgauiadfbuigbuifgdabhf
juhgbdaihjfhgbdiuflghbdfiugbfdugbbbbb","selectedProfile":
{"name":"secret","id":"secret"},"availableProfiles":[{"name":"secret","id":"nothing"}]}";
string token;
and i want to put the accestoken (the long gibberish) into the string token(the rest is not needed only the accesstoken). Can anyone help me?
There are few ways to do it, but the most simple is to locate "accessToken" with std::string::find(), then located leading and ending " of the token value itself, and then use std::string::substr() to extract a necessary piece. But in general, you better use some json parsing library, like https://github.com/nlohmann/json

Creating a .txt file in C++ with variables

So I'm designing a game where data is stored and read with text files. But I need to be able to do this in a repeating fashioned so the names of the text files need to be different for each one procedurally. I figured that using variables as the name would solve this issue but I am having a hard time doing this and getting the compiler to work with it.
This is my current code to write 'hello' to a text file named 'test.txt':
ofstream myfile;
myfile.open("test.txt");
myfile << "hello";
myfile.close();
Now, I can replace "test.txt" with a single char* pointer or char array buffer, but I need to separate the name of the file with the .txt extension.
The idea that I had was to somehow combine a char* variable for a name reference (Such as galaxy, star, planet, etc.), plus a numeric value (would have to be a big number, perhaps a double or float), plus the ".txt" text extension. This would then be one char pointer or array that would be compatible with myfile.open. Any ideas? I'm open to changing the process of this as long as I get the same end result.
You should consider string instead of char* for your filename, as C++11 allows both types:
string myfilename="test";
myfile.open(myfilename+".txt");
myfile << "hello";
myfile.close();
To create more complex filenames you could then consider to use stringstreams: you can easily combine and format the filename using the usual output fromatting unctions/operators, and convert it to a string.
stringstream nn;
int counter=0;
nn<<myfilename<<counter<<".txt";
myfile.open(nn.str());
...

Get Non Indented string from Json Object

I have a json object in c++. I am using json_cpp library.
I want to get the string from the Json::Value object. I am using it like below.
Json::Value obj;
....
....
....
string str = obj.toStyledString();
This returns the string in the pretty print format. But I want the string without any indentation. How can I do that as there are no other functions provided in the class?
You could use Json::FastWriter it does not have any indentation and formatting since it outputs everything on a single line. it is normally not suitable for 'human' consumption.
std::string toUnStyledString(const Json::Value& value)
{
Json::FastWriter writer;
return writer.write( value );
}
The function toStyledString also simply uses a Json::StyledWriter if you look into the definition of Json::Value::toStyledString.
Well, if this library doesn't provide appropriate methods then you could write them yourself. The JSON format is rather simple, so I don't think that it will take a lot of work.
Here you can find a good graphical representation of JSON format:
http://json.org
P.S. I've never worked with this particular library, so I propose sort of a general solution.
UPDATE: another option is to get a string returned by toStyledString() and remove indentation. But it requires string processing and will probably be resource consuming. Note that you can't just remove tabs/spaces/new line symbols, because they can be a part of JSON object.
Why do you want unindented string again?

load std::map from text file

This is a very simple thing, so I want to keep it as simple as it sounds. All I want is to load a bunch of key-value paires from a file, and populate them in to a map. I do not really care how the text is structured, as long as it is easy to read.
What i have now is:
xml with xsd generated code (overkill)
Protocol buffer (also overkill)
INI style text file
I like the syntax of the INI file, but I not want to write a parser for that. It sounds to me like I would be doing something lots of people have done before me. Is there not some sort of library to read simple structured files like this?
Since you seem to want the simplest thing humanly possible, I'm going to suggest something incredibly simple that may or may not work based on your map contents. If your map data values are strings that include spaces, this wont work. If they're strings without spaces, or numeric, you're set.
This isn't tested code, but it's close and simple so you should be fine even if it doesn't quite compile. Just change KeyType and ValueType to int, string, float, or whatever you're actually using in the file.
Set up file like:
key value
key2 value2
key3 value3
key4 value4
Read like:
KeyType key;
ValueType value;
std::map<KeyType, ValueType> myMap;
while (infile >> key >> value)
myMap[key] = value;
If you are in the MS world you can use
GetPrivateProfileSectionNames
GetPrivateProfileString
WritePrivateProfileString
to read from ini file or regestry. If you want to write Unicode make sure a newly created file gets the BOM of UTF16.

Search HTML lines and remove lines that don't start with </form></td><td><a

I have an HTML file with very bad formatted code that I get from a website, I want to extract some very small pieces of information.
I am only interested in lines that start like this:
</form></td><td> <b>user897</b></td></tr><tr><td>HouseA</td><td>2</td><td class="entriesTableRow-gamename">HouseA Type12 <span class="entriesTableRow-moredetails"></span></td><td>1 of 2</td><td>user123</td><td>10</td><td>
and I want to extract 3 fields:
A:HouseA
B:HouseA Type12
C:user123
D:10
I know I've seen people recommend HTML Agility Pack and lib2xml but I really don't think I need all that. My app is in C/C++.
I am already using getline to start reading lines, I am just not sure what's the best way to proceed. Thanks!
std::ifstream data("Home.html");
std::string line;
while(std::getline(data,line))
{
linenum++;
std::stringstream lineStream(line);
std::string user;
if (strncmp(line.c_str(), "</form></td><td>",strlen("</form></td><td>")) == 0)
{
printf("found a wanted line in line:%d\n", linenum);
}
}
In the general case, an XML/HTML parser is likely the best way here, as it will be robust against differing input. (Whatever you do, don't use regexps!)
Update
However, if you're targetting specific input, as it seems that you're doing, you can use sscanf (as you suggest) or cin.read() or regexp to scan manually.
Just beware that this code can break at any moment that the HTML changes (even just with whitespace).
Therefore, my/our recommendation is to use a proper tool for the job. XML/HTML is not raw text, and should not be treated as such.
How about writing a python script instead? :)