c++ How to serialize class to json and parse the json file? - c++

I have an xObject Class which basically is a trivial "Person" Class and I want to be able to serialize the whole class to a .json file, and then read that file in order to be able to extract the variables from the file and link those variables to the name of the class.
So for example:
xObject Class Code:
class xObject{
string name;
string lastname;
int age;
public:
string getName(){
return name;
}
string getLastname(){
return lastname;
}
int getAge(){
return age;
}
}
And then I create an object with some attributes on it.
int main(){
xObject homer;
homer.name = "Homer";
homer.lastname = "Simpson";
homer.age = 30;
//SERIALIZATION OF HOMER.
homer.serialExport("File.json")
return 0;
}
So now, my File.json should look like this:
{"homer" :
{"name" : "Homer"
"lastname" : "Simpson"
"age" : 30
}
}
and then, I want to be able to read from the file to extract data from it with something like this:
int main(){
xObject bart;
bart.name = "Bart";
//ACTUAL USE OF THE .JSON FILE HERE
myFile = ("File.json");
bart.lastname = Deserializer(myFile).getLastname(); //It is supossed to assign "Simpson"
//to the lastname reading from the serialized
//homer class file described above.
bart.age = Deserializer(myFile).getAge() - 20; //Sets homer's age minus 20 years.
return 0;
}
So, how can I do that on c++? (Libraries implementation accepted)
And how could I retrieve the class name that has been serialized?
For example Deserialize(myFile).getClassName() should return "homer"
I've done something similar in java with XML serialization, and it was pretty straight forward, but it seems that in C++ this is not very easy to do, and I'm relatively new to C++.

In c++ there is not introspection/reflection, so you can't automatically serialize a class without explicitly write your member variables in your stream. For the same reason, you can't retrieved the class name that have been serialized.
So the solution is to write a function in your class that serializes the member variables you want.
Of course you will not reinvent the wheel to format your file in json. You can use: https://github.com/open-source-parsers/jsoncpp.
For instance you can write:
Json::Value root;
root["homer"]["name"]="Homer";
root["homer"]["lastname"]="Simpson";
//etc
ofstream file;
file.open("File.json");
file << root;
file.close();
However, for the read, you can do as you wanted:
Json::Value root2;
ifstream file2;
file2.open("File.json");
file2 >> root2;
file2.close();
xObject homer;
homer.lastname = root2["homer"]["lastname"].toStyledString();
//etc
Of course your attribute has to be public. Otherwise you need to add a setter function.

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);
}

How to store a List of Structure data in a Vector

I want to store list of structure data in a vector and that data comes from a request payload as:
{
"Id":"1",
"Name":"name1",
"Salary":"10000",
"Contact":"1937282912"
}
I have the following structure declaration in js folder.
struct data {
string id;
string name;
string salary;
string contact;
};
struct data1 {
vector<data> vect;
void put();
};
Then I have a method definition for the above structure:
void data1::put()
{
vector<string> details;
for(int i=0; i < vect.size(); i++) {
details.push_back(vect[i].id);
details.push_back(vect[i].name);
details.push_back(vect[i].salary);
details.push_back(vect[i].contact);
}
}
Then there is a method defined in another structure (in different folder called bk folder) which is taking all data from payload as follows:
static data dglobal;
static data1 d1global;
string getData(string &payload) {
data dlocal;
dglobal=dlocal;
data1 d1local;
d1global=d1local;
// I am making JSON object for accepting JSON data from payload then
string sid=jsonobject["id"]....;
string name=jsonobject["name"]...;
string salary=jsonobject["salary"]...;
string contact=jsonobject["contact"]..;
dglobal.id = did;
dglobal.name = name;
dglobal.salary = salary;
dglobal.contact = contact;
d1global.vect.push_back(dglobal);
d1global.put();
}
Hey guys do not focus above way of accepting JSON data because everything okay with that I just want to store all data which coming from request payload.Each time when I hit URL from rest client there is always erase previous data and store recently hit data but I want to keep all data which is already store and currently Storing data,how can I do this?

Use writer/reader for multiple fields

The following is my constructor for a Student object. I will be using a list of student. I need to store the list so even if the program is turned off, I can still access all the contents. The only way I could think of was to use reader/writer and a text file.
1) Is there a more efficient way to store this information?
2) If not, how can I use reader/writer to store each field?
public Student(String firstName, String lastName, String gender, String
state, String school, String lit, String wakeUp, String sleep, String
social,String contactInfo, String country, String major) {
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.state = state;
this.school = school;
this.lit = lit;
this.wakeUp = wakeUp;
this.sleep = sleep;
this.social = social;
this.contactInfo = contactInfo;
this.country = country;
this.major = major;
}
The possibilities are really project specific and subjective.
Some possibilities include:
CSV file which makes it easy for exporting to other programs and parsing data
Online server which allows access from any computer that has the
program and an internet connection
Text file which works for local devices that won't require many
additions
It really just depends on how you want to implement it and what method suits your needs best.
To use reader/writer to store your fields, you could use the accessor methods of each variable to store them line by line in your text file. Below is some sample code to get you started on writing to the file:
PrintWriter outputStream = null;
try {
outputStream = new PrintWriter(new FileOutputStream(FILE_LOCATION));
}
catch (FileNotFoundException ex) {
JOptionPane optionPane = new JOptionPane("Unable to write to file\n " + FILE_LOCATION, JOptionPane.ERROR_MESSAGE);
JDialog dialog = optionPane.createDialog("Error!");
dialog.setAlwaysOnTop(true);
dialog.setVisible(true);
System.exit(0);
}
Iterator<YOUR_OBJECT> i = this.List.iterator();
YOUR_OBJECT temp = null;
while (i.hasNext()) {
temp = i.next();
if (temp instanceof YOUR_OBJECT) {
outputStream.println(temp.getAttribute());
}
}
outputStream.close();

File I/O with Windows Forms

I need to create a program with Windows forms. I made a bit of code in c++...and Windows forms in c++/cli at the same time. Now I'm trying to adapt the c++ code from the forms, but I'm having some problems with the file, it's completely different from c++.
I have 2 forms. The first is for registration (it should register every student in a file). The second is for modifying students data with a given surname for example.
In registration.cpp I have created a list of objects but when I write I use streamwriter, but I guess there isnt any relationship with my list.
So my problems are:
How can I WRITE my data list into a file?
How can I MODIFY that data?
Now I post some code, but it's in italian :D as I am from italy (sorry for my mistakes.)
//.cpp of the registration
class studente
{
private:
string cognome;
string nome;
public:
studente(){
cognome="";
nome="";
};
~studente(){};
void set(string str1,string str2){
cognome=str1;
nome=str2;
}
class primo_anno:public studente
{
private:
int voto_diploma;
public:
primo_anno(){
cognome="";
nome="";
voto_diploma='0';
};
~primo_anno(){};
void set(string str1,string str2, int mark){ voto_diploma=mark; };
void stampa(){//I KNOW ITS NOT USEFUL HERE..BUT IN C++ I USED THAT
f<<"\ncognome: "<<cognome<<"\n";
f<<"nome: "<<nome<<"\n";
f<<"voto: "<<voto_diploma<<"\n";
};
};
list<primo_anno> l1;//DECLARE MY STL LIST
{//WHEN I CLICK ON MY REGISTER BUTTON THE PROGRAM RUN THIS
int mark;
primo_anno *s;
s=new primo_anno;
char* str1=(char*)(Marshal::StringToHGlobalAnsi(textBox1->Text)).ToPointer();
char* str2=(char*)(Marshal::StringToHGlobalAnsi(textBox2->Text)).ToPointer();
mark = Convert::ToInt16(textBox35->Text);
s->set(str1,str2,mark);
l1.push_back(*s);
list<primo_anno>::iterator it;
//I HAVE FOUND THIS METHOD BUT ITS NOT LINKED TO MY STL LIST.
//BY THE WAY I AM ABLE TO WRITE ON FILE WITH THIS.BUT LATER I DONT KNOW HOW TO MODIFY
//FOR EXAMPLE "DELETE THE LINE WHERE THERE IS Rossi SURNAME".HOW!!!
TextWriter ^tw = gcnew StreamWriter("primoAnno.txt", true);//true append
tw->WriteLine(textBox1->Text + "\t\t" + textBox2->Text + "\t\t" + textBox35->Text);
tw->Close();
Thank you in advance! And sorry again for my English... I'm just a student:)
Normally, you can convert a std::string into a System::String^ quite easily (it's even possible that simply using gcnew String(myPrimoAnnoObj.cognome) will give you a string with the right contents, easily written into the managed stream.
However you appear to have failed to grasp how new works for unmanaged objects: Your code allocates a primo_anno structure dynamically for no reason, before copying its value into the list and leaking the pointer. You also leak the pointers to the unmanaged strings you obtained from the Marshal class.
Are you sure you should be using unmanaged objects? It would be much easier to have everything in a managed System::Collections::Generic::List<> of managed objects...
Added: For writing everything in a file, you can try something like this:
ref class MyClass
{
public:
String^ cognome;
String^ nome;
int voto_diploma;
};
//...
List<MyClass^>^ primo = gcnew List<MyClass^>();
//...
MyClass^ myObj = gcnew MyClass();
myObj->cognome = textBox1->Text;
myObj->nome = textBox2->Text;
myObj->voto_diploma = Convert::ToInt32(textBox35->Text);
primo->Add(myObj);
//...
TextWriter ^tw = gcnew StreamWriter(L"primoAnno.txt", true);
for each(MyClass^ obj in primo)
{
//You can use any character or string as separator,
//as long as it's not supposed to appear in the strings.
//Here, I used pipes.
tw->Write(obj->cognome);
tw->Write(L"|");
tw->Write(obj->nome);
tw->Write(L"|");
tw->WriteLine(obj->voto_diploma);
}
tw->Close();
For reading, you can use a function like this:
MyClass^ ParseMyClass(String^ line)
{
array<String^>^ splitString = line->Split(L'|');
MyClass^ myObj = gcnew MyClass();
myObj->cognome = splitString[0];
myObj->nome = splitString[1];
myObj->voto_diploma = Convert::ToInt32(splitString[2]);
return myObj;
}
And for deleting:
TextWriter^ tw = gcnew StreamWriter(L"primoAnno2.txt", true);
TextReader^ tr = gcnew StreamReader(L"primoAnno.txt");
String^ line;
while((line=tr->ReadLine()) != nullptr)
{
MyClass^ obj = ParseMyClass(line);
if(obj->cognome != L"cat")
tw->WriteLine(line);
}
tr->Close();
tw->Close();
File::Delete(L"primoAnno.txt");
File::Move(L"primoAnno2.txt", L"primoAnno.txt");
It may not be the exact code, but it's overall what should work.
Note: If you want your separator to be spaces, and there can be spaces in the strings, things will get a lot more complicated.
I have tried to use a generic list..(thanks MSDN).in the comments below there are my dubts..
List<String^>^ primo=gcnew List<String^>();
int mark;
char* str1=(char*)(Marshal::StringToHGlobalAnsi(textBox1->Text)).ToPointer();
char* str2=(char*)(Marshal::StringToHGlobalAnsi(textBox2->Text)).ToPointer();
mark = Convert::ToInt16(textBox35->Text);
//here i add TEXTBOXES to my generic list...not objects of my stl list
primo->Add(textBox1->Text);
primo->Add(textBox2->Text);
primo->Add(textBox35->Text);
TextWriter ^tw = gcnew StreamWriter("primoAnno.txt", true);
for each(String^ prim in primo){
//here i write my string one by one in column..i want them all in a line!how?
tw->WriteLine(prim);
}
//i also have tried to delete an object..but i dont like the remove..i mean i want all the strings in a line, if i find "cat" for example i want to delete the ENTIRE line..not just "cat"
if(primo->Contains("cat"))tw->WriteLine("ok");primo->Remove("cat");
for each(String^ prim in primo){
tw->WriteLine(prim);
}
tw->Close();
i make an example of my primoAnno.txt file
first time i write(and push the register button) i want this:
cat gae 5
second time i write(and push the register button again) i want this:
cat gae 5
bla bla 1
then, when i remove(if there is "cat" in a line delete that line) i want this:
bla bla 1
hope it s useful. thanks to ones who will reply

How can I create an .arff file from .txt?

Is there any simple way to do that? I'm not in Java and I'm new in Python so I would need another way(s). Thanks in advance!
Do you perhaps mean a csv file that ends in .txt? If the data inside the file looks like this:
1,434,2236,5,569,some,value,other,value
4,347,2351,1,232,different,value,than,those
Then it has comma separated values (csv) and Weka has classes and functions which convert a csv file into an arff: http://weka.wikispaces.com/Converting+CSV+to+ARFF You can use these from the command line, like this:
java weka.core.converters.CSVLoader filename.csv > filename.arff
Otherwise, #D3mon-1stVFW 's comment links to great documentation from weka about turning text files (things like blog posts or books or essays) into the arff format. http://weka.wikispaces.com/ARFF+files+from+Text+Collections and this can also be called from the command line, like this:
java weka.core.converters.TextDirectoryLoader /directory/with/your/text/files > output.arff
Missing -dir argument specifier:
java weka.core.converters.TextDirectoryLoader -dir /directory/with/your/text/files > output.arff
This solution assumes you have your data in .csv format - see kaz's solution.
One simple way to do this is in version 3.6.11 (I'm on a mac) is to open up the Explorer and then in the Preprocess tab select "Open file...", just as you would when you want to open a .arff file. Then where it asks for the File Format at the bottom of the dialog box, change it to .csv. You can now load CSV files straight into Weka. If the first line of your CSV file is a header line, these names will be used as the attribute names.
On the right-hand side of the Preprocesses tabs is a "Save..." button. You can click on that and save your data as a .arff file.
This is a bit long-winded to explain, but takes only a few moments to perform and is very intuitive.
package WekaDemo;
public class Txt2Arff {
static ArrayList inList=new ArrayList();
static String colNames[];
static String colTypes[];
static String indata[][];
static ArrayList clsList=new ArrayList();
static ArrayList disCls=new ArrayList();
static String res="";
public String genTrain()
{File fe=new File("input2.txt");
FileInputStream fis=new FileInputStream(fe);
byte bt[]=new byte[fis.available()];
fis.read(bt);
fis.close();
String st=new String(bt);
String s1[]=st.trim().split("\n");
String col[]=s1[0].trim().split("\t");
colNames=col;
colTypes=s1[1].trim().split("\t");
for(int i=2;i<s1.length;i++)
{
inList.add(s1[i]);
}
ArrayList at1=new ArrayList();
for(int i=0;i<inList.size();i++)
{
String g1=inList.get(i).toString();
if(!g1.contains("?"))
{
at1.add(g1);
res=res+g1+"\n";
}
}
indata=new String[at1.size()][colNames.length-1]; // remove cls
for(int i=0;i<at1.size();i++)
{
String s2[]=at1.get(i).toString().trim().split("\t");
for(int j=0;j<s2.length-1;j++)
{
indata[i][j]=s2[j].trim();
}
if(!disCls.contains(s2[s2.length-1].trim()))
disCls.add(s2[s2.length-1].trim());
clsList.add(s2[s2.length-1]);
}
String ar="#relation tra\n";
try
{
for(int i=0;i<colNames.length-1;i++) // all columName which you have split
//and store in Colname
{
//where yor attitude in nominal or you can say character value
if(colTypes[i].equals("con"))
ar=ar+"#attribute "+colNames[i].trim().replace(" ","_")+" real\n";
else
{
ArrayList at1=new ArrayList();
for(int j=0;j<indata.length;j++) //your all numeric data
{
if(!at1.contains(indata[j][i].trim()))
at1.add(indata[j][i].trim());
}
String sg1="{";
for(int j=0;j<at1.size();j++)
{
sg1=sg1+at1.get(j).toString().trim()+",";
}
sg1=sg1.substring(0,sg1.lastIndexOf(","));
sg1=sg1+"}";
ar=ar+"#attribute "+colNames[i].trim().replace(" ", "_")+" "+sg1+"\n";
}
}
//end of attribute
// now adding a class Attribute
ArrayList dis=new ArrayList();
String c1="";
for(int i=0;i<clsList.size();i++)
{
String g=clsList.get(i).toString().trim();
if(!dis.contains(g))
{
dis.add(g);
c1=c1+g+",";
}
}
c1=c1.substring(0, c1.lastIndexOf(","));
ar=ar+"#attribute class {"+c1+"}\n"; //attribute name
//adding class attribute is done
//now data
ar=ar+"#data\n";
for(int i=0;i<indata.length;i++)
{
String g1="";
for(int j=0;j<indata[0].length;j++)
{
g1=g1+indata[i][j]+",";
}
g1=g1+clsList.get(i);
ar=ar+g1+"\n";
}
}
catch(Exception e)
{
e.printStackTrace();
}
return ar;
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Txt2Arff T2A=new Txt2Arff();
String ar1=T2A.genTrain();
File fe1=new File("tr.arff");
FileOutputStream fos1=new FileOutputStream(fe1);
fos1.write(ar1.getBytes());
fos1.close();
}}