My program is rebelling? Changes are not made - c++

I have an annoying problem with Visual Studio. Indeed, I am in the design of a compiler, and I have a file reserved for error messages. It works with a dictionary (std::map): code → message.
However, the changes made to the dictionary do not seem to affect the program, which reacts as if no changes had been made.
It would be difficult for me to explain more clearly with words, so I recorded a video. (It does not belong to the site, sorry, I did not find how to include it i, this post).
As you can see, we use a function that displays the error message as it gets it from the dictionary :
std::map<ErrorCodes, std::string> Messages;
...
std::string ErrMessage = Messages[code];
I do not understand why the changes made do not affect the program as intended. It seems that Visual Studio no longer compiles part of the code...
Indeed, in the recording, we can see that the error message displayed in the console is the [E29] (the old one before the [E80]), and that the message displayed is not the one that corresponds with the enumeration either.
The problem may seem simple, but I honestly do not see where it might lie...
EDIT:
Here is a more detailed explanation:
In the video, the program running in the console is mine. "Compilation not success" is my own error message, and it is normal that it is displayed.
Here is the call code of the error call display:
exception.ThrowError(exception.E0080);
E0080 is the error listing code, here are the error message files :
*.hpp:
class Exception {
public:
enum ErrorCodes {
E0000,
E0001, // Can't load file
E0002, // Can't find header file
E0003, // Expected file name
E0004, // Unexpected token
E0005, // Expected Identifier
E0006, // Value without storage object
E0007, // Already existing object
E0008, // Redefined preprocessor definition
E0009, // Redefined variable
E0010, // Redefined function
E0011, // Redefined object
E0012, // Redefined rule
E0013, // Redefined value
E0014, // Undefined identifier
E0015, // Buoyage symbol missing
E0016, // Expected end of line symbol (';')
E0017, // Unexpected character
E0018, // Unknown token
E0019, // Non-close comment
E0020, // Non-compliant typing
E0021, // Use of uninitialized data
E0022, // Unacceptable suffix
E0023, // Invalid keyword combination
E0024, // Declaration not in accordance with non-local use
E0025, // Incompatible value with type / object defined
E0026, // Constant value too wide
E0027, // Too much initialization value in a static size array
E0028, // Non-conforming identifier
E0029, // Expected statement
E0030, // Wrong identifier format (the expected format is ASCII)
E0031, // Wrong pointer initialization
E0032, // Non-valid literal suffix
E0033, // No object can have the identifier 'vanaur'
E0034, // Non-existent object field
E0035, // Non-existent object method
E0036, // Missing function call arguments
E0037, // A rvalue cannot be accessed via the pointers
E0038, // The use of a pointer is unacceptable in this context
E0039, // A reference cannot be made to a constant value
E0040, // Invalid assembler code in external expression
E0041, // The types of the two objects do not match in the image assignment
E0042, // Only a defined object can be destroyed by the delete operator
E0043, // Empty template
E0044, // Object not existing in this namespace
E0045, // Typage temptation with a non-instanciated structure
E0046, // Temptation to access a private field of the object
E0047, // Temptation to access a private method of the object
E0048, // Invalid operator
E0049, // Reserved identifier
E0050, // Wrong usage of postfix and prefix operator
E0051, // Temptation to access an inaccessible element in a table
E0052, // The main function can only have 3 arguments variation
E0053, // This function is not defined as being able to return an array
E0054, // A non-instanciated structure cannot be used as an object instance with the keyword 'new'.
E0055, // Wrong choice of the anonymous string concatenation operator (between '^' and'+')
E0056, // An object can only inherit from one other object
E0057, // Incorrect 'typename' value
E0058, // Incorrect 'typesize' value
E0059, // The identifier of a process ('proc') cannot contain spaces
E0060, // The identifier of a process ('proc') cannot contain balises
E0061, // An exception cannot be thrown out of a function
E0062, // Syntax error
E0063, // The increment value of an iteration (with step) must be numerical
E0064, // An anonymous array serving as an iterator to a for loop cannot be empty
E0065, // Wrong ternary condition format
E0066, // A 'ret' instruction must only fit on one instruction (one line = one ';')
E0067, // Division by zero
E0068, // Wrong enumeration value
E0069, // 'Upon' block members cannot contain expressions other than 'it'
E0070, // A match/case expression must contain at least one 'case' expression before using 'default'
E0071, // Unknown error
E0072, // Undefined object
E0073, // Not a valid math expression
E0074, // Expected character
E0075, // Unbalanced brackets
E0076, // Non-ascii character detected
E0077, // The current version of Arlia only accepts constant values as optional function parameters
E0078, // Undefined type
E0079, // Statement not recognised in this context
E0080, // Invalid statement
};
void ThrowError(ErrorCodes, char);
void ThrowError(ErrorCodes, std::string);
void ThrowError(ErrorCodes, token_t);
void ThrowError(ErrorCodes, token_t, Expr);
void ThrowError(ErrorCodes, Expr);
private:
std::map<ErrorCodes, std::string> Messages =
{
{ E0001, " Can't load file" },
{ E0002, " Can't find header file" },
{ E0003, " Expected file name" },
{ E0004, " Unexpected token" },
{ E0005, " Expected Identifier" },
{ E0006, " Value without storage object" },
{ E0007, " Already existing object" },
{ E0008, " Redefined preprocessor definition" },
{ E0009, " Redefined variable" },
{ E0010, " Redefined function" },
{ E0011, " Redefined object" },
{ E0012, " Redefined rule" },
{ E0013, " Redefined value" },
{ E0014, " Undefined identifier" },
{ E0015, " Buoyage symbol missing" },
{ E0016, " Expected end of line symbol (';')" },
{ E0017, " Unexpected character" },
{ E0018, " Unknown token" },
{ E0019, " Non-close comment" },
{ E0020, " Non-compliant typing" },
{ E0021, " Use of uninitialized data" },
{ E0022, " Unacceptable suffix" },
{ E0023, " Invalid keyword combination" },
{ E0024, " Declaration not in accordance with non-local use" },
{ E0025, " Incompatible value with type / object defined" },
{ E0026, " Constant value too wide" },
{ E0027, " Too much initialization value in a static size array" },
{ E0028, " Non-conforming identifier" },
{ E0029, " Expected statement" },
{ E0030, " Wrong identifier format (the expected format is ASCII)" },
{ E0031, " Wrong pointer initialization" },
{ E0032, " Non-valid literal suffix" },
{ E0033, " No object can have the identifier 'vanaur'" },
{ E0034, " Non-existent object field" },
{ E0035, " Non-existent object method" },
{ E0036, " Missing function call arguments" },
{ E0037, " A rvalue cannot be accessed via the pointers" },
{ E0038, " The use of a pointer is unacceptable in this context" },
{ E0039, " A reference cannot be made to a constant value" },
{ E0040, " Invalid assembler code in external expression" },
{ E0041, " The types of the two objects do not match in the image assignment" },
{ E0042, " Only a defined object can be destroyed by the delete operator" },
{ E0043, " Empty template" },
{ E0044, " Object not existing in this namespace" },
{ E0045, " Typage temptation with a non-instanciated structure" },
{ E0046, " Temptation to access a private field of the object" },
{ E0047, " Temptation to access a private method of the object" },
{ E0048, " Invalid operator" },
{ E0049, " Reserved identifier" },
{ E0050, " Wrong usage of postfix and prefix operator" },
{ E0051, " Temptation to access an inaccessible element in a table" },
{ E0052, " The main function can only have 3 arguments variation" },
{ E0053, " This function is not defined as being able to return an array" },
{ E0054, " A non-instanciated structure cannot be used as an object instance with the keyword 'new'" },
{ E0055, " Wrong choice of the anonymous string concatenation operator (between '^' and'+')" },
{ E0056, " An object can only inherit from one other object" },
{ E0057, " Incorrect 'typename' value" },
{ E0058, " Incorrect 'typesize' value" },
{ E0059, " The identifier of a process ('proc') cannot contain spaces" },
{ E0060, " The identifier of a process ('proc') cannot contain balises" },
{ E0061, " An exception cannot be thrown out of a function" },
{ E0062, " Syntax error" },
{ E0063, " The increment value of an iteration (with step) must be numerical" },
{ E0064, " An anonymous array serving as an iterator to a for loop cannot be empty" },
{ E0065, " Wrong ternary condition format" },
{ E0066, " A 'ret' instruction must only fit on one instruction (one line = one ';')" },
{ E0067, " Division by zero" },
{ E0068, " Wrong enumeration value" },
{ E0069, " 'Upon' block members cannot contain expressions other than 'it'" },
{ E0070, " A match/case expression must contain at least one 'case' expression before using 'default'" },
{ E0071, " Unknown error" },
{ E0072, " Undefined object" },
{ E0073, " Not a valid math expression" },
{ E0074, " Expected character" },
{ E0075, " Unbalanced brackets" },
{ E0076, " Non-ascii character detected" },
{ E0077, " The current version of Arlia only accepts constant values as optional function parameters" },
{ E0078, " Undefined type" },
{ E0079, " Statement not recognised in this context" },
{ E0080, " Invalid statement" },
{ E0000, " ... " }
};
};
The *.cpp just implements the functions as follows :
ThrowError(ErrorCodes code) {
colored_message_error("[ E" + std::to_string(code) + " ]" + Messages[code], Color::yellow);
}
As you can see, the list contains 80 + 1 elements. And E0080 has 80 as index in the enumeration.
When I try to access it:
exception.ThrowError(exception.E0080);
my program doesn't seem to want to update the information. That is, the enumeration constant sent to the function: in fact, the program displays the value I set before it (E29).
It's exactly like I'm doing this:
exception.ThrowError(exception.E0029);
So, no, it's most likely not a stupid debugging or compiling problem (I still know how to use a compiler ^^). It seems strange that Visual Studio does not update this new data (how ? why ? is it ?).

Related

Error handling design: Bind error messages to error codes

I have a simple structures to handle errors
enum class Error
{
None = 0,
FirstError,
SecondError,
ThirdError,
...
}
struct ErrorCategory
{
static const std::string& Message(Error aError)
{
static const std::string messages[] =
{
"first error message",
"second error message",
"third error message",
...
}
const auto index = static_cast<size_t>(aError);
assert(index < std::size(messages) && "Invalid error");
return messages[index];
}
};
Also, there are some class and methods to work with those structures.
Though it works, but the amount of errors is growing, so it becomes hard to navigate between error messages and error codes in enum. I want to declare error code and message for it in one place to make it easy to find error code. Is there a way to do it without making my code huge (such as enum + switch cases for messages) so it would be easy to maintain and without using macro?
You can use std::map<Error, std::string> like:
enum class Error : uint8_t {
None = 0,
FirstError = 1,
SecondError = 2,
ThirdError = 3
};
std::map<Error, std::string> error_messages = {
{ Error::None, "unknown error message" },
{ Error::FirstError, "first error message" },
{ Error::SecondError, "second error message" },
{ Error::ThirdError, "third error message" }
};
and then use it afterwards like:
std::cerr << error_messages[Error::None] << std::endl;
std::cerr << error_messages[Error::FirstError] << std::endl;
std::cerr << error_messages[Error::SecondError] << std::endl;
std::cerr << error_messages[Error::ThirdError] << std::endl;
Demo
This type of operation is exactly how most localized UIs work. You map some common structured ID to a user-facing string.
Because of this, there are a huge amount of platform-specific ways of doing this which aim to do exactly what you want. For example on Windows:
(Windows) FormatMessage and Message Compiler
(Windows / .NET) .resx files and ResourceManager

JSON parsing using nlohmann json

I am trying to parse the JSON structure using nlohmann's json.hpp
. But I am not to create the JSON structure from the string. I have tried all the way, but still it is failing.
My requirement is to:
1) Create the JSON structure from the string.
2) Find the value of "statusCode" from it.
After trying for so long time, I am really getting doubt, does nlohmann's json parser support nested JSON or not.
#include "json.hpp"
using namespace std;
int main(){
// giving error 1
nlohmann::json strjson = nlohmann::json::parse({"statusResp":{"statusCode":"S001","message":"Registration Success","snStatus":"Active","warrantyStart":"00000000","warrantyEnd":"00000000","companyBPID":"0002210887","siteBPID":"0002210888","contractStart":"00000000","contractEnd":"00000000"}});
// Giving error 2:
auto j= "{
"statusResp": {
"statusCode": "S001",
"message": "Registration Success",
"snStatus": "Active",
"warrantyStart": "20170601",
"warrantyEnd": "20270601",
"companyBPID": "0002210887",
"siteBPID": "0002210888",
"contractStart": "00000000",
"contractEnd": "00000000"
}
}"_json;
// I actually want to get the value of "statusCode" code from the JSOn structure. But no idea how to parse the nested value.
return 1;
}
Below are the error for both the initialisations:
//ERROR 1:
test.cpp: In function 'int main()':
test.cpp:17:65: error: expected '}' before ':' token
nlohmann::json strjson = nlohmann::json::parse({"statusResp":{"statusCode":"S001","message":"Registration Success","snStatus":"Active","warrantyStart":"00000000","warrantyEnd":"00000000","companyBPID":"0002210887","siteBPID":"0002210888","contractStart":"00000000","contractEnd":"00000000"}});
// ERROR 2:
hemanty#sLinux:/u/hemanty/workspaces/avac/cb-product/mgmt/framework/src/lib/libcurl_cpp$g++ test.cpp -std=gnu++11
test.cpp: In function 'int main()':
test.cpp:27:17: error: expected '}' before ':' token
"statusResp": {
Since " is the character to begin and end a string literal you can not have a " character inside a string without putting a \ before it.
std::string str = " "statusCode":"5001" "; //This does not work
std::string str = " \"statusCode\":\"5001\" "; //This will work
An easier alternative when you want to make strings with a lot of " in them is to use the R"" string literal. Then you can write it like so.
std::string str = R"("statusCode":"5001")";
If we now transfear this to your json example, the correct way to parse the strings would be one of the following.
auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
// and below the equivalent with raw string literal
auto j3 = json::parse(R"({"happy": true, "pi": 3.141 })");
//Here we use the `_json` suffix
auto j2 = "
{
\"happy\": true,
\"pi\": 3.141
}"_json;
// Here we combine the R"" with _json suffix to do the same thing.
auto j2 = R"(
{
"happy": true,
"pi": 3.141
}
)"_json;
Examples taken from the readme
If this is what you need:
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;
}
Or:
json myjson = { {"name", "tom"}, {"age", 11} };
cout << "name=" << myjson["name"].get<std::string>() << endl;

using json spirit to read the name and value of Value objects in C++

I have a text file that's got data written in JSON format.
The data looks something like this --
[
...
{
"volume": 93,
"id": "part-30",
"value": 19
},
{
"volume": 83,
"id": "part-31",
"value": 19
}
...
]
After referring to this and this
I've gotten to a point where I can read the "name" field of the following data structure.
So all other things aside, my code to read this object looks like this --
// read from parts list file to JSON object.
const char* file_name2( "parts_list.txt" );
ifstream is2( file_name2 );
json_spirit::Value value2;
read( is2, value2 );
// const Object& addr_array = value.get_obj();
vector<Value> jsonObj2 = value2.get_array();
vector<Value>::iterator it;
vector<RobotParts> final;
for(it = jsonObj2.begin(); it!=jsonObj2.end(); it++)
{
auto valObj = it->get_obj();
RobotParts rpObj = RobotParts();
for(auto vo : valObj)
{
if(vo.name_=="volume"){
string s = vo.value_;
}
}
final.push_back(rpObj);
}
cout << final.size() << endl;
return 0;
But this line here --> vo.value_; seems to be creating a lot of problems.
I'm unable to figure out what's the data type of this object.
So far I've tried :
Reading into an integer. I thought since the volume has an integer value
int i = vo.get_value< int >();
Should work. But instead, it says
error: no member named 'get_value' in
'json_spirit::Pair_impl<json_spirit::Config_vector<std::__1::basic_string<char> > >'
Reading into a string so I could print it out.
string s = vo.value_;
This throws the following error:
error: no viable conversion from 'Value_type' (aka
'Value_impl<json_spirit::Config_vector<std::__1::basic_string<char> > >') to 'string' (aka 'basic_string<char, char_traits<char>,
allocator<char> >')
I can, however, print out vo.name_ by using cout << vo.name_ << endl within the loop.
This outputs :
...
volume
id
value
volume
id
value
...
so on.
I know this is due to data type incompatibility but I've spent two-three hours now unable to figure out how to access this value.
How do I access these values corresponding to volume, id and value?

mongodb query with c++ legacy driver results in BSONElement: bad type -64

I am trying to a process an array in a mongodb collection using the c++ mongo driver. However I always end up with the error message:
terminate called after throwing an instance of mongo::MsgAssertionException'
what(): BSONElement: bad type -64
Aborted (core dumped)
I tried to find it on google, but the only answers if found told me to repair my database. I did this but the error stay.
I am really confused by this error. The collection printed by the mongo-shell seems not to be corrupted and the shell also does not claim any error (see below). So I would assume that the vector rawDataArray generated in my code (see also below) is holding valid data. However, when I try to print the values I get the mentioned error message.
What am I doing wrong?
Thanks a lot
Michael
PS:
I am using the mongodb C++ legacy driver and the error is generated by the following piece of code:
mongo::DBClientConnection connection;
connection.connect("localhost");
mongo::BSONObj resultObj;
try
{
std::auto_ptr<mongo::DBClientCursor> cursor =
connection.query("mydb.results",
MONGO_QUERY( "_id" << mongo::OID(resultID) ) );
while (cursor->more())
{
resultObj = cursor->next();
}
}
catch( const mongo::DBException &e )
{
// error handling
}
// extract raw_data array
std::vector<mongo::BSONElement> rawDataArray;
if( resultObj.hasField("raw_data") )
{
rawDataArray = resultObj["raw_data"].Array();
}
else
{
// error handling
}
for(auto const & data : rawDataArray)
{
std::cout << data << std::endl;
}
The collection is looking like:
db.getCollection('results').find({}).pretty()
{
"_id" : ObjectId("56cf1315f7e0583e2c4ec702"),
"experiment_id" : ObjectId("56c5b8e7e1fa370a1de9d06f"),
"module_id" : ObjectId("56c5b8e7e1fa370a1de9d06e"),
"raw_data" : [
{
"id_number" : "0accb65f4fc311",
"box" : "0accb65f4fc3",
"paper" : 1,
"seed" : 1,
"length" : 0,
"time" : ISODate("2015-09-15T20:00:00.000Z")
},
{
"id_number" : "0accb65f4fc312",
"box" : "0accb65f4fc3",
"paper" : 1,
"seed" : 2,
"length" : 0,
"time" : ISODate("2015-09-15T20:00:00.000Z")
},
{
"id_number" : "0accb65f4fc313",
"box" : "0accb65f4fc3",
"paper" : 1,
"seed" : 3,
"length" : 0,
"time" : ISODate("2015-09-15T20:00:00.000Z")
},
... skipped some data here, there are 204 nearly identical elements
{
"id_number" : "0accb65f4fc3451",
"box" : "0accb65f4fc3",
"paper" : 4,
"seed" : 51,
"length" : 0,
"time" : ISODate("2015-09-15T20:00:00.000Z")
}
],
"processed_data" : []
}
You are accessing resultObj after the cursor object has been destroyed, but resultObj is merely viewing data owned by the cursor. Call getOwned on the BSONObj to get an owning copy if you need its lifetime to extend beyond the lifetime of the cursor which returned it.

Poco C++ building nested JSON objects

I have a nested JSON object. I'm trying to build it in a function and add the inner object to the original, but I can't extract the result.
void build_object (Poco::JSON::Object * const result)
{
/* Construct some int/bool/string fields here */
Poco::JSON::Object inner;
inner.set("some_number", 5);
inner.set("some_string", "xyz");
/* This is where it breaks down */
std::string key = "new_object";
result->set("new_object", inner);
/* Then some debugging and testing */
// The new object is printed inside the first -> seems like it's working
result->stringify(std::cout);
printf("result has(key): %i\n", result->has(key)); // true
printf("isObject: %i\n", result->isObject(key)); // false - huh?
printf("isNull: %i\n", result->isNull(key)); // false
printf("isArray: %i\n", result->isArray(key)); // false
Poco::JSON::Object::Ptr ptr = result->getObject(key);
// unsurpisingly fails since the above indicates it's not an object
printf("ptr isNull: %i\n", ptr.isNull()); // true
// ptr->has("some_number"); // throws NullPointerException
// if it's not an object/null/array, it must be a value
Poco::Dynamic::Var v = result->get(key);
// at least one of these things should be true, otherwise what is it?
printf("var isString: %i\n", v.isString()); // false
printf("var isStuct: %i\n", v.isStruct()); // false
printf("var isEmpty: %i\n", v.isEmpty()); // false
printf("var isArray: %i\n", v.isArray()); // false
printf("var isSigned: %i\n", v.isSigned()); // false
printf("var isNumeric: %i\n", v.isNumeric());// false
}
So, I have an inner object that is correctly put into the result, it is being printed via stringify with all the correct values and result->has() is successful. But, according to the result, it is not an object, array, or null, so you should be able to get it with var. But, once it's gotten from var, it's not a string, struct, array, or number, and it's also not empty. The inner object seems to exist and not exist at the same time.
So, how do I put this object into my result? And how do I get it out?
Thanks
note: I've seen this thread Correct usage of Poco C++ JSON for parsing data, but it's building the JSON object from string and then parsing it. I suppose I could build everything as a string and convert to the Poco Object at the last step, but I'm still curious why the above is happening. Also, using result->set() and result->get() are a cleaner, less hack-y solution than going through a string.
References: Poco JSON Doc,
Poco Dynamic Var Doc
Poco::JSON Objects and Arrays are held as shared pointers internally by default (optimization to avoid values copying) and everything is Dynamic::Var, so it works for both pointers and values. When you insert an Object as value it works because Dynamic::Var will hold pretty much anything, but the problem you experience when inspecting it comes from the fact that internal comparison does not return true for Object values because it compares only with default type - Poco::SharedPtr<Poco::JSON::Object>.
Here's a workaround:
void build_object (Poco::JSON::Object * const result)
{
// smart pointer, so don't worry about cleaning up
Poco::JSON::Object::Ptr inner = new Poco::JSON::Object;
inner->set("some_number", 5);
inner->set("some_string", "xyz");
std::string key = "new_object";
result->set(key, inner);
printf("isObject: %i\n", result->isObject(key)); // true
}
I have opened a github issue to alleviate this caveat.
I have been trying to create json file having nested object using poco library. Finally able to do with Poco::Json::Array.
Please find the posted code sinippet. Hope it will help. Json output attached with post.
#include "Poco\JSON\JSON.h"
#include "Poco\JSON\Stringifier.h"
#include "Poco\JSON\Object.h"
#include "Poco\Dynamic\Var.h"
using namespace std;
using Poco::JSON::Stringifier;
using Poco::JSON::Object;
using Poco::JSON::Array;
void makeJsonNestedObject()
{
Object RootObj(true);
Array FLArray;
for(int i=0; i<3; i++)
{
Object::Ptr FirstLevelArrayNode = new Poco::JSON::Object(true);
TCHAR strNameBuff[15];
_stprintf(strNameBuff, _T("%s_%d"),_T("Servername"),i);
std::basic_string<TCHAR> strName = strNameBuff;
FirstLevelArrayNode->set("HostName", strName);
FirstLevelArrayNode->set("Overall Impact", "Dummy Data");
Array SLArray;
for(int j=0; j<3;j++)
{
Object::Ptr SecondLevelArrayNode = new Poco::JSON::Object(true);
TCHAR attr1NameBuff[15];
TCHAR attr2NameBuff[15];
_stprintf(attr1NameBuff, _T("%s_%d"),_T("AttrOne"),j);
_stprintf(attr2NameBuff, _T("%s_%d"),_T("AttrTwo"),j);
std::basic_string<TCHAR> attr1Name = attr1NameBuff;
std::basic_string<TCHAR> attr2Name = attr2NameBuff;
SecondLevelArrayNode->set("Attribute", attr1Name);
SecondLevelArrayNode->set("SubAttribute", attr2Name);
Poco::Dynamic::Var obj(SecondLevelArrayNode);
SLArray.add(obj);
}
FirstLevelArrayNode->set("Attribute_Details",SLArray);
Poco::Dynamic::Var FLArrayNodeobj(FirstLevelArrayNode);
FLArray.add(FLArrayNodeobj);
}
std::ostringstream os;
std::cout <<"before stringlify.." << std::endl;
FLArray.stringify(os, 2);
std::cout << os.str() << std::endl;
}
Json output:
[
{
"HostName" : "Servername_0",
"Overall Impact" : "Dummy Data",
"Attribute_Details" : [
{
"Attribute" : "AttrOne_0",
"SubAttribute" : "AttrTwo_0"
},
{
"Attribute" : "AttrOne_1",
"SubAttribute" : "AttrTwo_1"
},
{
"Attribute" : "AttrOne_2",
"SubAttribute" : "AttrTwo_2"
}
]
},
{
"HostName" : "Servername_1",
"Overall Impact" : "Dummy Data",
"Attribute_Details" : [
{
"Attribute" : "AttrOne_0",
"SubAttribute" : "AttrTwo_0"
},
{
"Attribute" : "AttrOne_1",
"SubAttribute" : "AttrTwo_1"
},
{
"Attribute" : "AttrOne_2",
"SubAttribute" : "AttrTwo_2"
}
]
},
{
"HostName" : "Servername_2",
"Overall Impact" : "Dummy Data",
"Attribute_Details" : [
{
"Attribute" : "AttrOne_0",
"SubAttribute" : "AttrTwo_0"
},
{
"Attribute" : "AttrOne_1",
"SubAttribute" : "AttrTwo_1"
},
{
"Attribute" : "AttrOne_2",
"SubAttribute" : "AttrTwo_2"
}
]
}
]