Reading JSON from a file using C++ REST SDK (Casablanca) - c++

I have the following code which should read the contents of a text file and parse it as JSON
try {
string_t importFile = argv[++iArgCounter]; // extract filename
ifstream_t f(importFile); // filestream of working file
stringstream_t s; // string stream for holding JSON read from file
json::value v; // JSON read from input file
iArgCounter++; // increment arg counter
if (f) {
s << f.rdbuf(); // stream results of reading from file stream into string stream
f.close(); // close the filestream
v.parse(s); // parse the resultant string stream.
}
}
catch (web::json::json_exception excep) {
std::cout << "ERROR Parsing JSON: ";
std::cout << excep.what();
break;
}
And the following test JSON file
[
{
"Destinations":
[
{
"Domain": "127.0.0.1",
"Name": "GoogleLogin",
"Port": "8090"
}
],
"Listeners":
[
{
"Domain": "127.0.0.1",
"Name": "LoginRequest",
"Port": "8080",
"Route": "ProcessLoginRequest"
}
],
"Name": "LoginProcess",
"Routes":
[
{
"Name": "ProcessLoginRequest",
"Rules":
[{
"DestinationIfTrue": "GoogleLogin",
"LeftTerm":
{
"RuleTermType": 1,
"Value": "NETWORK"
},
"Operator": 2,
"RightTerm":
{
"RuleTermType": 0,
"Value": "NETWORK"
}
}],
"Transformations": []
}
]
}
]
The trouble is no matter what the JSON code I get the error 'Line 1, Column 2 Syntax error: Malformed token'. From what I can tell the JSON is correctly formatted with all brackets balanced.
Code is running on 64bit Windows 7.
Anyone got an idea why it thinks this (or how I can convert the stringstream_t to a string and see what it actually reads).

change the line
v.parse(s);
to
v = json::value::parse(s)

Could it be that the file is of utf16 encoding?
Or check if your json file has BOM (Byte Oder Mark) at the head by opening it with a hex editor.

Multiple things could go wrong here
Check if the ifstream is able to open the file correctly using the following
if(!f)
cerr << "can't open file";
If this is the case, check if name of the file and location is correct or not
Also replace
v.parse(s);
with
v = json::value::parse(s.str()) /* As parse would take string as input */

Related

How to read a json obj created with the nlohmann::json lib

I'm getting a JSON string from a curl request, like this:
[
{
"name": "P309",
"path": "P309",
"sha": "b9dbfa7ceb9db3b73c84ff326a418bdd50c1b227",
"type": "file",
"_links": {
"self": "https://api.github.com/repos//files/contents/P309?ref=main",
"git": "https://api.github.com/repos//files/git/blobs/b9dbfdd50c1b227",
"html": "https://github.com//files/blob/main/P309"
}
},
{
"name": "P310",
"path": "P310",
"sha": "b9dbfa7ceb9db3b73c84ff326a418bdd50c1b227",
"_links": {
"self": "https://api.github.com/repos//files/contents/P309?ref=main",
"git": "https://api.github.com/repos//files/git/blobs/b9dbfdd50c1b227",
"html": "https://github.com//files/blob/main/P309"
}
},
]
How can I parse/read it using the nlohmann::json lib?
I've found this example:
/*
"emulators": [
{
"general_info": {
"dev_id": "0123456789"
}
}
]
*/
for(json& o : data["emulators"]) {
json& gi = o["general_info"];
std::cout << gi["dev_id"] << '\n';
}
My JSON being parsed doesn't have any 'title/header', I'm confused about how to read it.
I tried:
using json = nlohmann::json;
json data = json::parse(downloaded_data);
for(json& o : data[0]) {
auto git = o["git"].get<std::string>();
auto name = o["name"].get<std::string>();
}
git outputs the value correctly, however, when reading name it throws an exception.
This is the value of data in the debugger
and this, of o.
Can I get any help on this?

create a JSON object that allows different name

I am creating a JSON file able to read measured value. I have the following structure:
{ "object":
{"object name 1":
{"type":
{"type name":
{"properties":[
{"measure1": 10,
"measure2":5
}
}
}
},
{"object name 2":
{"type":
{"type name":
{"properties":[
{"measure1": 10,
"measure2":5
}
}
}
}
}
}
now object 1 and 2 are exactly the same but they have different name. Is there a possibility of merging these two objects and provide a list of names?
I tried the following without success:
{ "object":
{["object name 1","object name 1"]:
{"type":
I am using C++ to read the file as follows:
std::string s =this->filename;
std::ifstream json_file_stream(s);
if(!json_file_stream)
error("Could not open Json file!");
nlohmann::json radionuclide_json;
json_file_stream >> radionuclide_json;
the code crashes at the last line

How to read Json string starting with square brackets in it? [duplicate]

This question already has an answer here:
How to use boost::property_tree to parse JSON with array root
(1 answer)
Closed 2 years ago.
I am using c++ code to read json string to retrieve value based on specific key names. Example of my json response from web API is in array format like below.
[
{
"username": "123456",
"useraddress": "abc",
"data": [
{
"schedule": true,
"task": "abc",
"risk": "1",
}
],
"date": "0000-00-00"
}
]
Like the above format is the actual response. I have to retrieve date value using key "date".
My code snippet:
{
std::stringstream jsonString;
boost::property_tree::ptree pt;
jsonString << ws2s(Info).c_str();
boost::property_tree::read_json(jsonString, pt);
std::string date = pt.get<std::string>("date");
}
'Info' in above snippet is wsstring containing json response data.
I can able to retrieve "date" if [] square brackets are removed manually. Since it is array format, if I pass without removing brackets, read_json throws error.
Can somebody help this out?
Yeah. Boost Property Tree is a property tree library, not JSON.
You're in luck though, Boost has a JSON library now https://www.boost.org/doc/libs/1_75_0/libs/json/doc/html/index.html
Note: your input isn't valid JSON either, because JSON doesn't strictly allow trailing commas. You can enable them with an option in Boost JSON though:
Live On Compiler Explorer
#include <boost/json.hpp>
#include <iostream>
int main() {
std::string input = R"(
[
{
"username": "123456",
"useraddress": "abc",
"data": [
{
"schedule": true,
"task": "abc",
"risk": "1",
}
],
"date": "0000-00-00"
}
])";
boost::json::parse_options options;
options.allow_trailing_commas = true;
auto json = boost::json::parse(input, {}, options);
for (auto& el : json.as_array()) {
std::cout << el.at("date") << "\n";
}
}
Prints
"0000-00-00"

Uploading file using cpp-httplib

I am using cpp-httplib and I am trying to upload a file to a post test server like https://ptsv2.com . I do not really understand the given documentation on file uploads, I somewhat understand that you have to make use of Multipart/form-data in order to upload a file.
The given code in the documentation is this
httplib::MultipartFormDataItems items = {
{ "text1", "text default", "", "" },
{ "text2", "aωb", "", "" },
{ "file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain" },
{ "file2", "{\n \"world\", true\n}\n", "world.json", "application/json" },
{ "file3", "", "", "application/octet-stream" },
};
auto res = cli.Post("/multipart", items);
in file1 you can see that it is creating a file on the server and naming it hello.txt.
How do I write it so that I can upload a file that is located on my device onto a server?
Any advice would be helpful. Thank you.
according to #Botje and cpp-httplib documentation
std::ifstream t_lf_img("lfimg.png");
std::stringstream buffer_lf_img;
buffer_lf_img << t_lf_img.rdbuf();
std::ifstream t_pc_file("pc.ply");
std::stringstream buffer_pc_file;
buffer_pc_file << t_pc_file.rdbuf();
httplib::Client cliSendFiles("http://ip::port");
httplib::MultipartFormDataItems items = {
{"files", buffer_lf_img.str(), "lf.png", "application/octet-stream"},
{"files", buffer_pc_file.str(), "truck.ply", "application/octet-stream"},
};
auto resSendFiles = cliSendFiles.Post("/uploadfile", items);

reading arrays of json objects with nlohmann c++ library

I am ok using this syntax with the nlohmann library
{
"key1": {"subKey1": "value11",
"subKey2": "value12"},
"key2": {"subKey1": "value21",
"subKey2": "value22"}
}
But I have a new file, which is valid json too (I checked) and is written this way, it is made of a single array of repetitive objects. My code will require to look through those objects and check values inside them individually:
[
{"key1": "value11",
"key2": "value12"},
{"key1": "value21",
"key2": "value22"}
]
I used to read my json files this way:
#include "json.hpp"
nlohmann::json topJson;
nlohmann::json subJson;
if(topJson.find(to_string("key1")) != topJson.end())
{
subJson = topJson["key1"];
entity.SetSubKeyOne(subJson["subKey1"]);
}
But this won't work with my new file syntax. How can I access these repetitive objects and tell nlohmann that my objects are inside an array? More precisely, how would I be able to reach (for example) "value22" with this file syntax?
Thanks!
You can try this:
std::string ss= R"(
{
"test-data":
[
{
"name": "tom",
"age": 11
},
{
"name": "jane",
"age": 12
}
]
}
)";
json myjson = json::parse(ss);
auto &students = myjson["test-data"];
for(auto &student : students) {
cout << "name=" << student["name"].get<std::string>() << endl;
}