JSON phasing with REST API - c++

I am trying to read 2nd levels in a JSON file with the REST API's Json fuctionallity #include <cpprest/json.h>
I need to get from the following JSON the name field:
{"desc":"","id":"57681f5dc4864c821cc73bfa","lists":[{"id":"576973346263056c88cfe845","name":"Board info"},{"id":"57681f5dc4864c821cc73bfb","name":"Misc"},{"id":"576978294972d812e4a91580","name":"thing"},{"id":"57681fdc228443c3306cc762","name":"thing2"},{"id":"5768200b1fbf41dd2c974052","name":"thing3"},{"id":"57681feb72ca90abb3afe170","name":"thingy"},{"id":"57681f5dc4864c821cc73bfc","name":"meep"},{"id":"57681f5dc4864c821cc73bfd","name":"BannedWordsPhrases"},{"id":"57681fba60fdfbf576abaece","name":"Errors"}],"name":"READER"}
(lets call this file JSON1)
I can get JSON1["lists"] but not JSON1["lists"]["name"].
here is my code:
#include "cpprest/json.h" //how I am importing stuff
...
typedef web::json::value JsonValue; //all of these are being uses
typedef web::json::value::value_type JsonValueType;
typedef std::wstring String;
typedef std::wstringstream StringStream;
using namespace utility;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace concurrency::streams;
...
int main()
{
...
web::json::value J1 = web::json::value::parse(S);
web::json::value &J2 = web::json::value::parse(S1);
output(J2);
wfstream _file("jsonFile.json");
_file >> obj;
wcout << obj[L"lists"][L"name"]; // the broken line
cout << endl;
}
all the functions and variables work and are correct, it functions with out the [L"name"] and with [L"lists"].
What am I doing wrong?

Note: my answer may be wrong, it would help if you could post the output of wcout << obj[L"lists"];. Also, I am assuming you are trying to get "name" as in "Board info" and "Mics" and not "READER". I will assume your output for wcout << obj[L"lists"]; is:
[{"id":"576973346263056c88cfe845","name":"Board info"},{"id":"57681f5dc4864c821cc73bfb","name":"Misc"},{"id":"576978294972d812e4a91580","name":"thing"},{"id":"57681fdc228443c3306cc762","name":"thing2"},{"id":"5768200b1fbf41dd2c974052","name":"thing3"},{"id":"57681feb72ca90abb3afe170","name":"thingy"},{"id":"57681f5dc4864c821cc73bfc","name":"meep"},{"id":"57681f5dc4864c821cc73bfd","name":"BannedWordsPhrases"},{"id":"57681fba60fdfbf576abaece","name":"Errors"}]
Proposed Answer: obj[L"lists"]; returns a list of 9 JSON objects in this case (listed above). You can access these JSON objects by index (0-8). For example, according to cpprestsdk, obj[L"lists"][0]; or obj[L"lists"].at(0);should return {"id":"576973346263056c88cfe845","name":"Board info"}.
From there you can get the name, for example:
obj[L"lists"][0][L"name"] should return Board info.

Related

Converting json file to json object jumbles up the order of objects

I am trying to parse a json file into a json object using nlohmann json library.
This is the json file:
{
"n":1,
"data":
{
"name":"Chrome",
"description":"Browse the internet.",
"isEnabled":true
}
}
This is my code:
#include <nlohmann/json.hpp>
#include <iostream>
#include <fstream>
using namespace std;
using json = nlohmann::json;
int main()
{
ifstream f("/Users/callum/sfucourses/cmpt373/test/example2.json");
json data = json::parse(f);
cout << data << endl;
}
If I don't do the parse and just do cout << f.rdbuf() I get correct output:
./interpret
/Users/callum/sfucourses/cmpt373/build
{
"n":1,
"data":
{
"name":"Chrome",
"description":"Browse the internet.",
"isEnabled":true
}
}
but if I do the parse and print out the json object 'data',then "n":1 and "name":"Chrome" is placed at the end instead of the beginning:
./interpret
{"data":{"description":"Browse the internet.","isEnabled":true,"name":"Chrome"},"n":1}
How do I get it to print in the correct order?
JSON is normally not ordered, but the library provides nlohmann::ordered_json that keeps the insertion order:
auto data = nlohmann::ordered_json::parse(f);
Parsing the file like above and printing it like you do produces this output:
{"n":1,"data":{"name":"Chrome","description":"Browse the internet.","isEnabled":true}}

C++ Apache Orc is not filtering data correctly

I am posting a simple c++ Apache orc file reading program which:
Read data from ORC file.
Filter data based on the given string.
Sample Code:
#include <iostream>
#include <list>
#include <memory>
#include <chrono>
// Orc specific headers.
#include <orc/Reader.hh>
#include <orc/ColumnPrinter.hh>
#include <orc/Exceptions.hh>
#include <orc/OrcFile.hh>
int main(int argc, char const *argv[])
{
auto begin = std::chrono::steady_clock::now();
orc::RowReaderOptions m_RowReaderOpts;
orc::ReaderOptions m_ReaderOpts;
std::unique_ptr<orc::Reader> m_Reader;
std::unique_ptr<orc::RowReader> m_RowReader;
auto builder = orc::SearchArgumentFactory::newBuilder();
std::string required_symbol("FILTERME");
/// THIS LINE SHOULD FILTER DATA BASED ON COLUMNS.
/// INSTEAD OF FILTERING IT TRAVERSE EACH ROW OF ORC FILE.
builder->equals("column_name", orc::PredicateDataType::STRING, orc::Literal(required_symbol.c_str(), required_symbol.size()));
std::string file_path("/orc/file/path.orc");
m_Reader = orc::createReader(orc::readFile(file_path.c_str()), m_ReaderOpts);
m_RowReader = m_Reader->createRowReader(m_RowReaderOpts);
m_RowReaderOpts.searchArgument(builder->build());
auto batch = m_RowReader->createRowBatch(5000);
try
{
std::cout << builder->build()->toString() << std::endl;
while(m_RowReader->next(*batch))
{
const auto &struct_batch = dynamic_cast<const orc::StructVectorBatch&>(*batch.get());
/** DO CALCULATIONS */
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
auto end = std::chrono::steady_clock::now();
std::cout << "Total Time taken to read ORC file: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " ms.\n";
return 0;
}
I tried searching on google for almost a week and tried to convert every possible java program into c++ to make my code works.
I tried to use the example in the STACKOVERFLOW LINK which has a similar issue but didn't work for me.
**Question:**
1. Am I wiring filtering code correctly. If yes then why it is not filtering data based on the given string.
2. Where can I find the C++ or 'relevant Java code' for row-level or strip-level filter.
Finally after trying multiple scenarios, I have resolved the above issue with ORC data filtering.
It was because of using the incorrect column number, I am not sure why there is a difference between the column id of the columns to fetch and columns to filter.
In above example I tried to filter data with column name and issue of filtering ORC with column name is still there. But unfortulately it is working fine with column number.
New Code:
#include <iostream>
#include <list>
#include <memory>
#include <chrono>
// Orc specific headers.
#include <orc/Reader.hh>
#include <orc/ColumnPrinter.hh>
#include <orc/Exceptions.hh>
#include <orc/OrcFile.hh>
int main(int argc, char const *argv[])
{
auto begin = std::chrono::steady_clock::now();
orc::RowReaderOptions m_RowReaderOpts;
orc::ReaderOptions m_ReaderOpts;
std::unique_ptr<orc::Reader> m_Reader;
std::unique_ptr<orc::RowReader> m_RowReader;
auto builder = orc::SearchArgumentFactory::newBuilder();
std::string required_symbol("FILTERME");
// <-- HERE COLUMN IDS ARE STARTING FROM 0-N. -->
std::list<uint64_t> cols = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
m_RowReaderOpts.include(cols);
int column_id = 7; // IN cols ABOVE, THIS COLUMN_ID 7 IS ACTUALLY 6. WHICH MEANS COLUMN_ID TO FILTER COLUMN IS +1 OF COLUMN ID PROVIDED IN DATA FETCH.
builder->equals(column_id, orc::PredicateDataType::STRING, orc::Literal(required_symbol.c_str(), required_symbol.size()));
std::string file_path("/orc/file/path.orc");
m_Reader = orc::createReader(orc::readFile(file_path.c_str()), m_ReaderOpts);
m_RowReader = m_Reader->createRowReader(m_RowReaderOpts);
m_RowReaderOpts.searchArgument(builder->build());
auto batch = m_RowReader->createRowBatch(5000);
try
{
std::cout << builder->build()->toString() << std::endl;
while(m_RowReader->next(*batch))
{
const auto &struct_batch = dynamic_cast<const orc::StructVectorBatch&>(*batch.get());
/** DO CALCULATIONS */
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
auto end = std::chrono::steady_clock::now();
std::cout << "Total Time taken to read ORC file: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " ms.\n";
return 0;
}
As per my understanding while resolving above issue is, column ids for fetching data starts from 0-N and for filtering it is 1-N. This is why you should provide 1, when you require to filter data at column 0.
To explain the confusion in the above answer:
In ORC, column field id is a different thing than column type id:
For files that have structs as the top-level object, field id 0 corresponds to the first struct field, field id 1 for the second struct field, and so on. See comments here: https://github.com/apache/orc/blob/v1.7.3/c++/include/orc/Reader.hh#L122-L123
Column type id is the pre-order traversal index of the type tree. As mentioned in the spec: The type tree is flattened in to a list via a pre-order traversal where each type is assigned the next id. Clearly the root of the type tree is always type id 0.
So if there are no nested types (struct/array/map) in the ORC file, we can see columnTypeId == columnFieldId + 1 on all columns except the root struct type.
The ids used in building sargs are column type ids. However, the ids used in RowReaderOptions::include(const std::list<uint64_t>& include) are column field ids. To have a consistent id mapping, I'd recommend using the include method for type ids:
RowReaderOptions::includeTypes(const std::list<uint64_t>& types);

CrerdWriteW storing credentials in Mandarin on Windows

I used the answer here to add credentials programmatically to Windows Credential Manager. The code is inspired by the code in the answer. When I run it however, the credentials in the cred manager show up in Mandarin. I am not sure what am I doing wrong. Would appreciate any pointers. TIA .
For references this is the code I have
#include <iostream>
#include "windows.h"
#include "wincred.h"
#pragma hdrstop
using namespace std;
int main()
{
const char* password = "testpass";
CREDENTIALW creds = { 0 };
creds.Type = CRED_TYPE_GENERIC;
creds.TargetName = (LPWSTR)("testaccount");
creds.CredentialBlobSize = strlen(password) + 1;
creds.CredentialBlob = (LPBYTE)password;
creds.Persist = CRED_PERSIST_LOCAL_MACHINE;
creds.UserName = (LPWSTR)("testuser");
BOOL result = CredWriteW(&creds, 0);
if (result != TRUE)
{
cout << "Some error occurred" << endl;
}
else
{
cout << "Stored the password successfully" << endl;
}
return 0;
}
To ensure there is no default language problem, I manually created a credential from within the credential manager for test.com and had no problems with it. Snapshot of the Cred Manager -
Appearantly, TargetName needs to refer to a mutable array, i.e. not a string literal. It also needs to be a wide string, or else the characters will be interpreted wrongly, in this case resulting in Chinese characters.
The solution is to define a mutable array that is initialized with a wide string, and have TargetName point to it:
WCHAR targetName [] = L"testuser";
creds.TargetName = targetName;
This way, no suspicious cast is needed to make it compile. When you want to input non-hardcoded strings (e.g. from user input or a file), you need to make sure they are correctly encoded and convert appropriately.

boost log format single attribute with logging::init_from_stream

When I set up format params in code, to format date time output I can use something like this
logging::formatter simpleFormat(expr::format("%1% %2%") %
expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%H:%M:%S") %
expr::smessage
);
But when I initialize logger with a config file, I can specify format only in attributes position notation, not their format details.
so, this line in a boost log config file
Format="[%TimeStamp%]: %Message%"
produces output:
[2015-Feb-06 09:32:27.401496]: blah blah blah
I want to reduce timestamp to something like this
[06.02.2015 09:32:27]
How can it be described in boost log config file, ot it cant be done at all?
Preamble
My answer is valid for boost 1.55 (haven't tested with latest one). And it was only tested with MSVC 2013 compiler.
Answer
Looks like you need custom formatter_factory for TimeStamp attribute to be able to specify it's format. This works for me:
#include <fstream>
#include "boost/shared_ptr.hpp"
#include "boost/log/trivial.hpp"
#include "boost/log/expressions.hpp"
#include "boost/log/utility/setup.hpp"
#include "boost/log/support/date_time.hpp"
class timestamp_formatter_factory :
public boost::log::basic_formatter_factory<char, boost::posix_time::ptime>
{
public:
formatter_type create_formatter(boost::log::attribute_name const& name, args_map const& args)
{
args_map::const_iterator it = args.find("format");
if (it != args.end())
return boost::log::expressions::stream << boost::log::expressions::format_date_time<boost::posix_time::ptime>(boost::log::expressions::attr<boost::posix_time::ptime>(name), it->second);
else
return boost::log::expressions::stream << boost::log::expressions::attr<boost::posix_time::ptime>(name);
}
};
int main()
{
// Initializing logging
boost::log::register_formatter_factory("TimeStamp", boost::make_shared<timestamp_formatter_factory>());
boost::log::add_common_attributes();
std::ifstream file("settings.ini");
boost::log::init_from_stream(file);
// Testing
BOOST_LOG_TRIVIAL(info) << "Test";
return 0;
}
And now it your settings file you can specify format argument for TimeStamp attribute. Like this:
[Sinks.ConsoleOut]
Destination=Console
AutoFlush=true
Format="[%TimeStamp(format=\"%Y.%m.%d %H:%M:%S\")%]: %Message%"
You should be able to use set_formatter as documented here
sink->set_formatter
(
expr::stream << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
);

how to get all timezone names in ICU

I am using boost::locale with ICU Backend to do time conversion between different timezones.when creating boost::local::Calendar, I can pass in a string like "America/New_York" to specify the timezone information.
but how do I get a list of all valid timezone names?
from ICU doc, it mentioned that users can use TimeZone.getAvailableIDs() method to iterate through all timezone names. but I can't even find a method called getAvailableIDs in timezone.h.
you can use TimeZone.createEnumeration() to get a list of all timezone names. it does says in the doc that using getAvailabeIDs, but this method seems not exist anymore.
I managed to implement it like this, using ICU 4.4.2:
#include <iostream>
#include <unicode/timezone.h>
#include <unicode/unistr.h>
using namespace icu;
int main()
{
StringEnumeration *timeZoneIds = TimeZone::createEnumeration();
UErrorCode status = U_ZERO_ERROR;
const UnicodeString *zoneId = timeZoneIds->snext(status);
while (zoneId != NULL && status == U_ZERO_ERROR)
{
std::string zoneIdString;
zoneId->toUTF8String(zoneIdString);
std::cout << zoneIdString << std::endl;
zoneId = timeZoneIds->snext(status);
}
delete timeZoneIds;
return 0;
}