function Json() { }

Json.encode_number = function(value) {
  var str = new String(value);
  return str.valueOf(); // ensure we get a string literal
}

Json.encode_bool = function(value) {
  return (value) ? "true" : "false";
}

Json.encode_character = function(value) {
  if (!value) return '';

  var poor_chars = ['"',   '\\',   '/',   "\b",  "\f",  "\n",  "\r",  "\t"];
  var good_chars = ['\\"', '\\\\', '\\/', '\\b', '\\f', '\\n', '\\r', '\\t'];
  if (poor_chars.contains(value)) { return good_chars[poor_chars.indexOf(value)]; }
  if (value.charCodeAt(0) > 255) { 
    value = value.charCodeAt(0);
    value = new String(value);
    return '\\u' + new String(Math.toBase(value, 16)).pad(4, "0", String.STR_PAD_LEFT); 
  }
  return value;
}

Json.encode_string = function(value) {
  return '"' + value.toArray().map(Json.encode_character).join("") + '"';
}

Json.encode_object = function(value) {
  var values = new Array();
  for (var k in value) {
    values.push(Json.encode(k) + ":" + Json.encode(value[k]));
  }

  return "{" + values.join(",") + "}";
}

Json.encode_array = function(value) {
  return "[" + value.map(Json.encode).join(",") + "]";
}

Json.encode = function(value) {
  if (typeof value == "boolean")
    return Json.encode_bool(value);
  if (typeof value == "number")
    return Json.encode_number(value);
  if (typeof value == "string")
    return Json.encode_string(value);
  if (value instanceof Array)
    return Json.encode_array(value);
  if (value instanceof Object)
    return Json.encode_object(value);

  return "null";
}

