Im developing a program in C that returns info from a DLL to be used in a webpage. The DLL returns a big struct with information but only need some fields that i plan to return as a json using https://github.com/nlohmann/json and then to char*.
Here is an example of the struct and the meaning of the values of each field (acording to the documentation pdf)
struct myStruct {
BYTE StatusCode;
BYTE ErrorCode;
DWORD WarningCode[2];
otherStruct SystemInfo[16];
...
}
StatusCode:
0x00 = No Error
0x01 = Error
0x02 = Ready
...
0x05 = Power Off
WarningCode
0x00 0x00 = No warning
0x02 0x01 = Warning Alert
... etc
Here is how i access the fields of the struct:
GetInfoStatus(&myStatusStruct);
jInfo["error_code"] = myStatusStruct.ErrorCode;
jInfo["status_code"] = myStatusStruct.StatusCode;
jInfo["warning_code"] = myStatusStruct.WarningCode2;
jInfo["is_available_warning_code"] = myStatusStruct.AvailableWarningCode2;
std::string info = jInfo.dump();
return info.c_str();
// My current return char* "json"
// {"available_warning_code":1,"error_code":255,"status_code":4}
But i would like to have something like this
{"available_warning_code": [0x01, "warning_alert"], "error_code": [0x01, "error_system_fail"], "status_code": [0x04, "low_battery"]}
Or similar so i can return also an error code to a "string" or "error_message" that indicates the meaning (a traslation) so my backend/frontend (NodeJS) later can detect "low_battery" and do something about it, instead of having to match 0x04 to a table to understand a 0x04 (that is different from other 0x04 in other key)
Ive checked this solution https://stackoverflow.com/a/208003/4620644 but still dont understand if is the best for my case and how to implement it. I have like 20 error codes, 10 warning codes, 15 status codes.
CodePudding user response:
You could create a std:pair
and use that in the json. Somewhere, though, you are going to have to type out all the error messages.
#include <iostream>
#include <vector>
#include <string>
#include <utility>
#include "json.h"
using namespace nlohmann;
std::pair<int, std::string> make_error(int error)
{
// Use a vector if error codes are sequential
// Otherwise, maybe a switch
std::vector<std::string> error_msgs = {
"No Error", "Error", "Ready"
};
if (error >= 0 && error < error_msgs.size()) {
return std::make_pair(error, error_msgs[error]);
}
else {
return std::make_pair(error, "Unknown");
}
}
int main()
{
json jInfo;
jInfo["error_code"] = make_error(2);
std::cout << jInfo.dump();
return 0;
}
This outputs:
{"error_code":[2,"Ready"]}
You'll have to do this for the other fields as well.
CodePudding user response:
To get error string
class CodeMap {
map<pair<int, int>, string> m_warningCodes {
{make_pair(0,0), "No warning"},
{make_pair(2,1), "Warning Alert"}
};
map<int, string> m_statusCode{
{0, "No Error"},
{1, "Error"},
{2, "Ready"},
{5, "Power Off"},
};
public:
std::string GetWarningCode(int code[]){
return m_warningCodes[make_pair(code[0], code[1])];
}
std::string GetStatusCode(int code){
return m_statusCode[code];
}
};
Hexadecimal in json do not comply to RFC 7159
https://github.com/nlohmann/json/issues/249
Approach 1: Hex as string
To get hex from int type
//with c 20 std::format can be used instead below function
std::string GetHex(int i) {
std::stringstream stream;
stream << "0x" <<std::hex << i;
return stream.str();
}
Assign key value pair to json field
CodeMap m; //To get message string
jInfo["error_code"] = make_pair(GetHex(myStatusStruct.ErrorCode), "error_system_fail");
jInfo["status_code"] = make_pair(GetHex(myStatusStruct.StatusCode), m.GetStatusCode(myStatusStruct.StatusCode));
output:
"error_code": ["0x01", "error_system_fail"], "status_code": ["0x04", "low_battery"]
Approach 2: Hex as integer
Assign key value pair to json field
CodeMap m; //To get message string
jInfo["error_code"] = make_pair(myStatusStruct.ErrorCode, "error_system_fail");
jInfo["status_code"] = make_pair(myStatusStruct.StatusCode, m.GetStatusCode(myStatusStruct.StatusCode));
output:
"error_code": [1, "error_system_fail"], "status_code": [4, "low_battery"]