How to create a json object with hierarchical object and values? - c++

How to create a hierarchical JSON object and value structure using Casablanca/cpprestsdk JSON library?
I referred to the following links. But I could not figure out placing the JSON object in another JSON object
https://github.com/Microsoft/cpprestsdk/wiki/JSON
https://microsoft.github.io/cpprestsdk/namespaceweb_1_1json.html
JSON Object:
{
"employee" :
{
"name" : "vinkris",
"age" : "30"
}
}
{
struct employee emp;
string object = U("{") + U("employee:") + U("{") ;
object += U("name:") + emp.name + U(",") ;
object += U("age:") + std::to_string(emp.age) + U("}") ;
json::value = json::value::string(object)
}
Is there any to simplify how the JSON body can be constructed?
For example:
{
JsonObject object();
JsonSubObjects subObject();
subObjects.add("name", "vinkris");
subObjects.add("age", "30");
object.add("employee", subObject)
}
I am very new to both c++ and Casablanca library. Wondering if this is possible?
It would be great to get some pointers on how to build something like this.

this
json::value obj = json::value::object();
json::value employee = json::value::object();
employee[U("name")] = json::value::string(U("vinkris"));
employee[U("age")] = json::value::number(30);
obj[U("employee")] = employee;
turns to this:
{"employee":{"age":30,"name":"vinkris"}}

Related

Flutter convert List<List<dynamic>>

I have a Flutter app in which I make an http request, which brings me json data. Afer formatting it with a package I get a list of lists of dynamic type. Here´s what it looks like:
[[2016-04-01, 85.5254], [2016-05-01, 89.1118], [2016-06-01, 91.8528], [2016-07-01, 93.7328], [2016-08-01, 93.9221], [2016-09-01, 95.0014], [2016-10-01, 97.2428], [2016-11-01, 98.8166]]
So I created a class named IpcData, which recieves a String and a double.
class IpcData {
final String date;
final double value;
IpcData(this.date, this.value);
}
So we could guess that an IpcData instance would look like the following:
IpcData(2016-08-01, 93.9221)
I can´t figure out how, but I´d like to have a method that using the information from the List<List<dynamic>> to return a List<IpcData>, that would looke like:
[IpcData(2016-08-01, 93.9221), IpcData(2016-08-01, 93.9221), IpcData(2016-08-01, 93.9221),]
You can use .map function on the original list to construct the new one. Something like this.
class IpcData {
final String date;
final double value;
IpcData(this.date, this.value);
#override
String toString() {
return '$date -> $value';
}
}
void main() {
List<List<dynamic>> initList = [
['2016-04-01', 85.5254], ['2016-05-01', 89.1118], ['2016-06-01', 91.8528],
['2016-07-01', 93.7328], ['2016-08-01', 93.9221], ['2016-09-01', 95.0014],
['2016-10-01', 97.2428], ['2016-11-01', 98.8166], ['2016-12-01', 99.8166]
];
List<IpcData> ipcList = initList.map((e) => IpcData(e[0], e[1])).toList();
print(ipcList);
}

C++ REST (Casablanca) - Failure while reading JSON

I was trying my hands with C++ REST APIs
I wrote to json using below way.
json::value resp;
std::vector<Portfolio> portfolio;
// Populate portfolio
this->PortfolioList(usrStr, pwdStr, portfolio);
std::vector<Portfolio>::iterator it;
for (it = portfolio.begin(); it != portfolio.end(); it++)
{
char costBuff[40]; _itoa_s(it->GetTotalCost(), costBuff, 10);
char qtyBuff[40]; _itoa_s(it->GetQuantity(), qtyBuff, 10);
json::value portfolioEntry;
portfolioEntry[U("username")] = json::value::string(utility::conversions::to_string_t(it->GetUserName()));
portfolioEntry[U("stockCode")] = json::value::string(utility::conversions::to_string_t(it->GetStockCode()));
portfolioEntry[U("quantity")] = json::value::string(utility::conversions::to_string_t(qtyBuff));
portfolioEntry[U("totalcost")] = json::value::string(utility::conversions::to_string_t(costBuff));
resp[utility::conversions::to_string_t(it->GetStockCode())] = portfolioEntry;
}
For this I got output as below
{
"11002":{"quantity":11002,"totalcost":"272","username":"arunavk"},
"11003":{"quantity":11003,"totalcost":"18700","username":"arunavk"},
"11004":{"quantity":11004,"totalcost":"760","username":"arunavk"},
"11005":{"quantity":11005,"totalcost":"32","username":"arunavk"}
}
Now, on the receiving end, I tried to read it as below
for (int i = 0; i < size; i++)
{
table->elementAt(i, 0)->addWidget(new Wt::WText(this->response[i][0].as_string()));
table->elementAt(i, 1)->addWidget(new Wt::WText(this->response[i][1].as_string()));
table->elementAt(i, 2)->addWidget(new Wt::WText(this->response[i][2].as_string()));
table->elementAt(i, 3)->addWidget(new Wt::WText(this->response[i][3].as_string()));
}
But it fails. What am I missing ?
Pardon me, I am new to this REST and Casablanca and JSON
From JSON point of view the following
{
"11002":{"quantity":11002,"totalcost":"272","username":"arunavk"},
"11003":{"quantity":11003,"totalcost":"18700","username":"arunavk"},
"11004":{"quantity":11004,"totalcost":"760","username":"arunavk"},
"11005":{"quantity":11005,"totalcost":"32","username":"arunavk"}
}
is java script object with properties "11002", ... "11005", is not array. So if you want to get value of property you have to use property name:
this->response["11002"]["quantity"]
because when you use integer index the json::value::operator [] supposes that you want to access the array element. Here is details https://microsoft.github.io/cpprestsdk/classweb_1_1json_1_1value.html#a56c751a1c22d14b85b7f41a724100e22
UPDATED
If you do not know properties of the recieved object, you can call the value::as_object method (https://microsoft.github.io/cpprestsdk/classweb_1_1json_1_1value.html#a732030bdee11c2f054299a0fb148df0e) to get JSON object and after that you can use specilized interface to iterate through the fields with begin and end iterators: https://microsoft.github.io/cpprestsdk/classweb_1_1json_1_1object.html#details

json serialize c++

I have this C++ code, and am having trouble json serializing it.
string uInput;
string const& retInput;
while(!std::cin.eof()) {
getline(cin, uInput);
JSONExample source; //JSON enabled class from jsonserialize.h
source.text = uInput;
//create JSON from producer
std::string json = JSON::producer<JSONExample>::convert(source); //string -> returns {"JSONExample":{"text":"hi"}}
//then create new instance from a consumer...
JSONExample sink = JSON::consumer<JSONExample>::convert(json);
//retInput = serialize(sink);
// Json::FastWriter fastWriter;
// retInput = fastWriter.write(uInput);
retInput = static_cast<string const&>(uInput);
pubnub::futres fr_2 = pb_2.publish(chan, retInput);
cout << "user input as json which should be published is " << retInput<< std::endl;
while(!cin.eof()) {
getline(cin, uInput);
newInput = "\"\\\"";
newInput += uInput;
newInput += "\\\"\"";
Instead of typing in the message like "\"hi\"", this code takes "hi" and does it.
If the change you described made the "Invalid JSON" disappear, then a "more correct" solution would be, AFAICT, to change the publish() line to:
pubnub::futres fr_2 = pb_2.publish(chan, json);
Because json already has JSON serialized data. Of course, if that JSON is what you want to publish.

How to read a JSON file containing multiple root elements?

If I had a file whose contents looked like:
{"one": 1}
{"two": 2}
I could simply parse each separate line as a separate JSON object (using JsonCpp). But what if the structure of the file was less convenient like this:
{
"one":1
}
{
"two":2
}
No one has mentioned arrays:
[
{"one": 1},
{"two": 2}
]
Is valid JSON and might do what the OP wants.
Neither example in your question is a valid JSON object; a JSON object may only have one root. You have to split the file into two objects, then parse them.
You can use http://jsonlint.com to see if a given string is valid JSON or not.
So I recommend either changing what ever is dumping multiple JSON objects into a single file to do it in separate files, or to put each object as a value in one JSON root object.
If you don't have control over whatever is creating these, then you're stuck parsing the file yourself to pick out the different root objects.
Here's a valid way of encoding those data in a JSON object:
{
"one": 1,
"two": 2
}
If your really need separate objects, you can do it like this:
{
"one":
{
"number": 1
},
"two":
{
"number": 2
}
}
Rob Kennedy is right. Calling it a second time would extract the next object, and so on.Most of the json lib can not help you to do all in a single root. Unless you are using more high end framework in QT.
You can also use this custom function to parse multiple root elements even if you have complex objects.
static getParsedJson(jsonString) {
const parsedJsonArr = [];
let tempStr = '';
let isObjStartFound = false;
for (let i = 0; i < jsonString.length; i += 1) {
if (isObjStartFound) {
tempStr += jsonString[i];
if (jsonString[i] === '}') {
try {
const obj = JSON.parse(tempStr);
parsedJsonArr.push(obj);
tempStr = '';
isObjStartFound = false;
} catch (err) {
// console.log("not a valid JSON object");
}
}
}
if (!isObjStartFound && jsonString[i] === '{') {
tempStr += jsonString[i];
isObjStartFound = true;
}
}
return parsedJsonArr;
}

how to generate fake data using moq for unit test?

I need to generate some data to unit test my repositories. i was using a loop to generate a list of objects, see codes below. I learned moq is a great mocking library, Can I use moq to generate that and how do I do it?
public IQueryable<Category> GetCategories()
{
IList<Category> result = new List<Category>();
for (int i = 1; i <= 2; i++)
{
Category c = new Category();
c.ID = i;
c.Name = "Parent" + i.ToString();
c.ParentID = 0;
for (int x = i*10; x < i*10+5; x++)
{
Category sub = new Category();
sub.ID = x;
sub.Name = "Sub" + x.ToString();
sub.ParentID = i;
result.Add(sub);
}
result.Add(c);
}
return result.AsQueryable<Category>();
}
You can't use Moq to create the data, but you can use AutoFixture:
public IQueryable<Category> GetCategories()
{
return fixture.CreateMany<Category>().AsQueryable();
}
However, this will not give you a hierarchical tree. It will return objects like this:
Object 1:
- ID = 0
- ParentID = 1
Object 2:
- ID = 2
- ParentID = 3
etc.
If you really need to have this hierarchical data, you would need to use the following code:
public IQueryable<Category> GetCategories()
{
var result = new List<Category>();
// Create the parents
var parents = fixture.Build<Category>()
.Without(x => x.ParentID)
.CreateMany());
result.AddRange(parents);
result.AddRange(parents.SelectMany(p => fixture.Build<Category>()
.With(x => x.ParentID, p.ID)
.CreateMany()));
return result.AsQueryable();
}
This will add multiple parents with multiple subs for each parent.
You can use faker.net to generate fake data. for Example: for dotnet core project its Faker.NETCore.
dotnet add package Faker.NETCore -v 1.0.1
and then use the same in your code in the following manner:-
public void GetStudent()
{
var st = new Student()
st.FirstName = Faker.Name.First();
st.LastName = Faker.Name.Last();
st.Mobile = Faker.Phone.Number();
}