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 />'+' '.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(/&/,'&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}
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ön verschachtelt..."},"tippt einfach json-zeugs in dem grossen Feld.","Die Anzeige aktualisiert sich sofort...","Die Formatierungen sind als <style> gespeichert. Ihr könnt sie so beliebig ändern.",{"Zahlen":1,"sind":[1,4,55.67],"auch":"schön"}]</textarea>
<div id="ausgabe"></div>
</body>
</html>