How to get JSON objects value using casablanca in C++ - c++

I am new to Json. And i m using codeplex (casablanca) for reading the json values.
Below is the sample json string:
[{ "rollno": 2000,
"name": "suhani","marks":{"grade":"C"} }, {"rollno": 3000,"name": "ishu", "marks":{ "grade":"A"} }]
The code to access name & rollno, i am writing below code:
json::value jobj = json::value::parse(utility::conversions::to_string_t(resultbody));
for (unsigned int i = 0; i < jobj.size(); i++) {
auto getval = jobj[i];
if (getval.at(U("name")).is_string()) {
auto xstr = getval.at(U("name")).as_string();
std::string wide = utility::conversions::to_utf8string(xstr);
std::string str(wide.begin(), wide.end());
string name = str;
}
if (getval.at(U("rollno")).is_integer()) {
auto xstr = getval.at(U("rollno")).as_integer();
int rollno = xstr;
} }
HOW TO GET VALUE AT GRADE ?? When i access marks it is of type object, i am not getting how to access grade from there. Please respond.

Marks is still a json object. You'll need to access the grade property. From your code snippet add the following:
for (unsigned int i = 0; i < jobj.size(); i++) {
auto getval = jobj[i];
auto marks_object = getval.at(U("marks"));
auto grade_value = marks_object.at(U("grade")).as_string();

Related

Assign different values to different struct variables using loop

I have a struct of Examinee like below (each has 1 id and their scores of different subjects):
struct Examinee
{
string id;
float math, literature, physic, chemistry, biology, history, geography, civic_education, natural_science,
social_science, foreign_language;
};
Now i want to write a function that reads from a string different values and assign them to an Examinee. The string looks like this (each info is separated by a comma):
BD1200001,9,4.0,5.0,10,3.5,7.5,4.25,7.0,7.75,9.25,2.0
This is what i have done so far:
Examinee readExaminee(string line_info) {
//turn line_info to char*
int Line_info_length = line_info.length();
char* info = new char[Line_info_length + 1];
strcpy(info, line_info.c_str());
//create examinee
Examinee examinee;
//read id into examinee by token
char* token = strtok(info, ",");
examinee.id = token;
//read score and assign to subjects
while (token != NULL)
{
float score = strtof(token, NULL);
//assign score to appropriate subject
token = strtok(NULL, ",");
}
delete[] info;
return examinee;
}
The question is: Can i assign each score to each subject in while loop like above? How can i do that? If not, is assigning each score manually the only way?
I'd change the design of Examinee. Something along these lines:
struct Examinee
{
enum Subject {kSubjMath, kSubjLiterature, ..., kSubjForeignLanguage, kSubjCount};
string id;
float scores[kSubjCount];
};
This way you can access scores in a loop, e.g.
for (int subj = 0; subj < Examinee::kSubjCount; ++subj) {
examinee.scores[subj] = some_score;
}
Or access specific score as examinee.scores[Examinee::kSubjLiterature]
If you are unable or unwilling to change Examinee, you can sort of simulate this locally:
Examinee examinee;
float* scores[] = {&examinee.math, &examinee.literature, ..., &examinee.foreign_language};
for (int subj = 0; subj < std::extent_v<scores>; ++subj) {
*scores[subj] = some_value;
}

How to convert TRON address to different format

I have an issue while deploying contract in TRON network, where I am required to specify address in format that starts with 4.. or when I receive transactions history (here the api respond with 4.. addresses as well).
Therefore I have a question:
How to convert TRON address started with TLAXtqju7GKyqoP... to 419b6e043089843624c36f1e3b1e8572d189cbe170 and vice versa?
How to convert TRON address started with TLAXtqju7GKyqoP... to 419b6e043089843624c36f1e3b1e8572d189cbe170 and vice versa?
const TronWeb = require('tronweb');
const tronWeb = new TronWeb(
'http://127.0.0.1:9090',
'http://127.0.0.1:9090',
'http://127.0.0.1:9090',
'd6fbbf6eecffdb32172e391363a401f89617acb9dd01897b9fa180830a8a46b2',
);
Once you have the tronWeb object, then you can convert the addresses vice-versa by using tronWeb's address utility
For Example:
const addressInHexFormat = '414450cf8c8b6a8229b7f628e36b3a658e84441b6f';
const addressInBase58 = tronWeb.address.fromHex(addressInHexFormat);
> addressInBase58 = 'TGCRkw1Vq759FBCrwxkZGgqZbRX1WkBHSu'
const addressInHex = tronWeb.address.toHex(addressInBase58);
> addressInHex = '414450cf8c8b6a8229b7f628e36b3a658e84441b6f'
Note
The above tronWeb object is created by using Tron's Quickstart Docker container. In this way the addresses can be converted vice-versa.
You just should decode your base58Address from Base58. In result you will obtain addresschecksum, so you should remove last 4 bytes from result and obtain desired address.
address = 41||sha3[12,32): 415a523b449890854c8fc460ab602df9f31fe4293f
sha256_0 = sha256(address): 06672d677b33045c16d53dbfb1abda1902125cb3a7519dc2a6c202e3d38d3322
sha256_1 = sha256(sha256_0): 9b07d5619882ac91dbe59910499b6948eb3019fafc4f5d05d9ed589bb932a1b4
checkSum = sha256_1[0, 4): 9b07d561
addchecksum = address || checkSum: 415a523b449890854c8fc460ab602df9f31fe4293f9b07d561
base58Address = Base58(addchecksum): TJCnKsPa7y5okkXvQAidZBzqx3QyQ6sxMW
The address format is well explained in the relevant TRON documentation.
In Java code (based on wallet-cli):
public String tronHex(String base58) {
byte[] decoded = decode58(base58);
String hexString = decoded == null ? "" : org.spongycastle.util.encoders.Hex.toHexString(decoded);
return hexString;
}
private byte[] decode58(String input) {
byte[] decodeCheck = Base58.decode(input);
if (decodeCheck.length <= 4) {
return null;
}
byte[] decodeData = new byte[decodeCheck.length - 4];
System.arraycopy(decodeCheck, 0, decodeData, 0, decodeData.length);
byte[] hash0 = Sha256Hash.hash(decodeData);
byte[] hash1 = Sha256Hash.hash(hash0);
if (hash1[0] == decodeCheck[decodeData.length] &&
hash1[1] == decodeCheck[decodeData.length + 1] &&
hash1[2] == decodeCheck[decodeData.length + 2] &&
hash1[3] == decodeCheck[decodeData.length + 3]) {
return decodeData;
}
return null;
}
And the other way around:
public String hexStringTobBase58(String hexString) {
hexString = adjustHex(hexString);
byte[] decodedHex = hexString == null? new byte[0] : org.spongycastle.util.encoders.Hex.decode(hexString);
String base58 = encode58(decodedHex);
return base58;
}
private String adjustHex(String hexString) {
if (hexString.startsWith("0x")) {
hexString = "41" + hexString.substring(2);
}
if (hexString.length() % 2 == 1) {
hexString = "0" + hexString;
}
return hexString;
}
private String encode58(byte[] input) {
byte[] hash0 = Sha256Hash.hash(input);
byte[] hash1 = Sha256Hash.hash(hash0);
byte[] inputCheck = new byte[input.length + 4];
System.arraycopy(input, 0, inputCheck, 0, input.length);
System.arraycopy(hash1, 0, inputCheck, input.length, 4);
return Base58.encode(inputCheck);
}
Find class Base58 here, class Sha256Hash here and the required dependency to Spongy Castle here.
C# example:
public static string GetHex(this String str)
{
var sb = new StringBuilder();
var bytes = Base58.Bitcoin.Decode(str); // nuget https://www.nuget.org/packages/SimpleBase/
for (int i = 0; i < bytes.Length - 4; i++)
{
var t = bytes[i];
sb.Append(t.ToString("X2"));
}
return sb.ToString();
}

Best way to refactor If-statement

I have the following code:
if (adSetting.Core_standard_application_role)
{
rc = new IntegrationRoleCompany();
rc.RoleCompany = firmSettings.FirmNo.ToString();
rc.RoleName = "Core standard application role";
rcList.Add(rc);
}
if (adSetting.Expense_Invoice_Application_Access)
{
rc = new IntegrationRoleCompany();
rc.RoleCompany = firmSettings.FirmNo.ToString();
rc.RoleName = "Expense Invoice Application Access";
rcList.Add(rc);
}
The problem is that I have 20 if-checks where I check addSetting.Property. Now to the question:
What is the best and most effective way to refactor this if-statements?
you could have a 20x2 array with the adSetting.STUFF_AS_STRING -> rc.RoleName mapping.
then loop over the array in a for loop
pseudo code:
for (var i=0; i<theArray.length; i++) {
adSettingStr, RoleName = theArray[i]
if (adSetting[adSettingStr]) {
rc = new IntegrationRoleCompany();
rc.RoleCompany = firmSettings.FirmNo.ToString();
rc.RoleName = RoleName;
rcList.Add(rc);
}
}

Making an array for a static casted indexed array

I don't know if my title is right but I am trying to eliminate duplicate so I think I should put this definitions in an array. Can someone suggest me how I could put the pButtons in array? I am thinking something like pButton[EButtonHost], pButton[EButtonUsername] etc.
#define pButtonHost static_cast<XQtMultipleStringInputButton*>(m_pButtonList[EButtonHost])
#define pButtonUsername static_cast<XQtMultipleStringInputButton*>(m_pButtonList[EButtonUsername])
#define pButtonPassword static_cast<XQtMultipleStringInputButton*>(m_pButtonList[EButtonPassword])
I have a method below like this.
XIniFile readIniFile;
readIniFile.open(k_systemIniFile, EIniReadOnly);
string data;
readIniFile.readString("Server", "host", data);
pButtonHost->setString(data);
m_host = pButtonHost->getString();
readIniFile.readString("Server", "username", data);
pButtonUsername->setString(data);
m_username = pButtonUsername->getString();
readIniFile.readString("Server", "password", data);
pButtonPassword->setString(data);
m_password = pButtonPassword->getString();
They look like duplicates so I am trying to optimize it. Thanks!
Update:
I have something like this now. Would this be right? or do you have any better suggestions?
for (int i = 0; i < 3; ++i) {
readIniFile.readString("Server", k_dataList[i], data);
static_cast<XQtMultipleStringInputButton*>(m_pButtonList[i])->setString(data);
m_pData[i] = static_cast<XQtMultipleStringInputButton*>(m_pButtonList[i])->getString();
}
A below code looks clear by using auto and `lambda',
auto GetConfigInfo = [&](string section_name, ButtonType btn_type)-> string
{
readIniFile.readString("Server", section_name, data);
m_pButtonList[btn_type_]->setString(data);
return m_pButtonList->getString();
};
m_host = GetConfigInfo("host", EButtonHost);
m_username = GetConfigInfo("username", EButtonUserName);
m_password = GetConfigInfo("password", EButtonPassword);
and a define data type by using struct can be other method.
struct ConfigDefine
{
string section_;
ButtonType btn_type_; //your enum button type, such as EButtonHost, EButtonUserName
string& result_;
}configs[] =
{
{"host", EButtonHost, m_host},
{"username", EButtonUserName, m_username},
{"password", EButtonPassword, m_password}
};
for_each(std::begin(configs), std::end(configs), [&](ConfigDefine& config)
{
readIniFile.readString("Server", config.section_, data);
m_pButtonList[config.btn_type_]->setString(data);
config.result_ = pButtonHost->getString();
});
Do you intend to have something like this one?
#define ASIZE 3
int indx[ASIZE] = {EButtonHost, EButtonUsername, EButtonPassword};
string s[ASIZE] = {"host", "username", "password"};
string *m[ASIZE] = {&m_host, &m_username, &m_password};
for (int i = 0; i < ASIZE; i++) {
readIniFile.readString("Server", s[i].c_str(), data);
pButtonHost->setString(data);
*m[i] = pButtonHost->getString();
}

Create a json array in C++

So im trying to create a json Object in c++ dynamically. I want to add a timestamp and then an array with the data included.
So thats what my json String would look like :
{
"timestep": "2160.00",
"vehicles": [
{
"id": "35092_35092_353",
"x": "6.988270",
"y": "50.872139",
"angle": "-20.812787",
"type": "passenger_P_14_1",
"speed": "0.000000",
"pos": "4.600000",
"lane": "4.600000",
"slope": "4.600000"
},
{
"id": "35092_35092_353",
"x": "6.988270",
"y": "50.872139",
"angle": "-20.812787",
"type": "passenger_P_14_1",
"speed": "0.000000",
"pos": "4.600000",
"lane": "4.600000",
"slope": "4.600000"
},
{
"id": "35092_35092_353",
"x": "6.988270",
"y": "50.872139",
"angle": "-20.812787",
"type": "passenger_P_14_1",
"speed": "0.000000",
"pos": "4.600000",
"lane": "4.600000",
"slope": "4.600000"
}
]
}
Im totally new to C++ and im using the Casablanca ( C++ REST SDK) package.
So im having a really hard time producing the code. And i cant find any working solutions. I found this on the wiki
Create a JSON object:
json::value obj;
obj[L"key1"] = json::value::boolean(false);
obj[L"key2"] = json::value::number(44);
obj[L"key3"] = json::value::number(43.6);
obj[L"key4"] = json::value::string(U("str"));
and that works for me. But how do i create an array?
i tried several things but nothing worked. Maybe theres a better package? But as far as i understood its an official micorosft package for json and http.
Help would be really nice!
There are 2 mechanisms. If you are used to std c++ libraries, this should look familiar. Element vector is derived from std::vector.
json::value::element_vector e;
// the first item in the pair is the array index, the second the value
e.push_back(std::make_pair(json::value(0), json::value(false)));
e.push_back(std::make_pair(json::value(1), json::value::string(U("hello"))));
json::value arr(e);
And, if you prefer a cleaner look, and can accept a less efficient compiled result:
json::value arr;
arr[0] = json::value(false);
arr[1] = json::value(U("hello"));
From your message you have tried a bunch of stuff. If you have tried mechanisms like these but they didn't work, give us a sample program that demontrates the failure and we'll have a crack at it.
To get the basic structure in your file above:
json::value vehicles;
vehicles[0] = // 1st vehicle object
vehicles[1] = // 2nd vehicle object
// etc
json::value root;
root[L"timestep"] = json::number(2160.0);
root[L"vehicles"] = vehicles;
Here's how to create an array dynamically using vector. Assume that you have 10 vehicles to add.
std::vector<web::json::value> arrayVehicles;
for(int i = 0; i < 10; i++)
{
web::json::value vehicle;
std::string vehicleID = "id_prefix_" + std::to_string(i);
vehicle["id"] = web::json::value::string(vehicleID);
vehicle["x"] = web::json::value::number(6.988270);
vehicle["y"] = web::json::value::number(50.872139);
arrayVehicles.push_back(vehicle);
}
web::json::value myJSON;
myJSON["vehicles"] = web::json::value::array(arrayVehicles);
You could put it like this:
json::value vehicle1;
vehicle1[L"id"] = json::value::string(L"35092_35092_353");
vehicle1[L"x"] = json::value::number(6.988270);
vehicle1[L"y"] = json::value::number(50.872139);
json::value vehicle2;
vehicle2[L"id"] = json::value::string(L"35092_35092_353");
vehicle2[L"x"] = json::value::number(1.23456);
vehicle2[L"y"] = json::value::number(6.78901);
json::value vehicles;
vehicles[L"timestamp"] = json::value::number(2160);
vehicles[L"vehicles"] = json::value::array({vehicle1, vehicle2});
Here is another method to produce a json array in Casablanca:
int size = 3;
web::json::value yourJson;
yourJson[U("vehicles")] = web::json::value::array(size);
yourJson[U("vehicles")].as_array()[0] = web::json::value(U("some entry"));
yourJson[U("vehicles")].as_array()[1] = web::json::value(U("another entry"));
//...
If you wish to use the array as an answer on a received http_request (in case below it's a http_request request), you are free to use the following snippet of code as an example:
json::value answer;
auto array = answer.array();
for (size_t i = 0; i < GenFile.GetNumberOfCurves(); i++)
{
web::json::value vehicle;
vehicle[L"smth"] = web::json::value::number(WhatEverArray[i].whatever());
array[i] = vehicle;
}
request.reply(status_codes::OK, array);
The following sample json C++ array of strings works for me.
const char * const line_items_items =
"[\
{\
\"commodity_code\": \"44121903\",\
\"description\": \"Miscellaneous goods\",\
\"upc\": \"65100004327\",\
\"quantity\": \"2\",\
\"unit_of_measurement\": \"M62\",\
\"unit_cost\": \"23.09\",\
\"discount_amount\": \"10.03\",\
\"total_amount\": \"50.03\",\
\"tax_amount\": \"10.05\",\
\"extended_amount\": \"76.04\",\
\"debit_or_credit_indicator\": \"credit\",\
\"net_or_gross_indicator\": \"net\"\
},\
{\
\"commodity_code\": \"44121809\",\
\"description\": \"Miscellaneous goods\",\
\"upc\": \"65100007654\",\
\"quantity\": \"4\",\
\"unit_of_measurement\": \"M66\",\
\"unit_cost\": \"35.09\",\
\"discount_amount\": \"5.06\",\
\"total_amount\": \"0.53\",\
\"tax_amount\": \"8.07\",\
\"extended_amount\": \"96.12\",\
\"debit_or_credit_indicator\": \"debit\",\
\"net_or_gross_indicator\": \"gross\"\
}\
]";