Closed DragonOsman closed 5 years ago
Okay, never mind; instead of changing the current object I could just make another one that's based on it, with one set of keys being the currency abbreviations I need. I want the currency list object to look like this:
{"rates":{"CAD":1.4741,"HKD":8.6776,"ISK":138.1,"PHP":58.008,"DKK":7.4559,"HUF":328.58,"CZK":25.769,"AUD":1.6396,"RON":4.7212,"SEK":10.7165,"IDR":15726.13,"INR":79.304,"BRL":4.5224,"RUB":72.9469,"HRK":7.394,"JPY":117.79,"THB":33.997,"CHF":1.0893,"SGD":1.536,"PLN":4.355,"BGN":1.9558,"TRY":6.3815,"CNY":7.8439,"NOK":9.9593,"NZD":1.736,"ZAR":16.8439,"USD":1.1065,"MXN":22.0041,"ILS":3.8924,"GBP":0.90453,"KRW":1341.19,"MYR":4.6362},"base":"EUR","date":"2019-08-23"}
How do I do this? I tried to do this:
json currency_list;
for (const auto& [key, value] : json::parse(res.body())["rates"].items())
{
if (key == "CAD")
{
currency_list["currencies"][key] = "Canadian dollar";
}
…
}
currency_list["currencies"]["EUR"] = "European euro";
But this only gave me an object with that last item in it (the one with key "EUR"). So how do I do this correctly? I hope someone would help me out here. Thanks.
json currency_list = json::parse(res.body());
Then you iterate over that.
Will it be possible to modify the values in currency_list
with that? Since the values in it will the conversion rates from res.body()
.
Yes, then currency_list will have the right values... If you want "res" to get updated that is a different problem.
I need a currency list where the values are the full currency names, like I said above. The res.body()
object itself has a currency abbreviation to rates mapping; I don't want that. I just want the abbreviations themselves from that object.
I tried to do this:
json currency_list{ json::parse(res.body()) };
for (auto j_iter{ currency_list["rates"].items().begin() }; j_iter != currency_list["rates"].items().end(); ++j_iter)
{
if (j_iter.key() == "CAD")
{
}
}
But I don't know how to access and modify the values from here. Please help. Is this the right way, or is there still something wrong here?
There's a "base" key with the value "EUR". I'm erasing that and want to add a new value inside the "rates" array. I want to rename that array key to "currencies" and add a new value in there "EUR: European euro".
So far I have this:
json currency_list{ json::parse(res.body()) };
for (auto j_iter{ currency_list.begin() }; j_iter != currency_list.end(); ++j_iter)
{
if (j_iter->find("base") != j_iter->end())
{
j_iter->erase(j_iter->find("base"));
}
}
for (auto j_iter{ currency_list["rates"].begin() }; j_iter != currency_list["rates"].end(); ++j_iter)
{
if (j_iter->find("CAD") != j_iter->end())
{
*(j_iter->find("CAD")) = "Canadian dollar";
}
if (j_iter->find("USD") != j_iter->end())
{
*(j_iter->find("USD")) = "US dollar";
}
}
Is it possible to rename keys? And then how do I insert the key-value pair I want to insert?
The JSON object I want to make would look like this:
{"currences":{"CAD":"Canadian dollar","HKD":"Hong Kong dollar","ISK":"Icelandic krona","PHP":"Philippine peso","DKK":"Danish krone","HUF":"Hungarian forint","CZK":"Czech koruna","AUD":"Australian dollar","RON":"Romanian leu","SEK":"Swedish krona","IDR":"Indonesian rupiah","INR":"Indian rupee","BRL":"Brazilian real","RUB":"Russian rouble","HRK":"Croatian kuna","JPY":"Japanese yen","THB":"Thai baht","CHF":"Swiss franc","SGD":"Singapore dollar","PLN":"Polish zloty","BGN":"Bulgarian lev","TRY":"Tukish lira","CNY":"Chinese yuan renminbi","NOK":"Norwegian krone","NZD":"New Zealand dollar","ZAR":"South African rand","USD":"United States dollar","MXN":"Mexican peso","ILS":"Israeli shekel","GBP":"Pound sterling","KRW":"South Korean won","MYR":"Malaysian ringgit", "EUR":"European euro"}}
and the res.body()
object looks like this:
{"rates":{"CAD":1.4741,"HKD":8.6776,"ISK":138.1,"PHP":58.008,"DKK":7.4559,"HUF":328.58,"CZK":25.769,"AUD":1.6396,"RON":4.7212,"SEK":10.7165,"IDR":15726.13,"INR":79.304,"BRL":4.5224,"RUB":72.9469,"HRK":7.394,"JPY":117.79,"THB":33.997,"CHF":1.0893,"SGD":1.536,"PLN":4.355,"BGN":1.9558,"TRY":6.3815,"CNY":7.8439,"NOK":9.9593,"NZD":1.736,"ZAR":16.8439,"USD":1.1065,"MXN":22.0041,"ILS":3.8924,"GBP":0.90453,"KRW":1341.19,"MYR":4.6362},"base":"EUR","date":"2019-08-23"}
I hope that makes it clearer what I want to do.
I made a file like this to read into a std::map<std::string, std::tuple<std::string, std::string>>
from:
currencies
CAD:Canadian dollar
HKD:Hong Kong dollar
ISK:Icelandic krona
PHP:Philippine peso
DKK:Danish krone
HUF:Hungarian forint
CZK:Czech koruna
AUD:Australian dollar
RON:Romanian leu
SEK:Swedish krona
IDR:Indonesian rupiah
INR:Indian rupee
BRL:Brazilian real
RUB:Russian rouble
HRK:Croatian kuna
JPY:Japanese yen
THB:Thai baht
CHF:Swiss franc
SGD:Singapore dollar
PLN:Polish zloty
BGN:Bulgarian lev
TRY:Tukish lira
CNY:Chinese yuan renminbi
NOK:Norwegian krone
NZD:New Zealand dollar
ZAR:South African rand
USD:United States dollar
MXN:Mexican peso
ILS:Israeli shekel
GBP:Pound sterling
KRW:South Korean won
MYR:Malaysian ringgit
EUR:European euro
and then I read into the map and initialized a nlohmann::json
object from it like this:
std::string nested_map_str{}, abbreviation{}, currency_name{};
std::ifstream ifs{"./currency_list_json.txt"};
std::map<std::string, std::tuple<std::string, std::string>> currency_map;
/*Attempting to create JSON object that looks like the following:
{"currences":{"CAD":"Canadian dollar","HKD":"Hong Kong dollar","ISK":"Icelandic krona",
"PHP":"Philippine peso","DKK":"Danish krone","HUF":"Hungarian forint","CZK":"Czech koruna",
"AUD":"Australian dollar","RON":"Romanian leu","SEK":"Swedish krona","IDR":"Indonesian rupiah",
"INR":"Indian rupee","BRL":"Brazilian real","RUB":"Russian rouble","HRK":"Croatian kuna",
"JPY":"Japanese yen","THB":"Thai baht","CHF":"Swiss franc","SGD":"Singapore dollar",
"PLN":"Polish zloty","BGN":"Bulgarian lev","TRY":"Tukish lira","CNY":"Chinese yuan renminbi",
"NOK":"Norwegian krone","NZD":"New Zealand dollar","ZAR":"South African rand","USD":"United States dollar",
"MXN":"Mexican peso","ILS":"Israeli shekel","GBP":"Pound sterling","KRW":"South Korean won","MYR":"Malaysian ringgit",
"EUR":"European euro"}}*/
while (ifs)
{
ifs >> nested_map_str;
std::getline(ifs, abbreviation, ':');
std::getline(ifs, currency_name);
currency_map.insert_or_assign(nested_map_str, std::make_tuple(abbreviation, currency_name));
}
json currency_list{ currency_map };
Then I tried to print it out, but I got this output for the JSON object:
{"{currencies:{CAD:Canadian":[" dollar,HKD","Hong Kong dollar,ISK:Icelandic krona,PHP:Philippine peso,DKK:Danish krone,HUF:Hungarian forint,CZK:Czech koruna,AUD:Australian dollar,RON:Romanian leu,SEK:Swedish krona,IDR:Indonesian rupiah,INR:Indian rupee,BRL:Brazilian real,RUB:Russian rouble,HRK:Croatian kuna,JPY:Japanese yen,THB:Thai baht,CHF:Swiss franc,SGD:Singapore dollar,PLN:Polish zloty,BGN:Bulgarian lev,TRY:Tukish lira,CNY:Chinese yuan renminbi,NOK:Norwegian krone,NZD:New Zealand dollar,ZAR:South African rand,USD:United States dollar,MXN:Mexican peso,ILS:Israeli shekel,GBP:Pound sterling,KRW:South Korean won,MYR:Malaysian ringgit, EUR:European euro}}"]}
How can I make this work correctly? Any help is appreciated. Thanks.
wouldn't something like this work? (can't test if this code compiles at the moment)
nlohmann::json currency_rates = nlohmann::json::parse(res.body());
nlohmann::json currency_list = nlohmann::json::object{};
for(const auto& [key, value] : currency_rates["rates"]) {
currency_list[key] = abbrevToFullName(key);
}
But i wonder if you really need to build the conversion object dynamically; surely, it would be easier (and in my opinion cleaner) to read a file that contains the data you want, as it looks like the data is static/never changes.
I had to try to find a new currency API because the one I was using most recently (before the one with the list I showed just now) seems to be a deprecated service now. At first I found one that gets its data from the European Central Bank, but it doesn't support all of world countries. I found another one that's free and supports all currencies, but this one doesn't have a way to query it for a list of currencies either. I decided to try and make a JSON object representing a list of currencies on my own. This is the function I did it with:
// Function to create and return currency list as a nlohmann::json object
json get_currency_list()
{
return { "currencies",
{ { "AED", "United Arab Emirates Dirham" }, { "AFN", "Afghan Afghani" },
{ "ALL", "Albanian Lek" }, { "AMD", "Armenian Dram" }, { "ANG", "Netherlands Antillean Guilder" },
{ "AOA", "Angolan Kwanza" }, { "ARS", "Argentine Peso" }, { "AUD", "Australian Dollar" },
{ "AWG", "Aruban Florin" }, { "AZN", "Azerbaijani Manat" }, { "BAM", "Bosnia & Herzegovina Convertible Mark" },
{ "BBD", "Barbadian Dollar" }, { "BDT", "Bangladeshi Taka" }, { "BGN", "Bulgarian Lev" },
{ "BHD", "Bahraini Dinar" }, { "BIF", "Burundian Franc" }, { "BMD", "Bermudian Dollar" },
{ "BND", "Brunei Dollar" }, { "BOB", "Bolivian Boliviano" }, { "BRL", "Brazilian Real" },
{ "BSD", "Bahamian Dollar" }, { "BTN", "Bhutanese Ngultrum" }, { "BWP", "Botswana Pula" },
{ "BYN", "Belarus Ruble" }, { "BZD", "Belize Dollar" }, { "CAD", "Canadian Dollar" },
{ "CDF", "Congolese Franc" }, { "CHF", "Swiss Franc" }, { "CLP", "Chilean Peso" },
{ "CNY", "Chinese Yuan" }, { "COP", "Colombian Peso" }, { "CRC", "Costa Rican Colon" },
{ "CUC", "Cuban Convertible Peso" }, { "CVE", "Cape Verdean Escudo" }, { "CZK", "Czech Republic Koruna" },
{ "DJF", "Djiboutian Franc" }, { "DKK", "Danish Krone" }, { "DOP", "Dominican Peso" },
{ "DZD", "Algerian Dinar" }, { "EGP", "Egyptian Pound" }, { "ERN", "Eritrean Nakfa" },
{ "ETB", "Ethiopian Birr" }, { "EUR", "Euro" }, { "FJD", "Fiji Dollar" },
{ "GBP", "British Pound Sterling" }, { "GEL", "Georgian Lari" }, { "GHS", "Ghanaian Cedi" },
{ "GIP", "Gibraltar Pound" }, { "GMD", "Gambian Dalasi" }, { "GNF", "Guinea Franc" },
{ "GTQ", "Guatemalan Quetzal" }, { "GYD", "Guyanaese Dollar" }, { "HKD", "Hong Kong Dollar" },
{ "HNL", "Honduran Lempira" }, { "HRK", "Croatian Kuna" }, { "HTG", "Haiti Gourde" },
{ "HUF", "Hungarian Forint" }, { "IDR", "Indonesian Rupiah" }, { "ILS", "Israeli Shekel" },
{ "INR", "Indian Rupee" }, { "IQD", "Iraqi Dinar" }, { "IRR", "Iranian Rial" },
{ "ISK", "Icelandic Krona" }, { "JMD", "Jamaican Dollar" }, { "JOD", "Jordanian Dinar" },
{ "JPY", "Japanese Yen" }, { "KES", "Kenyan Shilling" }, { "KGS", "Kyrgystani Som" },
{ "KHR", "Cambodian Riel" }, { "KMF", "Comorian Franc" }, { "KPW", "North Korean Won" },
{ "KRW", "South Korean Won" }, { "KWD", "Kuwaiti Dinar" }, { "KYD", "Cayman Islands Dollar" },
{ "KZT", "Kazakhstan Tenge" }, { "LAK", "Laotian Kip" }, { "LBP", "Lebanese Pound" },
{ "LKR", "Sri Lankan Rupee" }, { "LRD", "Liberian Dollar" }, { "LSL", "Lesotho Loti" },
{ "LYD", "Libyan Dinar" }, { "MAD", "Moroccan Dirham" }, { "MDL", "Moldovan Leu" },
{ "MGA", "Malagasy Ariary" }, { "MKD", "Macedonian Denar" }, { "MMK", "Myanma Kyat" },
{ "MNT", "Mongolian Tugrik" }, { "MOP", "Macau Pataca" }, { "MRO", "Mauritanian Ouguiya" },
{ "MUR", "Mauritian Rupee" }, { "MVR", "Maldivian Rufiyaa" }, { "MWK", "Malawi Kwacha" },
{ "MXN", "Mexican Peso" }, { "MYR", "Malaysian Ringgit" }, { "MZN", "Mozambican Metical" },
{ "NAD", "Namibian Dollar" }, { "NGN", "Nigerian Naira" }, { "NIO", "Nicaragua Cordoba" },
{ "NOK", "Norwegian Krone" }, { "NPR", "Nepalese Rupee" }, { "NZD", "New Zealand Dollar" },
{ "OMR", "Omani Rial" }, { "PAB", "Panamanian Balboa" }, { "PEN", "Peruvian Nuevo Sol" },
{ "PGK", "Papua New Guinean Kina" }, { "PHP", "Philippine Peso" }, { "PKR", "Pakistani Rupee" },
{ "PLN", "Polish Zloty" }, { "PYG", "Paraguayan Guarani" }, { "QAR", "Qatari Riyal" },
{ "RON", "Romanian Leu" }, { "RSD", "Serbian Dinar" }, { "RUB", "Russian Ruble" },
{ "RWF", "Rwanda Franc" }, { "SAR", "Saudi Riyal" }, { "SBD", "Solomon Islands Dollar" },
{ "SCR", "Seychellois Rupee" }, { "SDG", "Sudanese Pound" }, { "SEK", "Swedish Krona" },
{ "SGD", "Singapore Dollar" }, { "SHP", "Saint Helena Pound" }, { "SLL", "Sierra Leonean Leone" },
{ "SOS", "Somali Shilling" }, { "SRD", "Surinamese Dollar" }, { "SSP", "South Sudanese Pound" },
{ "STD", "Sao Tome and Principe Dobra" }, { "SYP", "Syrian Pound" }, { "SZL", "Swazi Lilangeni" },
{ "THB", "Thai Baht" }, { "TJS", "Tajikistan Somoni" }, { "TMT", "Turkmenistani Manat" },
{ "TND", "Tunisian Dinar" }, { "TOP", "Tonga Paanga" }, { "TRY", "Turkish Lira" },
{ "TTD", "Trinidad and Tobago Dollar" }, { "TWD", "New Taiwan Dollar" }, { "TZS", "Tanzanian Shilling" },
{ "UAH", "Ukrainian Hryvnia" }, { "UGX", "Ugandan Shilling" }, { "USD", "United States Dollar" },
{ "UYU", "Uruguayan Peso" }, { "UZS", "Uzbekistan Som" }, { "VEF", "Venezuelan Bolivar" },
{ "VND", "Vietnamese Dong" }, { "VUV", "Vanuatu Vatu" }, { "WST", "Samoan Tala" },
{ "XAF", "Central African CFA franc" }, { "XCD", "East Caribbean Dollar" }, { "XOF", "West African CFA franc" },
{ "XPF", "CFP Franc" }, { "YER", "Yemeni Rial" }, { "ZAR", "South African Rand" },
{ "ZMW", "Zambian Kwacha" } }
};
}
I tried to use the return value of this function here to send the currency list to the JS code on my app's front end:
if (req.target() == "/?q=currency_list")
{
try
{
json currency_list{ get_currency_list() };
http::response<http::string_body> res{
std::piecewise_construct,
std::make_tuple(std::move(std::string(currency_list))),
std::make_tuple(http::status::ok, req.version()) };
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
res.set(http::field::content_type, "application/json");
res.content_length(res.body().size());
res.keep_alive(req.keep_alive());
return send(std::move(res));
}
catch (const json::exception& e)
{
std::cerr << "Line 503: Error: " << e.what() << std::endl;
}
}
But this gave me an error saying:
[json.exception.type_error.302] type must be string, but is array
So how do I fix this error now? Should I turn my current object into a string representation of the same object (if there's a way for it to retain the keys and values it currently has)?
I'm sorry for this. This is different from the original question now too. Should I close this thread and open a new one?
I'm late to this, so some comments:
std::map
internally. You cannot change keys (easily) in a std::map
, so it is also not easy in the library.items()
is just a nice way to access the first
and second
members of a std::map::iterator
. As the keys are constant, you cannot assign to key()
.However, you can use this trick for std::map
(from https://stackoverflow.com/a/5743682/266378):
#include "json.hpp"
#include <iostream>
using json = nlohmann::json;
int main()
{
json j;
j["CAD"] = 10;
j["EUR"] = 20;
j["USD"] = 30;
std::cout << j << std::endl;
const auto it = j.find("CAD");
if (it != j.end())
{
std::swap(j["Canadian Dollars"], *it);
j.erase(it);
}
std::cout << j << std::endl;
}
Output:
{"CAD":10,"EUR":20,"USD":30}
{"Canadian Dollars":10,"EUR":20,"USD":30}
@nlohmann Thanks. But I'd also like a reply to my most recent post if that's okay. Or maybe I really should close this issue and open a new one.
I'm talking about the post right above yours.
Yes, please open a new issue.
key:value
pairs where I want to change the values. It's a mapping of currency codes to exchange rates, and I want to change it to one of currency codes to full currency names.