Skip to main content

I'd write it as a recursive descent parser since this is quite simple:

http://en.wikipedia.org/wiki/Recursive_descent_parser

Actually I already did this a couple of years back, when I wanted to create something that simply formats and highlights JSON a bit. If you can understand it, then you can modify it to your needs:

<html>
    <head>
        <style type="text/css">
.str
{
    color: green;
}

.obj
{
    font-weight: bold;
}

.num
{
    color: red;
}
        </style>
        <script language="javascript" type="text/javascript">

String.prototype.repeat = function(n) {
  result = '';
  for (var i = 0; i < n; i++) result += this;
  return result;
}

function jsonFormater() {
  this.reset = function() {
    this.txt = '';
    this.pos = 0;
    this.result = '';
    this.indent = 0;
    this.classes = Array();
  };

  this.undoindent = function() {
    this.indent -= 4;
    this.nline();
  };

  this.doindent = function() {
    this.indent += 4;
    this.nline();
  };

  this.nline = function() {
    this.result += '<br />' + '&nbsp;'.repeat(this.indent);
  };

  this.chClass = function(neu) {
    if (this.classes.length > 0) this.result += '</span>';
    this.result += '<span class="' + neu + '">';
    this.classes.push(neu);
  };

  this.endClass = function() {
    this.classes.pop();
    this.result += '</span>';
    if (this.classes.length > 0) this.result += '<span class="' + this.classes[this.classes.length - 1] + '">';
  };

  this.formatJson = function(txt) {
    this.txt = txt;
    this.pos = 0;
    this.result = '';
    while (this.pos < this.txt.length) {
      if (this.txt[this.pos] == '{') this.parseObj();
      else if (this.txt[this.pos] =='[') this.parseArray();
      this.pos++;
    }

    return this.result;
  }

  this.parseObj = function(ende) {
    if (typeof ende =='undefined') var ende = '}';
    this.chClass('obj');

    do {
      if ((this.txt[this.pos] == '{') || (this.txt[this.pos] == '[')) this.nline();
      this.result += this.txt[this.pos];
      if (this.txt[this.pos] == ',') this.nline();
      if ((this.txt[this.pos] == '{') || (this.txt[this.pos] == '[')) this.doindent();
      this.pos++;
      if (this.txt[this.pos] == '{') this.parseObj();
      if (this.txt[this.pos] == '[') this.parseArray();
      if (this.txt[this.pos] == '"') this.parseString();
      if (/\d/.test(this.txt[this.pos])) this.parseNum();
      if ((this.txt[this.pos] == '}') || (this.txt[this.pos] == ']')) this.undoindent();
    } while ((this.pos < this.txt.length) && (this.txt[this.pos] != ende));

    this.result += this.txt[this.pos];
    this.pos++;
    this.endClass();
  };

  this.parseArray = function() {
    this.parseObj(']');
  };

  this.parseString = function() {
    this.chClass('str');
    do {
      this.result += this.htmlEscape(this.txt[this.pos]);
      this.pos++;
    } while ((this.pos < this.txt.length) && ((this.txt[this.pos] != '"') || (this.txt[this.pos - 1] == '\\')));

    this.result += this.htmlEscape(this.txt[this.pos]);
    this.pos++;
    this.endClass();
  };

  this.parseNum = function() {
    this.chClass('num');
    do {
      this.result += this.txt[this.pos];
      this.pos++;
    } while ((this.pos < this.txt.length) && (/[\d\.]/.test(this.txt[this.pos])));

    this.endClass();
  };

  this.htmlEscape = function(txt) {
    return txt.replace(/&/,'&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  };

  this.reset();
}

var parser = new jsonFormater();

function go(txt) {
  document.getElementById('ausgabe').innerHTML = parser.formatJson(txt);
  parser.reset();
}

        </script>
    </head>
    <body onLoad="go(document.getElementById('thetextarea').value);">
        <textarea id="thetextarea" rows="25" cols="70" onKeyUp="go(this.value);">[{"Dies":"Ist ein Beispiel...","mit":["Arrays","und","so"]},{"alles":"sch&ouml;n verschachtelt..."},"tippt einfach json-zeugs in dem grossen Feld.","Die Anzeige aktualisiert sich sofort...","Die Formatierungen sind als &lt;style&gt; gespeichert. Ihr k&ouml;nnt sie so beliebig &auml;ndern.",{"Zahlen":1,"sind":[1,4,55.67],"auch":"sch&ouml;n"}]</textarea>
        <div id="ausgabe"></div>
    </body>
</html>
yankee
  • 498
  • 3
  • 5
  • 11