Json data creation for nlohmann - c++

I have some data like
{
"GLOBAL DATA":
{
"FIRST": [
{"BEGIN": "0", "END" : "100"}
],
"SECOND":"SomeData",
"THIRD":"SomeMoreData"
}
}
I want to add more data to FIRST array.
I tried creating the insertion data as follows
json v2 = {"BEGIN": "200","END" : "300"};
But this gives error
example1.cpp:34:23: error: expected '}' before ':' token json v2 = {"BEGIN": "200","END" : "300"};
What's the issue with my v2 data?

You could wrap the JSON data in a raw string literal and use the _json user-defined literal to parse it:
json v2 = R"({"BEGIN": "200", "END": "300"})"_json;
Or you could make it directly (without parsing), but using valid C++ syntax:
json v2 = {{"BEGIN", "200"}, {"END", "300"}};

analyze pretty much what you want to do:
this here:
{"BEGIN":"0","END":"100","MIDDLE":50}
is an object at index 0 in the hierarchy:
globalData.first
so you can do get the element at index 0 in the array and add a new key:value
std::string st = "{\"GLOBAL DATA\":{\"FIRST\": [{\"BEGIN\": \"0\", \"END\" : \"100\"}],\"SECOND\":\"SomeData\",\"THIRD\":\"SomeMoreData\"}}";
nlohmann::json second = nlohmann::json::parse(st);
second["GLOBAL DATA"]["FIRST"].at(0).push_back({"MIDDLE", 50});
std::cout << second.dump().c_str();
the output:
{"GLOBAL DATA":{"FIRST": [{"BEGIN":"0","END":"100","MIDDLE":50}],"SECOND":"SomeData","THIRD":"SomeMoreData"}}

Related

How to return json string of arrays using rapidjson

I have a json file which looks like this
{
"ActivityId":"CB8FA1DA-DCB4-40B3-9D12-2786BD89B4D4",
"AdditionalParams":{
},
"Extensions":[
{
"Id":"1234",
"IsEnabled":false,
"Name":"Name1"
},
{
"Id":"4567",
"IsEnabled":false,
"Name":"Name2"
},
{
"Id":"8910",
"IsEnabled":true,
"Name":"Name3"
}
]
}
I see a lot of code online which tries to get the IsEnabled,Name fields(as an example). However, I am trying to use rapidjson to print out the array of extensions as is.
Here is the code that I have tried
Document document;
document.Parse(json);
if (document.HasMember(L"Extensions")) {
eventPayload = document[L"Extensions"].GetString();
}
document[L"Extensions"] is not a string, it's an array, so you will have to first getArray, then iterate through it with a JSONIterator and then get the value of IsEnabled.
Also, you don't have to use L"", since they are normal strings and not wide strings.

c++ JsonCpp parse string with escaped quotes as array

I've got the following json string:
{
"data" :
[
{
"cart" : "[{\"name\":\"Test item 1\",\"price\":15,\"quantity\":1,\"sum\":15,\"tax\":\"none\",\"payment_type\":\"advance\",\"item_type\":\"service\"},{\"name\":\"Test item 2\",\"price\":13.01,\"quantity\":2,\"sum\":26.02,\"tax\":\"none\",\"payment_type\":\"part_prepay\",\"item_type\":\"work\"}]",
"contact" : "noname#google.com",
"p_id" : "603",
"sum" : "100.02",
"tax_system" : "osn"
}
],
"msg" : null,
"result" : "success"
}
I can parse cart as std::string after parsing input json string as stringstream:
const std::string ParseJsonData(std::stringstream ssJsonStream)
{
Json::Value jsonData;
Json::Value responseData;
Json::Value responseDataCart;
Json::CharReaderBuilder jsonReader;
std::string errs;
if (Json::parseFromStream(jsonReader, ssJsonStream, &jsonData, &errs)) {
responseData = jsonData["data"];
responseDataCart = responseData[0]["cart"];
return responseDataCart.toStyledString().c_str();
}
else
return "Could not parse HTTP data as JSON";
}
Please, tell me, how can i parse cart as array with JsonCpp?
The same way you parsed the outer JSON!
You started with a string (well, hidden by a stream) and turned it into JSON.
Now that JSON contains a property that is a string and, itself, contains JSON. The problem is recursive. The fact that the inner string originally came from JSON too can be ignored. Just pretend it's a string you typed in.
So, you can use JSON::Reader to in turn get the JSON out of that string.
Something like:
const std::string responseDataCartStr = responseData[0]["cart"].asString();
Json::Reader reader;
if (!reader.parse(responseDataCartStr, responseDataCart))
throw std::runtime_error("Parsing nested JSON failed");
JsonCpp provides a few ways to parse JSON and it's worth exploring them to find the most appropriate for your use case. The above is just an example.
Ignore the backslashes — the escaping was meaningful within the encapsulating JSON document, but the outermost parse stage should already have taken that into consideration. You'll see if you print responseDataCartStr to console that it is a valid JSON document in its own right.

Trying to parse JSON data

I'm writing C++ code using curl and JsonCpp (https://github.com/open-source-parsers/jsoncpp). Json::parseFromStream returns the following data:
Funds: [
{
"id" : 1,
"jsonrpc" : "2.0",
"result" :
{
"availableToBetBalance" : 437.91000000000003,
"discountRate" : 4.0,
"exposure" : 0.0,
"exposureLimit" : -5000.0,
"pointsBalance" : 3135,
"retainedCommission" : 0.0,
"wallet" : "UK"
}
}
]
How do I extract availableToBetBalance - I've tried things like:
std::string d = json_data["result.availableToBetBalance"].asString();
and:
std::string d = json_data["result"]["availableToBetBalance"].asString();
The latter throws and exception : in Json::Value::resolveReference(key, end): requires objectValue
You're ignoring the array layer, signified by the outer [ and ] characters.
In this particular case, the data you're looking for is in the first (and only) element of an array, so:
std::string d = json_data[0]["result"]["availableToBetBalance"].asString();
// ^^^

bsonxx::from_json convert all value types to string

I am using Boost's Property Tree library for storing my json files. For example,
I have the following JSON file:
{
"var" : true,
"bar" : -1.56
}
Next I parse this file to ptree object, do my job and want to store output in MongoDB. For this I convert it back to JSON string:
boost::property_tree::ptree root;
boost::property_tree::read_json(file_path, root);
... // do my job
std::stringstream ss;
boost::property_tree::json_parser::write_json(ss, root);
std::string my_json_string = ss.str();
After this I push my results to MongoDB, by converting JSON string to BSON like this: bsonxx::from_json(my_json_string). As result I receive the following entity in database:
{
"var" : "true",
"bar" : "-1.56"
}
Is there a way to insert my JSON string to MongoDB with persistence types?

JSON array with multiple values c++

I have this body request example:
{
"users": [{
"userId": 123
}, {
"userId": 1234
}]
}
For the previous example I receive one std::list<UsersId>* VUsers that have my userId (in this case '123' and '1234'), create cJSON array, iterate my list and get all userId. (Note: the UsersId is one auxiliar class that I use and receive one int in constructor)
cJSON* cJsonUsers = cJSON_CreateArray();
cJSON_AddItemToObject(root, "VUsers", cJsonUsers);
std::list<UsersId>::const_iterator itUsers = VUsers->begin();
while (itUsers != VUsers->end())
{
cJSON *cJsonVNode = cJSON_CreateObject();
cJSON_AddItemToArray(cJsonUsers, cJsonUser);
cJSON_AddNumberToObject(cJsonUser, "userId", itUsers->userId);
++itVNodes;
}
But know I want to the same but make more simple/easy and need to change the body request to something like this:
{
"users": {
"userId": [123, 1234]
}
}
I'm using this c++ library -> https://github.com/DaveGamble/cJSON but I dont understand how to do to implement the modification that I need.
EDIT 2 (PARSE THE JSON)
cJSON* cJsonUsers = cJSON_GetObjectItem(root, "users");
if (!cJsonUsers) return 0;
if (cJsonUsers->type != cJSON_Array) return 0;
std::list<VUserId>* users = new std::list<VUserId>();
cJSON* cJsonVUser;
cJSON_ArrayForEach(cJsonVUser, cJsonUsers)
{
cJSON* cJsonVUserId = cJSON_GetObjectItem(cJsonVUser, "userId");
if (!cJsonVUserId) continue;
int user_id = cJsonVUserId->valueint;
VUserId userId(user_id);
users->push_back(userId);
}
Something like this could work, that is, create the object and array outside of the loop, and insert the numbers inside the loop:
cJSON* cJsonUsers = cJSON_CreateObject();
cJSON_AddItemToObject(root, "users", cJsonUsers);
cJSON* cJsonUserId = cJSON_CreateArray();
cJSON_AddItemToObject(cJsonUsers, "userId", cJsonUserId);
std::list<UsersId>::const_iterator itUsers = VUsers->begin();
while (itUsers != VUsers->end())
{
cJSON_AddItemToArray(cJsonUserId, cJSON_CreateNumber(itUsers->userId));
++itVNodes;
}
Note that there are languages out there that are more convenient to manipulate JSON if you have the flexibility (disclaimer: I was involved in the design of some of these). Of course there are always use cases when you have to use C++ and in which a library makes a lot of sense.
With languages such as C++ or Java, there is an impedance mismatch between objects in the classical sense, and data formats like XML or JSON. For example, with the standardized, declarative and functional XQuery 3.1 this does not need much code to transform the first document into the second:
let $original-document := json-doc("users.json")
return map {
"users" : map {
"userId" : array { $original-document?users?*?userId }
}
}