fork download
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <regex>
  4. #include <string>
  5. #include <vector>
  6.  
  7. namespace boris {
  8.  
  9. namespace impl{
  10. enum class Position{
  11. TAB = 0,
  12. COMMA = 1,
  13. OBJ_START = 2,
  14. OBJ_END = 3,
  15. ARRAY_START = 4,
  16. ARRAY_END = 5
  17. };
  18. struct RegexPos{
  19. size_t pos;
  20. long length;
  21. };
  22.  
  23. std::string generateSpaces( int l ){
  24. return std::string(l*4, ' ');
  25. }
  26. long lowestOf( std::vector<size_t> & of ){
  27. std::vector<size_t>::iterator result = std::min_element(std::begin(of), std::end(of));
  28. return std::distance(std::begin(of), result);
  29. }
  30.  
  31. void insertColonSpaces( std::string & j ){ //NOT FULLY FUNCTIONAL. IT SPACES OUT COLONS IF THEY ARE PART OF VALUE OR VARIABLE NAME
  32. std::regex colon = std::regex(R"(\s*?\:\s*?(?=\S))");
  33. j.assign(std::regex_replace(j, colon, " : "));
  34. }
  35. RegexPos findRegexFirstPosition( const std::string & json, const long & start_pos, const std::regex & rx ){
  36. size_t at = -1;
  37. long len = 0;
  38.  
  39. std::string ss( json.begin()+start_pos, json.end() );
  40. std::smatch m;
  41.  
  42. std::regex_search( ss, m, rx );
  43.  
  44. if ( m.size() > 0 ) {
  45. at = m.position(0);
  46. len = m[0].str().size();
  47. }
  48. if( at < json.size() ) at += start_pos;
  49. return {at,len};
  50. }
  51. }
  52.  
  53. enum class Colons{
  54. TIGHT,
  55. SPACED
  56. };
  57.  
  58. std::string JSONPrettify( const std::string & json, const boris::Colons spacing=boris::Colons::TIGHT ){
  59.  
  60. using namespace boris::impl;
  61.  
  62. std::string pretty = json;
  63. const std::regex var = std::regex(R"((\".+?\"[^\,]*?((\".*?\")|(\d*?))(?=\n*?\s*?(\,|\{|\}|\[|\])))|(\d+?)|(\".*?\"))");
  64.  
  65. long it = 0;
  66. int depth = 0;
  67.  
  68. while( it < pretty.size() ){
  69.  
  70. RegexPos pos_tab = findRegexFirstPosition( pretty,it, var );
  71. auto pos_comma = pretty.find( ",", it );
  72. auto pos_obj_start = pretty.find( "{", it );
  73. auto pos_obj_end = pretty.find( "}", it );
  74. auto pos_array_start = pretty.find( "[", it );
  75. auto pos_array_end = pretty.find( "]", it );
  76.  
  77. long old_it = it;
  78.  
  79. Position work_with;
  80.  
  81. {
  82. std::vector<size_t> _temp = { pos_tab.pos, pos_comma, pos_obj_start, pos_obj_end,pos_array_start,pos_array_end };
  83.  
  84. auto at = lowestOf(_temp);
  85.  
  86.  
  87. if(_temp[at] > pretty.size()) break;
  88.  
  89.  
  90. work_with = static_cast<Position>(at);
  91. }
  92.  
  93. switch( work_with ){
  94.  
  95. case(Position::TAB):{
  96. std::string insert = generateSpaces(depth);
  97.  
  98. pretty.insert( pos_tab.pos, insert );
  99.  
  100. it = pos_tab.pos+insert.size()+pos_tab.length;
  101. break;
  102. }
  103.  
  104. case(Position::COMMA):{
  105. std::string insert = "\n";
  106.  
  107. pretty.insert( pos_comma+1, insert );
  108.  
  109. it = pos_comma+1;
  110. break;
  111. }
  112.  
  113. case(Position::OBJ_START):{
  114. std::string insert = "\n";
  115. pretty.insert( pos_obj_start+1, insert );
  116.  
  117. it = pos_obj_start+insert.size();
  118.  
  119. depth+=1;
  120.  
  121. if(pos_obj_start-1 > pretty.size()) continue;
  122.  
  123. if(pretty.at(pos_obj_start-1) != ':'){
  124. std::string extra = generateSpaces( depth-1 );
  125. pretty.insert( pos_obj_start, extra );
  126. it+=extra.size();
  127. }
  128.  
  129. break;
  130. }
  131.  
  132. case(Position::OBJ_END):{
  133. std::string insert = "\n"+generateSpaces( depth-1 );
  134. pretty.insert( pos_obj_end, insert );
  135.  
  136. it = pos_obj_end+insert.size()+1;
  137.  
  138. depth-=1;
  139. break;
  140. }
  141.  
  142. case(Position::ARRAY_START):{
  143. std::string insert = "\n";
  144. pretty.insert( pos_array_start+1,insert );
  145. it=pos_array_start+insert.size();
  146.  
  147. depth+=1;
  148. break;
  149. }
  150.  
  151. case(Position::ARRAY_END):{
  152. std::string insert = "\n"+generateSpaces( depth-1 );
  153. pretty.insert( pos_array_end,insert );
  154. it=pos_array_end+insert.size()+1;
  155.  
  156. depth-=1;
  157. break;
  158. }
  159.  
  160. default:{
  161. break;
  162. }
  163. };
  164.  
  165. if(it == old_it)
  166. break;
  167. }
  168.  
  169. if(spacing == Colons::SPACED)
  170. insertColonSpaces(pretty);
  171.  
  172. return pretty;
  173. }
  174. };
  175.  
  176. int main() {
  177. 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]}") ;
  178. }
Success #stdin #stdout 0s 3548KB
stdin
Standard input is empty
stdout
{
    "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
    ]
}