Pagini recente » Cod sursa (job #1579084) | Cod sursa (job #106735) | Cod sursa (job #590927) | Cod sursa (job #846868) | Cod sursa (job #1358538)
/**
* Converts JSON to CSV.
*/
#include <algorithm>
#include <fstream>
#include <iostream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef pair<string, string> json_field;
typedef vector<json_field> json_dictionary;
/**
* Checks if a character is digit.
*
* @param ch
* @return `true` if the given character is digit, `false` otherwise.
*/
inline bool isdigit(char ch)
{
return ((ch >= '0') && (ch <= '9'));
}
/**
* Basic JSON object.
*/
class Json {
public:
/**
* Adds a dictionary in the `data` vector.
*
* @param dict
* @param out Actually, no dictionary is being added to the `data` vector.
* The dictionary is printed to the output stream as soon as
* possible. I did this to save some time. Please, forgive me.
*/
void addDictionary(json_dictionary &dict, ostream &out);
/**
* Prints the JSON file in CSV format to the output stream.
*
* @param out
*/
void dump(ostream &out);
private:
/**
* Stores dictionaries.
*/
vector<json_dictionary> data;
};
/**
* Basic JSON parser.
*/
class JsonParser {
public:
/**
* Parses the JSON data from the stream.
*
* @param s Source stream.
* @return
*/
Json* parse(istream &in, ostream &out);
private:
/**
* List of possible states of the parser.
* They are usually stored in a stack.
*/
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 dictionary value (expects string). */
STATE_IN_DICT_VALUE_STR,
/** In dictionary value (expects integer). */
STATE_IN_DICT_VALUE_INT,
/** Final state. */
STATE_END,
};
};
int main()
{
ifstream fin("convertor.in");
ofstream fout("convertor.out");
JsonParser jp;
jp.parse(fin, fout);
return 0;
}
Json* JsonParser::parse(istream &in, ostream &out)
{
Json *json = new Json;
json_dictionary dict;
char ch, key[128], value[1024];
int keyLen = 0, valueLen = 0;
State state = STATE_NONE;
while (state != STATE_END) {
in >> ch;
if (state == STATE_NONE) {
if (ch == '[') {
// Array found.
state = STATE_IN_ARRAY;
}
} else if (state == STATE_IN_ARRAY) {
if (ch == ']') {
// Array ended.
state = STATE_END;
} else if (ch == '{') {
// Dictionary found. Resetting everything.
dict.clear();
state = STATE_IN_DICT;
}
} else if (state == STATE_IN_DICT) {
if (ch == '"') {
// Key found. Resetting everything.
keyLen = valueLen = 0;
// Reading key.
while (in >> noskipws >> key[keyLen]) {
if (key[keyLen] == '"') {
break;
}
++keyLen;
}
// Finding the delimiter between key and value.
while (in >> ch) {
if (ch == ':') {
break;
}
}
// Determining value type.
while (in >> ch) {
if (ch == '"') {
state = STATE_IN_DICT_VALUE_STR;
break;
} else if (isdigit(ch)) {
state = STATE_IN_DICT_VALUE_INT;
break;
}
}
// Reading value.
if (state == STATE_IN_DICT_VALUE_STR) {
while (in >> noskipws >> value[valueLen]) {
if (value[valueLen] == '"') {
break;
}
++valueLen;
}
} else if (state == STATE_IN_DICT_VALUE_INT) {
value[valueLen++] = ch;
while (in >> value[valueLen]) {
if (!isdigit(value[valueLen])) {
break;
}
++valueLen;
}
}
// Pushing the field.
key[keyLen] = value[valueLen] = 0;
dict.push_back(json_field(key, value));
// Pushing the dictionary aswell if it ended now.
if (ch == '}') {
json->addDictionary(dict, out);
state = STATE_IN_ARRAY;
} else {
state = STATE_IN_DICT;
}
} else if (ch == '}') {
// Dictionary ended.
json->addDictionary(dict, out);
state = STATE_IN_ARRAY;
}
}
}
return json; // TODO: Return `NULL` on failure.
}
void Json::addDictionary(json_dictionary &entry, ostream &out)
{
static bool isFirst = true;
if (isFirst) {
// Builds the header.
vector<string> header;
for (json_dictionary::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_dictionary::iterator field = entry.begin(); field != entry.end(); ++field) {
out << field->second << ',';
}
out << '\n';
}
void Json::dump(ostream &out)
{
// Builds the header (using only the first entry).
vector<string> header;
for (json_dictionary::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);
}
}
// Prints the header.
for (vector<string>::iterator it = header.begin(); it != header.end(); ++it) {
out << *it << ',';
}
out << '\n';
// Prints data.
for (vector<json_dictionary>::iterator entry = data.begin(); entry != data.end(); ++entry) {
// TODO: Print fields in order (@see `header`).
for (json_dictionary::iterator field = entry->begin(); field != entry->end(); ++field) {
out << field->second << ',';
}
out << '\n';
}
}