context: #define READABLE
  
  namespace RacingGameKit.Helpers
  {
      using UnityEngine;
      using System.Collections;
      using System.Collections.Generic;
  
      /*
       * http://www.opensource.org/licenses/lgpl-2.1.php
       * JSONObject class
       * for use with Unity
       * Copyright Matt Schoen 2010
       */
      public class Nullable
      {
          //Extend this class if you want to use the syntax
          //  if(myObject)
          //to check if it is not null
          public static implicit operator bool(Nullable o)
          {
              return (object)o != null;
          }
      }
  
      public class JSONObject : Nullable
      {
          const int MAX_DEPTH = 1000;
          public enum Type { NULL, STRING, NUMBER, OBJECT, ARRAY, BOOL }
          public JSONObject parent;
          public Type type = Type.NULL;
          public ArrayList list = new ArrayList();
          public ArrayList keys = new ArrayList();
          public string str;
          public float n; 
          public bool b;
  
          public static JSONObject nullJO { get { return new JSONObject(JSONObject.Type.NULL); } }
          public static JSONObject obj { get { return new JSONObject(JSONObject.Type.OBJECT); } }
          public static JSONObject arr { get { return new JSONObject(JSONObject.Type.ARRAY); } }
  
          public JSONObject(JSONObject.Type t)
          {
              type = t;
              switch (t)
              {
                  case Type.ARRAY:
                      list = new ArrayList();
                      break;
                  case Type.OBJECT:
                      list = new ArrayList();
                      keys = new ArrayList();
                      break;
              }
          }
          public JSONObject(bool b)
          {
              type = Type.BOOL;
              this.b = b;
          }
          public JSONObject(float f)
          {
              type = Type.NUMBER;
              this.n = f;
          }
          public JSONObject(Dictionary<string, string> dic)
          {
              type = Type.OBJECT;
              foreach (KeyValuePair<string, string> kvp in dic)
              {
                  keys.Add(kvp.Key);
                  list.Add(kvp.Value);
              }
          }
          public JSONObject() { }
          public JSONObject(string str)
          {	//create a new JSONObject from a string (this will also create any children, and parse the whole string)
              //Debug.Log(str);
              if (str != null)
              {
  #if(READABLE)
                  str = str.Replace("\\n", "");
                  str = str.Replace("\\t", "");
                  str = str.Replace("\\r", "");
                  str = str.Replace("\t", "");
                  str = str.Replace("\n", "");
                  str = str.Replace("\\", "");
  #endif
                  if (str.Length > 0)
                  {
                      if (string.Compare(str, "true", true) == 0)
                      {
                          type = Type.BOOL;
                          b = true;
                      }
                      else if (string.Compare(str, "false", true) == 0)
                      {
                          type = Type.BOOL;
                          b = false;
                      }
                      else if (str == "null")
                      {
                          type = Type.NULL;
                      }
                      else if (str[0] == '"')
                      {
                          type = Type.STRING;
                          this.str = str.Substring(1, str.Length - 2);
                      }
                      else
                      {
                          try
                          {
                              n = float.Parse(str);
                              type = Type.NUMBER;
                          }
                          catch (System.FormatException)
                          {
                              int token_tmp = 0;
                              /*
                               * Checking for the following formatting (www.json.org)
                               * object - {"field1":value,"field2":value}
                               * array - [value,value,value]
                               * value - string	- "string"
                               *		 - number	- 0.0
                               *		 - bool		- true -or- false
                               *		 - null		- null
                               */
                              switch (str[0])
                              {
                                  case '{':
                                      type = Type.OBJECT;
                                      keys = new ArrayList();
                                      list = new ArrayList();
                                      break;
                                  case '[':
                                      type = JSONObject.Type.ARRAY;
                                      list = new ArrayList();
                                      break;
                                  default:
                                      type = Type.NULL;
                                      Debug.LogWarning("improper JSON formatting:" + str);
                                      return;
                              }
                              int depth = 0;
                              bool openquote = false;
                              bool inProp = false;
                              for (int i = 1; i < str.Length; i++)
                              {
                                  if (str[i] == '\\')
                                  {
                                      i++;
                                      continue;
                                  }
                                  if (str[i] == '"')
                                      openquote = !openquote;
                                  if (str[i] == '[' || str[i] == '{')
                                      depth++;
                                  if (depth == 0 && !openquote)
                                  {
                                      if (str[i] == ':' && !inProp)
                                      {
                                          inProp = true;
                                          try
                                          {
                                              keys.Add(str.Substring(token_tmp + 2, i - token_tmp - 3));
                                          }
                                          catch { Debug.Log(i + " - " + str.Length + " - " + str); }
                                          token_tmp = i;
                                      }
                                      if (str[i] == ',')
                                      {
                                          inProp = false;
                                          list.Add(new JSONObject(str.Substring(token_tmp + 1, i - token_tmp - 1)));
                                          token_tmp = i;
                                      }
                                      if (str[i] == ']' || str[i] == '}')
                                          list.Add(new JSONObject(str.Substring(token_tmp + 1, i - token_tmp - 1)));
                                  }
                                  if (str[i] == ']' || str[i] == '}')
                                      depth--;
                              }
                          }
                      }
                  }
              }
              else
              {
                  type = Type.NULL;	//If the string is missing, this is a null
              }
          }
          public void AddField(bool val) { Add(new JSONObject(val)); }
          public void AddField(float val) { Add(new JSONObject(val)); }
          public void AddField(int val) { Add(new JSONObject(val)); }
          public void Add(JSONObject obj)
          {
              if (obj)
              {		//Don't do anything if the object is null
                  if (type != JSONObject.Type.ARRAY)
                  {
                      type = JSONObject.Type.ARRAY;		//Congratulations, son, you're an ARRAY now
                      Debug.LogWarning("tried to add an object to a non-array JSONObject.  We'll do it for you, but you might be doing something wrong.");
                  }
                  list.Add(obj);
              }
          }
          public void AddField(string name, bool val) { AddField(name, new JSONObject(val)); }
          public void AddField(string name, float val) { AddField(name, new JSONObject(val)); }
          public void AddField(string name, int val) { AddField(name, new JSONObject(val)); }
          public void AddField(string name, string val)
          {
              AddField(name, new JSONObject { type = JSONObject.Type.STRING, str = val });
          }
          public void AddField(string name, JSONObject obj)
          {
              if (obj)
              {		//Don't do anything if the object is null
                  if (type != JSONObject.Type.OBJECT)
                  {
                      type = JSONObject.Type.OBJECT;		//Congratulations, son, you're an OBJECT now
                      Debug.LogWarning("tried to add a field to a non-object JSONObject.  We'll do it for you, but you might be doing something wrong.");
                  }
                  keys.Add(name);
                  list.Add(obj);
              }
          }
          public void SetField(string name, JSONObject obj)
          {
              if (HasField(name))
              {
                  list.Remove(this[name]);
                  keys.Remove(name);
              }
              AddField(name, obj);
          }
          public JSONObject GetField(string name)
          {
              if (type == JSONObject.Type.OBJECT)
                  for (int i = 0; i < keys.Count; i++)
                      if ((string)keys[i] == name)
                          return (JSONObject)list[i];
              return null;
          }
          public bool HasField(string name)
          {
              if (type == JSONObject.Type.OBJECT)
                  for (int i = 0; i < keys.Count; i++)
                      if ((string)keys[i] == name)
                          return true;
              return false;
          }
          public void Clear()
          {
              type = JSONObject.Type.NULL;
              list.Clear();
              keys.Clear();
              str = "";
              n = 0;
              b = false;
          }
          public JSONObject Copy()
          {
              return new JSONObject(print());
          }
          /*
           * The Merge function is experimental. Use at your own risk.
           */
          public void Merge(JSONObject obj)
          {
              MergeRecur(this, obj);
          }
          static void MergeRecur(JSONObject left, JSONObject right)
          {
              if (right.type == JSONObject.Type.OBJECT)
              {
                  for (int i = 0; i < right.list.Count; i++)
                  {
  
gt:                     if (right.keys[i] != null)