#include <algorithm>
#include <iostream>
#include <regex>
#include <string>
#include <vector>
namespace boris {
namespace impl{
enum class Position{
TAB = 0,
COMMA = 1,
OBJ_START = 2,
OBJ_END = 3,
ARRAY_START = 4,
ARRAY_END = 5
};
struct RegexPos{
size_t pos;
long length;
};
std::string generateSpaces( int l ){
return std::string(l*4, ' ');
}
long lowestOf( std::vector<size_t> & of ){
std::vector<size_t>::iterator result = std::min_element(std::begin(of), std::end(of));
return std::distance(std::begin(of), result);
}
void insertColonSpaces( std::string & j ){ //NOT FULLY FUNCTIONAL. IT SPACES OUT COLONS IF THEY ARE PART OF VALUE OR VARIABLE NAME
std::regex colon = std::regex(R"(\s*?\:\s*?(?=\S))");
j.assign(std::regex_replace(j, colon, " : "));
}
RegexPos findRegexFirstPosition( const std::string & json, const long & start_pos, const std::regex & rx ){
size_t at = -1;
long len = 0;
std::string ss( json.begin()+start_pos, json.end() );
std::smatch m;
std::regex_search( ss, m, rx );
if ( m.size() > 0 ) {
at = m.position(0);
len = m[0].str().size();
}
if( at < json.size() ) at += start_pos;
return {at,len};
}
}
enum class Colons{
TIGHT,
SPACED
};
std::string JSONPrettify( const std::string & json, const boris::Colons spacing=boris::Colons::TIGHT ){
using namespace boris::impl;
std::string pretty = json;
const std::regex var = std::regex(R"((\".+?\"[^\,]*?((\".*?\")|(\d*?))(?=\n*?\s*?(\,|\{|\}|\[|\])))|(\d+?)|(\".*?\"))");
long it = 0;
int depth = 0;
while( it < pretty.size() ){
RegexPos pos_tab = findRegexFirstPosition( pretty,it, var );
auto pos_comma = pretty.find( ",", it );
auto pos_obj_start = pretty.find( "{", it );
auto pos_obj_end = pretty.find( "}", it );
auto pos_array_start = pretty.find( "[", it );
auto pos_array_end = pretty.find( "]", it );
long old_it = it;
Position work_with;
{
std::vector<size_t> _temp = { pos_tab.pos, pos_comma, pos_obj_start, pos_obj_end,pos_array_start,pos_array_end };
auto at = lowestOf(_temp);
if(_temp[at] > pretty.size()) break;
work_with = static_cast<Position>(at);
}
switch( work_with ){
case(Position::TAB):{
std::string insert = generateSpaces(depth);
pretty.insert( pos_tab.pos, insert );
it = pos_tab.pos+insert.size()+pos_tab.length;
break;
}
case(Position::COMMA):{
std::string insert = "\n";
pretty.insert( pos_comma+1, insert );
it = pos_comma+1;
break;
}
case(Position::OBJ_START):{
std::string insert = "\n";
pretty.insert( pos_obj_start+1, insert );
it = pos_obj_start+insert.size();
depth+=1;
if(pos_obj_start-1 > pretty.size()) continue;
if(pretty.at(pos_obj_start-1) != ':'){
std::string extra = generateSpaces( depth-1 );
pretty.insert( pos_obj_start, extra );
it+=extra.size();
}
break;
}
case(Position::OBJ_END):{
std::string insert = "\n"+generateSpaces( depth-1 );
pretty.insert( pos_obj_end, insert );
it = pos_obj_end+insert.size()+1;
depth-=1;
break;
}
case(Position::ARRAY_START):{
std::string insert = "\n";
pretty.insert( pos_array_start+1,insert );
it=pos_array_start+insert.size();
depth+=1;
break;
}
case(Position::ARRAY_END):{
std::string insert = "\n"+generateSpaces( depth-1 );
pretty.insert( pos_array_end,insert );
it=pos_array_end+insert.size()+1;
depth-=1;
break;
}
default:{
break;
}
};
if(it == old_it)
break;
}
if(spacing == Colons::SPACED)
insertColonSpaces(pretty);
return pretty;
}
};
int main() {
std::cout << boris::JSONPrettify("{\"name\":\"John[]\",\"lastname\":\"Smith\",\"co,ol\":1,\"c\":[1,2,3,4,{\"a\":1},\"b\",\"d,ed\"],\"e\":{\"zz\":1},\"com,\":\"aza:\",\"{e\":[\"a]\",2,3,4]}") ;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8cmVnZXg+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx2ZWN0b3I+CgpuYW1lc3BhY2UgYm9yaXMgewogICAgCiAgICBuYW1lc3BhY2UgaW1wbHsKICAgICAgICBlbnVtIGNsYXNzIFBvc2l0aW9uewogICAgICAgICAgICBUQUIgPSAwLAogICAgICAgICAgICBDT01NQSA9IDEsCiAgICAgICAgICAgIE9CSl9TVEFSVCA9IDIsCiAgICAgICAgICAgIE9CSl9FTkQgPSAzLAogICAgICAgICAgICBBUlJBWV9TVEFSVCA9IDQsCiAgICAgICAgICAgIEFSUkFZX0VORCA9IDUKICAgICAgICB9OwogICAgICAgIHN0cnVjdCBSZWdleFBvc3sKICAgICAgICAgICAgc2l6ZV90IHBvczsKICAgICAgICAgICAgbG9uZyBsZW5ndGg7CiAgICAgICAgfTsKICAgICAgICAgICAgCiAgICAgICAgc3RkOjpzdHJpbmcgZ2VuZXJhdGVTcGFjZXMoIGludCBsICl7CiAgICAgICAgICAgIHJldHVybiBzdGQ6OnN0cmluZyhsKjQsICcgJyk7CiAgICAgICAgfQogICAgICAgIGxvbmcgbG93ZXN0T2YoIHN0ZDo6dmVjdG9yPHNpemVfdD4gJiBvZiApewogICAgICAgICAgICBzdGQ6OnZlY3RvcjxzaXplX3Q+OjppdGVyYXRvciByZXN1bHQgPSBzdGQ6Om1pbl9lbGVtZW50KHN0ZDo6YmVnaW4ob2YpLCBzdGQ6OmVuZChvZikpOwogICAgICAgICAgICByZXR1cm4gc3RkOjpkaXN0YW5jZShzdGQ6OmJlZ2luKG9mKSwgcmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgdm9pZCBpbnNlcnRDb2xvblNwYWNlcyggc3RkOjpzdHJpbmcgJiBqICl7IC8vTk9UIEZVTExZIEZVTkNUSU9OQUwuIElUIFNQQUNFUyBPVVQgQ09MT05TIElGIFRIRVkgQVJFIFBBUlQgT0YgVkFMVUUgT1IgVkFSSUFCTEUgTkFNRQogICAgICAgICAgICBzdGQ6OnJlZ2V4IGNvbG9uID0gc3RkOjpyZWdleChSIihccyo/XDpccyo/KD89XFMpKSIpOwogICAgICAgICAgICBqLmFzc2lnbihzdGQ6OnJlZ2V4X3JlcGxhY2UoaiwgY29sb24sICIgOiAiKSk7CiAgICAgICAgfQogICAgICAgIFJlZ2V4UG9zIGZpbmRSZWdleEZpcnN0UG9zaXRpb24oIGNvbnN0IHN0ZDo6c3RyaW5nICYganNvbiwgY29uc3QgbG9uZyAmIHN0YXJ0X3BvcywgY29uc3Qgc3RkOjpyZWdleCAmIHJ4ICl7CiAgICAgICAgICAgIHNpemVfdCBhdCA9IC0xOwogICAgICAgICAgICBsb25nIGxlbiA9IDA7CiAgICAgICAgICAgIAogICAgICAgICAgICBzdGQ6OnN0cmluZyBzcygganNvbi5iZWdpbigpK3N0YXJ0X3BvcywganNvbi5lbmQoKSApOwogICAgICAgICAgICBzdGQ6OnNtYXRjaCBtOwogICAgICAgICAgICAKICAgICAgICAgICAgc3RkOjpyZWdleF9zZWFyY2goIHNzLCBtLCByeCApOwogICAgICAgICAgICAKICAgICAgICAgICAgaWYgKCBtLnNpemUoKSA+IDAgKSB7CiAgICAgICAgICAgICAgICBhdCA9IG0ucG9zaXRpb24oMCk7CiAgICAgICAgICAgICAgICBsZW4gPSBtWzBdLnN0cigpLnNpemUoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiggYXQgPCBqc29uLnNpemUoKSApIGF0ICs9IHN0YXJ0X3BvczsKICAgICAgICAgICAgcmV0dXJuIHthdCxsZW59OwogICAgICAgIH0KICAgIH0KICAgIAogICAgZW51bSBjbGFzcyBDb2xvbnN7CiAgICAgICAgVElHSFQsCiAgICAgICAgU1BBQ0VECiAgICB9OwogICAgCiAgICBzdGQ6OnN0cmluZyBKU09OUHJldHRpZnkoIGNvbnN0IHN0ZDo6c3RyaW5nICYganNvbiwgY29uc3QgYm9yaXM6OkNvbG9ucyBzcGFjaW5nPWJvcmlzOjpDb2xvbnM6OlRJR0hUICl7CiAgICAgICAgCiAgICAgICAgdXNpbmcgbmFtZXNwYWNlIGJvcmlzOjppbXBsOwogICAgICAgIAogICAgICAgIHN0ZDo6c3RyaW5nIHByZXR0eSAgICAgID0ganNvbjsKICAgICAgICBjb25zdCBzdGQ6OnJlZ2V4IHZhciAgICA9IHN0ZDo6cmVnZXgoUiIoKFwiLis/XCJbXlwsXSo/KChcIi4qP1wiKXwoXGQqPykpKD89XG4qP1xzKj8oXCx8XHt8XH18XFt8XF0pKSl8KFxkKz8pfChcIi4qP1wiKSkiKTsKICAgICAgICAKICAgICAgICBsb25nIGl0ICAgICAgICAgICAgICAgICA9IDA7CiAgICAgICAgaW50IGRlcHRoICAgICAgICAgICAgICAgPSAwOwogICAgICAgIAogICAgICAgIHdoaWxlKCBpdCA8IHByZXR0eS5zaXplKCkgKXsKICAgICAgICAgICAgCiAgICAgICAgICAgIFJlZ2V4UG9zIHBvc190YWIgICAgICAgID0gZmluZFJlZ2V4Rmlyc3RQb3NpdGlvbiggcHJldHR5LGl0LCB2YXIgKTsKICAgICAgICAgICAgYXV0byBwb3NfY29tbWEgICAgICAgICAgPSBwcmV0dHkuZmluZCggIiwiLCBpdCApOwogICAgICAgICAgICBhdXRvIHBvc19vYmpfc3RhcnQgICAgICA9IHByZXR0eS5maW5kKCAieyIsIGl0ICk7CiAgICAgICAgICAgIGF1dG8gcG9zX29ial9lbmQgICAgICAgID0gcHJldHR5LmZpbmQoICJ9IiwgaXQgKTsKICAgICAgICAgICAgYXV0byBwb3NfYXJyYXlfc3RhcnQgICAgPSBwcmV0dHkuZmluZCggIlsiLCBpdCApOwogICAgICAgICAgICBhdXRvIHBvc19hcnJheV9lbmQgICAgICA9IHByZXR0eS5maW5kKCAiXSIsIGl0ICk7CiAgICAgICAgICAgIAogICAgICAgICAgICBsb25nIG9sZF9pdCAgICAgICAgICAgICA9IGl0OwogICAgICAgICAgICAKICAgICAgICAgICAgUG9zaXRpb24gd29ya193aXRoOwogICAgICAgICAgICAKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc3RkOjp2ZWN0b3I8c2l6ZV90PiBfdGVtcCA9IHsgcG9zX3RhYi5wb3MsIHBvc19jb21tYSwgcG9zX29ial9zdGFydCwgcG9zX29ial9lbmQscG9zX2FycmF5X3N0YXJ0LHBvc19hcnJheV9lbmQgfTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgYXV0byBhdCA9IGxvd2VzdE9mKF90ZW1wKTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAKICAgICAgICAgICAgICAgIGlmKF90ZW1wW2F0XSA+IHByZXR0eS5zaXplKCkpICAgYnJlYWs7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgd29ya193aXRoID0gc3RhdGljX2Nhc3Q8UG9zaXRpb24+KGF0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICAKICAgICAgICAgICAgc3dpdGNoKCB3b3JrX3dpdGggKXsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGNhc2UoUG9zaXRpb246OlRBQik6ewogICAgICAgICAgICAgICAgICAgIHN0ZDo6c3RyaW5nIGluc2VydCA9IGdlbmVyYXRlU3BhY2VzKGRlcHRoKTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBwcmV0dHkuaW5zZXJ0KCBwb3NfdGFiLnBvcywgaW5zZXJ0ICk7CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgaXQgPSBwb3NfdGFiLnBvcytpbnNlcnQuc2l6ZSgpK3Bvc190YWIubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgY2FzZShQb3NpdGlvbjo6Q09NTUEpOnsKICAgICAgICAgICAgICAgICAgICBzdGQ6OnN0cmluZyBpbnNlcnQgPSAiXG4iOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIHByZXR0eS5pbnNlcnQoIHBvc19jb21tYSsxLCBpbnNlcnQgKTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBpdCA9IHBvc19jb21tYSsxOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgY2FzZShQb3NpdGlvbjo6T0JKX1NUQVJUKTp7CiAgICAgICAgICAgICAgICAgICAgc3RkOjpzdHJpbmcgaW5zZXJ0ID0gIlxuIjsKICAgICAgICAgICAgICAgICAgICBwcmV0dHkuaW5zZXJ0KCBwb3Nfb2JqX3N0YXJ0KzEsIGluc2VydCApOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGl0ID0gcG9zX29ial9zdGFydCtpbnNlcnQuc2l6ZSgpOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGRlcHRoKz0xOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGlmKHBvc19vYmpfc3RhcnQtMSA+IHByZXR0eS5zaXplKCkpIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGlmKHByZXR0eS5hdChwb3Nfb2JqX3N0YXJ0LTEpICE9ICc6Jyl7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZDo6c3RyaW5nIGV4dHJhID0gZ2VuZXJhdGVTcGFjZXMoIGRlcHRoLTEgKTsKICAgICAgICAgICAgICAgICAgICAgICAgcHJldHR5Lmluc2VydCggcG9zX29ial9zdGFydCwgZXh0cmEgKTsKICAgICAgICAgICAgICAgICAgICAgICAgaXQrPWV4dHJhLnNpemUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBjYXNlKFBvc2l0aW9uOjpPQkpfRU5EKTp7CiAgICAgICAgICAgICAgICAgICAgc3RkOjpzdHJpbmcgaW5zZXJ0ID0gIlxuIitnZW5lcmF0ZVNwYWNlcyggZGVwdGgtMSApOwogICAgICAgICAgICAgICAgICAgIHByZXR0eS5pbnNlcnQoIHBvc19vYmpfZW5kLCBpbnNlcnQgKTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBpdCA9IHBvc19vYmpfZW5kK2luc2VydC5zaXplKCkrMTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBkZXB0aC09MTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGNhc2UoUG9zaXRpb246OkFSUkFZX1NUQVJUKTp7CiAgICAgICAgICAgICAgICAgICAgc3RkOjpzdHJpbmcgaW5zZXJ0ID0gIlxuIjsKICAgICAgICAgICAgICAgICAgICBwcmV0dHkuaW5zZXJ0KCBwb3NfYXJyYXlfc3RhcnQrMSxpbnNlcnQgKTsKICAgICAgICAgICAgICAgICAgICBpdD1wb3NfYXJyYXlfc3RhcnQraW5zZXJ0LnNpemUoKTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBkZXB0aCs9MTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGNhc2UoUG9zaXRpb246OkFSUkFZX0VORCk6ewogICAgICAgICAgICAgICAgICAgIHN0ZDo6c3RyaW5nIGluc2VydCA9ICJcbiIrZ2VuZXJhdGVTcGFjZXMoIGRlcHRoLTEgKTsKICAgICAgICAgICAgICAgICAgICBwcmV0dHkuaW5zZXJ0KCBwb3NfYXJyYXlfZW5kLGluc2VydCApOwogICAgICAgICAgICAgICAgICAgIGl0PXBvc19hcnJheV9lbmQraW5zZXJ0LnNpemUoKSsxOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGRlcHRoLT0xOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgZGVmYXVsdDp7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIAogICAgICAgICAgICBpZihpdCA9PSBvbGRfaXQpCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgaWYoc3BhY2luZyA9PSBDb2xvbnM6OlNQQUNFRCkKICAgICAgICAgICAgaW5zZXJ0Q29sb25TcGFjZXMocHJldHR5KTsKICAgICAgICAKICAgICAgICByZXR1cm4gcHJldHR5OwogICAgfQp9OwoKaW50IG1haW4oKSB7CglzdGQ6OmNvdXQgPDwgYm9yaXM6OkpTT05QcmV0dGlmeSgie1wibmFtZVwiOlwiSm9obltdXCIsXCJsYXN0bmFtZVwiOlwiU21pdGhcIixcImNvLG9sXCI6MSxcImNcIjpbMSwyLDMsNCx7XCJhXCI6MX0sXCJiXCIsXCJkLGVkXCJdLFwiZVwiOntcInp6XCI6MX0sXCJjb20sXCI6XCJhemE6XCIsXCJ7ZVwiOltcImFdXCIsMiwzLDRdfSIpCTsKfQ==