Pagini recente » Cod sursa (job #924808) | Cod sursa (job #1232061) | Cod sursa (job #1810810) | Cod sursa (job #3245573) | Cod sursa (job #1357377)
/**
* Converts JSON to CSV.
*/
#include <algorithm>
#include <fstream>
#include <iostream>
#include <unordered_map>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef pair<string, string> json_field;
typedef vector<json_field> json_entry;
/**
* Checks if a character is digit.
*
* @param ch
* @return `true` if the given character is digit, `false` otherwise.
*/
bool isdigit(char ch)
{
return ((ch >= '0') && (ch <= '9'));
}
/**
* Basic JSON parser working with an array containing multiple dictionaries.
*/
class JsonParser {
public:
/**
* Parses the JSON data from the stream.
*
* @param s Source stream.
*/
bool parse(istream &in, ostream &out);
/**
* Dumps the data in CSV format.
*
* @param s Destination stream.
*/
void dump(ostream &out);
/**
* Dumps an entry to the output.
* I hope this is going to save me some time.
*
* @see `dump`
* @param s Destination stream.
* @param entry Source entry.
*/
void dumpEntry(ostream &out, json_entry &entry);
private:
enum State {
/** Initial state. */
STATE_NONE,
/** In array (expects entry). */
STATE_IN_ARRAY,
/** In dictionary (expects field). */
STATE_IN_DICT,
/** In dictionary key (expects string). */
STATE_IN_DICT_KEY,
/** In a dictionary, expects a value. */
STATE_IN_DICT_VALUE_TMP,
/** In dictionary value (expects string). */
STATE_IN_DICT_VALUE_STR,
/** In dictionary value (expects integer). */
STATE_IN_DICT_VALUE_INT,
};
/** Stores entries. */
vector<json_entry> data;
};
int main()
{
ifstream fin("convertor.in");
ofstream fout("convertor.out");
JsonParser jp;
jp.parse(fin, fout);
//jp.dump(fout);
return 0;
}
bool JsonParser::parse(istream &in, ostream &out)
{
json_entry entry;
json_field field;
char ch;
stack<State> state;
state.push(STATE_NONE);
while (in >> noskipws >> ch) {
if (state.top() == STATE_NONE) {
if (ch == '[') {
data.clear();
state.push(STATE_IN_ARRAY);
}
} else if (state.top() == STATE_IN_ARRAY) {
if (ch == ']') {
state.pop();
} else if (ch == '{') {
entry.clear();
state.push(STATE_IN_DICT);
} else if (ch == ',') {
// TODO: New entry is coming.
}
} else if (state.top() == STATE_IN_DICT) {
if (ch == '}') {
//data.push_back(entry);
dumpEntry(out, entry);
state.pop();
} else if (ch == '"') {
field.first.clear();
field.second.clear();
state.push(STATE_IN_DICT_KEY);
} else if (ch == ':') {
state.push(STATE_IN_DICT_VALUE_TMP);
} else if (ch == ',') {
// TODO: New entry is coming.
}
} else if (state.top() == STATE_IN_DICT_KEY) {
if (ch == '"') {
// TODO: Escaping.
state.pop();
} else {
field.first += ch;
}
} else if (state.top() == STATE_IN_DICT_VALUE_TMP) {
if (ch == '"') {
state.pop();
state.push(STATE_IN_DICT_VALUE_STR);
} else if (isdigit(ch)) {
state.pop();
state.push(STATE_IN_DICT_VALUE_INT);
field.second += ch;
}
} else if (state.top() == STATE_IN_DICT_VALUE_STR) {
if (ch == '"') {
entry.push_back(field);
state.pop();
} else {
field.second += ch;
}
} else if (state.top() == STATE_IN_DICT_VALUE_INT) {
if (isdigit(ch)) {
field.second += ch;
} else if (ch == ',') {
entry.push_back(field);
state.pop();
} else if (ch == '}') {
entry.push_back(field);
//data.push_back(entry);
dumpEntry(out, entry);
state.pop();
state.pop(); // popping STATE_IN_DICT too
}
}
}
return true; // TODO: Return false on failure.
}
void JsonParser::dump(ostream &out)
{
// Builds the header.
vector<string> header;
for (json_entry::iterator field = data.begin()->begin(); field != data.begin()->end(); ++field) {
if (find(header.begin(), header.end(), field->first) == header.end()) {
header.push_back(field->first);
}
}
/*
for (vector<json_entry>::iterator entry = data.begin(); entry != data.end(); ++entry) {
for (json_entry::iterator field = entry->begin(); field != entry->end(); ++field) {
if (find(header.begin(), header.end(), field->first) == header.end()) {
header.push_back(field->first);
}
}
}
*/
// Prints the header.
for (vector<string>::iterator it = header.begin(); it != header.end(); ++it) {
out << *it << ",";
}
out << "\n";
// Prints data.
for (vector<json_entry>::iterator entry = data.begin(); entry != data.end(); ++entry) {
// TODO: Print fields in order (@see `header`).
for (json_entry::iterator field = entry->begin(); field != entry->end(); ++field) {
out << field->second << ",";
}
out << "\n";
}
}
void JsonParser::dumpEntry(ostream &out, json_entry &entry)
{
static bool isFirst = true;
if (isFirst) {
// Builds the header.
vector<string> header;
for (json_entry::iterator field = entry.begin(); field != entry.end(); ++field) {
if (find(header.begin(), header.end(), field->first) == header.end()) {
header.push_back(field->first);
}
}
// Prints the header.
for (vector<string>::iterator it = header.begin(); it != header.end(); ++it) {
out << *it << ",";
}
out << "\n";
isFirst = false;
}
// Prints data.
for (json_entry::iterator field = entry.begin(); field != entry.end(); ++field) {
out << field->second << ",";
}
out << "\n";
}