SimpleJSON

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
m (Fixed typo (it's != its))
(SimpleJSON.cs: Updated parsing method so it uses a StringBuilder instead of a string. This improves performance and avoids garbage when huge data is parsed.)
Line 150: Line 150:
 
using System.Collections.Generic;
 
using System.Collections.Generic;
 
using System.Linq;
 
using System.Linq;
 
+
using System.Text;
  
 
namespace SimpleJSON
 
namespace SimpleJSON
 
{
 
{
public enum JSONBinaryTag
+
    public enum JSONBinaryTag
{
+
    {
Array = 1,
+
        Array = 1,
Class = 2,
+
        Class = 2,
Value = 3,
+
        Value = 3,
IntValue = 4,
+
        IntValue = 4,
DoubleValue = 5,
+
        DoubleValue = 5,
BoolValue = 6,
+
        BoolValue = 6,
FloatValue = 7,
+
        FloatValue = 7,
}
+
    }
  
public abstract class JSONNode
+
    public abstract partial class JSONNode
{
+
    {
#region common interface
+
        #region common interface
  
public virtual void Add (string aKey, JSONNode aItem)
+
        public virtual void Add(string aKey, JSONNode aItem)
{
+
        {
}
+
        }
  
public virtual JSONNode this [int aIndex]   { get { return null; } set { } }
+
        public virtual JSONNode this[int aIndex] { get { return null; } set { } }
  
public virtual JSONNode this [string aKey] { get { return null; } set { } }
+
        public virtual JSONNode this[string aKey] { get { return null; } set { } }
  
public virtual string Value               { get { return ""; } set { } }
+
        public virtual string Value { get { return ""; } set { } }
  
public virtual int Count                   { get { return 0; } }
+
        public virtual int Count { get { return 0; } }
  
public virtual void Add (JSONNode aItem)
+
        public virtual void Add(JSONNode aItem)
{
+
        {
Add ("", aItem);
+
            Add("", aItem);
}
+
        }
  
public virtual JSONNode Remove (string aKey)
+
        public virtual JSONNode Remove(string aKey)
{
+
        {
return null;
+
            return null;
}
+
        }
  
public virtual JSONNode Remove (int aIndex)
+
        public virtual JSONNode Remove(int aIndex)
{
+
        {
return null;
+
            return null;
}
+
        }
  
public virtual JSONNode Remove (JSONNode aNode)
+
        public virtual JSONNode Remove(JSONNode aNode)
{
+
        {
return aNode;
+
            return aNode;
}
+
        }
  
public virtual IEnumerable<JSONNode> Children
+
        public virtual IEnumerable<JSONNode> Children
{
+
        {
get {
+
            get
yield break;
+
            {
}
+
                yield break;
}
+
            }
 +
        }
  
public IEnumerable<JSONNode> DeepChildren
+
        public IEnumerable<JSONNode> DeepChildren
{
+
        {
get {
+
            get
foreach (var C in Children)
+
            {
foreach (var D in C.DeepChildren)
+
                foreach (var C in Children)
yield return D;
+
                    foreach (var D in C.DeepChildren)
}
+
                        yield return D;
}
+
            }
 +
        }
  
public override string ToString ()
+
        public override string ToString()
{
+
        {
return "JSONNode";
+
            return "JSONNode";
}
+
        }
  
public virtual string ToString (string aPrefix)
+
        public virtual string ToString(string aPrefix)
{
+
        {
return "JSONNode";
+
            return "JSONNode";
}
+
        }
  
public abstract string ToJSON (int prefix);
+
        public abstract string ToJSON(int prefix);
  
#endregion common interface
+
        #endregion common interface
  
#region typecasting properties
+
        #region typecasting properties
  
public virtual JSONBinaryTag Tag { get; set; }
+
        public virtual JSONBinaryTag Tag { get; set; }
  
public virtual int AsInt
+
        public virtual int AsInt
{
+
        {
get {
+
            get
int v = 0;
+
            {
if (int.TryParse (Value, out v))
+
                int v = 0;
return v;
+
                if (int.TryParse(Value, out v))
return 0;
+
                    return v;
}
+
                return 0;
set {
+
            }
Value = value.ToString ();
+
            set
Tag = JSONBinaryTag.IntValue;
+
            {
}
+
                Value = value.ToString();
}
+
                Tag = JSONBinaryTag.IntValue;
 +
            }
 +
        }
  
public virtual float AsFloat
+
        public virtual float AsFloat
{
+
        {
get {
+
            get
float v = 0.0f;
+
            {
if (float.TryParse (Value, out v))
+
                float v = 0.0f;
return v;
+
                if (float.TryParse(Value, out v))
return 0.0f;
+
                    return v;
}
+
                return 0.0f;
set {
+
            }
Value = value.ToString ();
+
            set
Tag = JSONBinaryTag.FloatValue;
+
            {
}
+
                Value = value.ToString();
}
+
                Tag = JSONBinaryTag.FloatValue;
 +
            }
 +
        }
  
public virtual double AsDouble
+
        public virtual double AsDouble
{
+
        {
get {
+
            get
double v = 0.0;
+
            {
if (double.TryParse (Value, out v))
+
                double v = 0.0;
return v;
+
                if (double.TryParse(Value, out v))
return 0.0;
+
                    return v;
}
+
                return 0.0;
set {
+
            }
Value = value.ToString ();
+
            set
Tag = JSONBinaryTag.DoubleValue;
+
            {
 +
                Value = value.ToString();
 +
                Tag = JSONBinaryTag.DoubleValue;
  
}
+
            }
}
+
        }
  
public virtual bool AsBool
+
        public virtual bool AsBool
{
+
        {
get {
+
            get
bool v = false;
+
            {
if (bool.TryParse (Value, out v))
+
                bool v = false;
return v;
+
                if (bool.TryParse(Value, out v))
return !string.IsNullOrEmpty (Value);
+
                    return v;
}
+
                return !string.IsNullOrEmpty(Value);
set {
+
            }
Value = (value) ? "true" : "false";
+
            set
Tag = JSONBinaryTag.BoolValue;
+
            {
 +
                Value = (value) ? "true" : "false";
 +
                Tag = JSONBinaryTag.BoolValue;
  
}
+
            }
}
+
        }
  
public virtual JSONArray AsArray
+
        public virtual JSONArray AsArray
{
+
        {
get {
+
            get
return this as JSONArray;
+
            {
}
+
                return this as JSONArray;
}
+
            }
 +
        }
  
public virtual JSONClass AsObject
+
        public virtual JSONClass AsObject
{
+
        {
get {
+
            get
return this as JSONClass;
+
            {
}
+
                return this as JSONClass;
}
+
            }
 +
        }
  
  
#endregion typecasting properties
+
        #endregion typecasting properties
  
#region operators
+
        #region operators
  
public static implicit operator JSONNode (string s)
+
        public static implicit operator JSONNode(string s)
{
+
        {
return new JSONData (s);
+
            return new JSONData(s);
}
+
        }
  
public static implicit operator string (JSONNode d)
+
        public static implicit operator string(JSONNode d)
{
+
        {
return (d == null) ? null : d.Value;
+
            return (d == null) ? null : d.Value;
}
+
        }
  
public static bool operator == (JSONNode a, object b)
+
        public static bool operator ==(JSONNode a, object b)
{
+
        {
if (b == null && a is JSONLazyCreator)
+
            if (b == null && a is JSONLazyCreator)
return true;
+
                return true;
return System.Object.ReferenceEquals (a, b);
+
            return System.Object.ReferenceEquals(a, b);
}
+
        }
  
public static bool operator != (JSONNode a, object b)
+
        public static bool operator !=(JSONNode a, object b)
{
+
        {
return !(a == b);
+
            return !(a == b);
}
+
        }
  
public override bool Equals (object obj)
+
        public override bool Equals(object obj)
{
+
        {
return System.Object.ReferenceEquals (this, obj);
+
            return System.Object.ReferenceEquals(this, obj);
}
+
        }
  
public override int GetHashCode ()
+
        public override int GetHashCode()
{
+
        {
return base.GetHashCode ();
+
            return base.GetHashCode();
}
+
        }
  
 +
        #endregion operators
  
#endregion operators
+
        internal static string Escape(string aText)
 +
        {
 +
            string result = "";
 +
            foreach (char c in aText)
 +
            {
 +
                switch (c)
 +
                {
 +
                    case '\\':
 +
                        result += "\\\\";
 +
                        break;
 +
                    case '\"':
 +
                        result += "\\\"";
 +
                        break;
 +
                    case '\n':
 +
                        result += "\\n";
 +
                        break;
 +
                    case '\r':
 +
                        result += "\\r";
 +
                        break;
 +
                    case '\t':
 +
                        result += "\\t";
 +
                        break;
 +
                    case '\b':
 +
                        result += "\\b";
 +
                        break;
 +
                    case '\f':
 +
                        result += "\\f";
 +
                        break;
 +
                    default:
 +
                        result += c;
 +
                        break;
 +
                }
 +
            }
 +
            return result;
 +
        }
  
internal static string Escape (string aText)
+
        static JSONData Numberize(string token)
{
+
        {
string result = "";
+
            bool flag = false;
foreach (char c in aText) {
+
            int integer = 0;
switch (c) {
+
            double real = 0;
case '\\':
+
result += "\\\\";
+
break;
+
case '\"':
+
result += "\\\"";
+
break;
+
case '\n':
+
result += "\\n";
+
break;
+
case '\r':
+
result += "\\r";
+
break;
+
case '\t':
+
result += "\\t";
+
break;
+
case '\b':
+
result += "\\b";
+
break;
+
case '\f':
+
result += "\\f";
+
break;
+
default  :
+
result += c;
+
break;
+
}
+
}
+
return result;
+
}
+
  
static JSONData Numberize (string token)
+
            if (int.TryParse(token, out integer))
{
+
            {
bool flag = false;
+
                return new JSONData(integer);
int integer = 0;
+
            }
double real = 0;
+
  
if (int.TryParse (token, out integer)) {
+
            if (double.TryParse(token, out real))
return new JSONData (integer);
+
            {
}
+
                return new JSONData(real);
 +
            }
  
if (double.TryParse (token, out real)) {
+
            if (bool.TryParse(token, out flag))
return new JSONData (real);
+
            {
}
+
                return new JSONData(flag);
 +
            }
  
if (bool.TryParse (token, out flag)) {
+
            throw new NotImplementedException(token);
return new JSONData (flag);
+
        }
}
+
  
throw new NotImplementedException (token);
+
        static void AddElement(JSONNode ctx, string token, string tokenName, bool tokenIsString)
}
+
        {
 +
            if (tokenIsString)
 +
            {
 +
                if (ctx is JSONArray)
 +
                    ctx.Add(token);
 +
                else
 +
                    ctx.Add(tokenName, token); // assume dictionary/object
 +
            }
 +
            else
 +
            {
 +
                JSONData number = Numberize(token);
 +
                if (ctx is JSONArray)
 +
                    ctx.Add(number);
 +
                else
 +
                    ctx.Add(tokenName, number);
  
static void AddElement (JSONNode ctx, string token, string tokenName, bool tokenIsString)
+
            }
{
+
        }
if (tokenIsString) {
+
if (ctx is JSONArray)
+
ctx.Add (token);
+
else
+
ctx.Add (tokenName, token); // assume dictionary/object
+
} else {
+
JSONData number = Numberize (token);
+
if (ctx is JSONArray)
+
ctx.Add (number);
+
else
+
ctx.Add (tokenName, number);
+
  
}
+
        public static JSONNode Parse(string aJSON)
}
+
        {
 +
            Stack<JSONNode> stack = new Stack<JSONNode>();
 +
            JSONNode ctx = null;
 +
            int i = 0;
 +
            StringBuilder Token = new StringBuilder();
 +
            StringBuilder TokenName = new StringBuilder();
 +
            bool QuoteMode = false;
 +
            bool TokenIsString = false;
 +
            while (i < aJSON.Length)
 +
            {
 +
                switch (aJSON[i])
 +
                {
 +
                    case '{':
 +
                        if (QuoteMode)
 +
                        {
 +
                            Token.Append(aJSON[i]);
 +
                            break;
 +
                        }
 +
                        stack.Push(new JSONClass());
 +
                        if (ctx != null)
 +
                        {
 +
                            string tmpName = TokenName.ToString().Trim();
 +
                            if (ctx is JSONArray)
 +
                                ctx.Add(stack.Peek());
 +
                            else if (tmpName != "")
 +
                                ctx.Add(tmpName, stack.Peek());
 +
                        }
 +
                        TokenName.Length = 0;
 +
                        Token.Length = 0;
 +
                        ctx = stack.Peek();
 +
                        break;
  
public static JSONNode Parse (string aJSON)
+
                    case '[':
{
+
                        if (QuoteMode)
Stack<JSONNode> stack = new Stack<JSONNode> ();
+
                        {
JSONNode ctx = null;
+
                            Token.Append(aJSON[i]);
int i = 0;
+
                            break;
string Token = "";
+
                        }
string TokenName = "";
+
bool QuoteMode = false;
+
bool TokenIsString = false;
+
while (i < aJSON.Length) {
+
switch (aJSON [i]) {
+
case '{':
+
if (QuoteMode) {
+
Token += aJSON [i];
+
break;
+
}
+
stack.Push (new JSONClass ());
+
if (ctx != null) {
+
TokenName = TokenName.Trim ();
+
if (ctx is JSONArray)
+
ctx.Add (stack.Peek ());
+
else if (TokenName != "")
+
ctx.Add (TokenName, stack.Peek ());
+
}
+
TokenName = "";
+
Token = "";
+
ctx = stack.Peek ();
+
break;
+
  
case '[':
+
                        stack.Push(new JSONArray());
if (QuoteMode) {
+
                        if (ctx != null)
Token += aJSON [i];
+
                        {
break;
+
                            string tmpName = TokenName.ToString().Trim();
}
+
                            if (ctx is JSONArray)
 +
                                ctx.Add(stack.Peek());
 +
                            else if (tmpName != "")
 +
                                ctx.Add(tmpName, stack.Peek());
 +
                        }
 +
                        TokenName.Length = 0;
 +
                        Token.Length = 0;
 +
                        ctx = stack.Peek();
 +
                        break;
  
stack.Push (new JSONArray ());
+
                    case '}':
if (ctx != null) {
+
                    case ']':
TokenName = TokenName.Trim ();
+
                        if (QuoteMode)
 +
                        {
  
if (ctx is JSONArray)
+
                            Token.Append(aJSON[i]);
ctx.Add (stack.Peek ());
+
                            break;
else if (TokenName != "")
+
                        }
ctx.Add (TokenName, stack.Peek ());
+
                        if (stack.Count == 0)
}
+
                            throw new Exception("JSON Parse: Too many closing brackets");
TokenName = "";
+
Token = "";
+
ctx = stack.Peek ();
+
break;
+
  
case '}':
+
                        stack.Pop();
case ']':
+
                        if (Token.Length > 0)
if (QuoteMode) {
+
                        {
Token += aJSON [i];
+
                            string tmpName = TokenName.ToString().Trim();
break;
+
                            AddElement(ctx, Token.ToString(), TokenName.ToString(), TokenIsString);
}
+
                            TokenIsString = false;
if (stack.Count == 0)
+
                        }
throw new Exception ("JSON Parse: Too many closing brackets");
+
                        TokenName.Length = 0;
 +
                        Token.Length = 0;
 +
                        if (stack.Count > 0)
 +
                            ctx = stack.Peek();
 +
                        break;
  
stack.Pop ();
+
                    case ':':
if (Token != "") {
+
                        if (QuoteMode)
TokenName = TokenName.Trim ();
+
                        {
/*
+
                            Token.Append(aJSON[i]);
if (ctx is JSONArray)
+
                            break;
ctx.Add (Token);
+
                        }
else if (TokenName != "")
+
                        TokenName.Length = 0;
ctx.Add (TokenName, Token);
+
                        TokenName.Append(Token);
*/
+
                        Token.Length = 0;
AddElement (ctx, Token, TokenName, TokenIsString);
+
                        TokenIsString = false;
TokenIsString = false;
+
                        break;
}
+
TokenName = "";
+
Token = "";
+
if (stack.Count > 0)
+
ctx = stack.Peek ();
+
break;
+
  
case ':':
+
                    case '"':
if (QuoteMode) {
+
                        QuoteMode ^= true;
Token += aJSON [i];
+
                        TokenIsString = QuoteMode == true ? true : TokenIsString;
break;
+
                        break;
}
+
TokenName = Token;
+
Token = "";
+
TokenIsString = false;
+
break;
+
  
case '"':
+
                    case ',':
QuoteMode ^= true;
+
                        if (QuoteMode)
TokenIsString = QuoteMode == true ? true : TokenIsString;
+
                        {
break;
+
                            Token.Append(aJSON[i]);
 +
                            break;
 +
                        }
 +
                        if (Token.Length > 0)
 +
                        {
 +
                            AddElement(ctx, Token.ToString(), TokenName.ToString(), TokenIsString);
 +
                            TokenIsString = false;
 +
                        }
 +
                        TokenName.Length = 0;
 +
                        Token.Length = 0;
 +
                        TokenIsString = false;
 +
                        break;
  
case ',':
+
                    case '\r':
if (QuoteMode) {
+
                    case '\n':
Token += aJSON [i];
+
                        break;
break;
+
}
+
if (Token != "") {
+
/*
+
if (ctx is JSONArray) {
+
ctx.Add (Token);
+
} else if (TokenName != "") {
+
ctx.Add (TokenName, Token);
+
}
+
*/
+
AddElement (ctx, Token, TokenName, TokenIsString);
+
TokenIsString = false;
+
  
}
+
                    case ' ':
TokenName = "";
+
                    case '\t':
Token = "";
+
                        if (QuoteMode)
TokenIsString = false;
+
                            Token.Append(aJSON[i]);
break;
+
                        break;
  
case '\r':
+
                    case '\\':
case '\n':
+
                        ++i;
break;
+
                        if (QuoteMode)
 +
                        {
 +
                            char C = aJSON[i];
 +
                            switch (C)
 +
                            {
 +
                                case 't':
 +
                                    Token.Append('\t');
 +
                                    break;
 +
                                case 'r':
 +
                                    Token.Append('\r');
 +
                                    break;
 +
                                case 'n':
 +
                                    Token.Append('\n');
 +
                                    break;
 +
                                case 'b':
 +
                                    Token.Append('\b');
 +
                                    break;
 +
                                case 'f':
 +
                                    Token.Append('\f');
 +
                                    break;
 +
                                case 'u':
 +
                                    {
 +
                                        string s = aJSON.Substring(i + 1, 4);
 +
                                        Token.Append((char)int.Parse(
 +
                                            s,
 +
                                            System.Globalization.NumberStyles.AllowHexSpecifier));
 +
                                        i += 4;
 +
                                        break;
 +
                                    }
 +
                                default:
 +
                                    Token.Append(C);
 +
                                    break;
 +
                            }
 +
                        }
 +
                        break;
  
case ' ':
+
                    default:
case '\t':
+
                        Token.Append(aJSON[i]);
if (QuoteMode)
+
                        break;
Token += aJSON [i];
+
                }
break;
+
                ++i;
 +
            }
 +
            if (QuoteMode)
 +
            {
 +
                throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
 +
            }
 +
            return ctx;
 +
        }
  
case '\\':
+
        public virtual void Serialize(System.IO.BinaryWriter aWriter)
++i;
+
        {
if (QuoteMode) {
+
        }
char C = aJSON [i];
+
switch (C) {
+
case 't':
+
Token += '\t';
+
break;
+
case 'r':
+
Token += '\r';
+
break;
+
case 'n':
+
Token += '\n';
+
break;
+
case 'b':
+
Token += '\b';
+
break;
+
case 'f':
+
Token += '\f';
+
break;
+
case 'u':
+
{
+
string s = aJSON.Substring (i + 1, 4);
+
Token += (char)int.Parse (
+
s,
+
System.Globalization.NumberStyles.AllowHexSpecifier);
+
i += 4;
+
break;
+
}
+
default  :
+
Token += C;
+
break;
+
}
+
}
+
break;
+
  
default:
+
        public void SaveToStream(System.IO.Stream aData)
Token += aJSON [i];
+
        {
break;
+
            var W = new System.IO.BinaryWriter(aData);
}
+
            Serialize(W);
++i;
+
        }
}
+
if (QuoteMode) {
+
throw new Exception ("JSON Parse: Quotation marks seems to be messed up.");
+
}
+
return ctx;
+
}
+
 
+
public virtual void Serialize (System.IO.BinaryWriter aWriter)
+
{
+
}
+
 
+
public void SaveToStream (System.IO.Stream aData)
+
{
+
var W = new System.IO.BinaryWriter (aData);
+
Serialize (W);
+
}
+
  
#if USE_SharpZipLib
+
#if USE_SharpZipLib
 
public void SaveToCompressedStream(System.IO.Stream aData)
 
public void SaveToCompressedStream(System.IO.Stream aData)
 
{
 
{
Line 636: Line 656:
 
 
 
#else
 
#else
public void SaveToCompressedStream (System.IO.Stream aData)
+
        public void SaveToCompressedStream(System.IO.Stream aData)
{
+
        {
throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
}
+
        }
  
public void SaveToCompressedFile (string aFileName)
+
        public void SaveToCompressedFile(string aFileName)
{
+
        {
throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
}
+
        }
  
public string SaveToCompressedBase64 ()
+
        public string SaveToCompressedBase64()
{
+
        {
throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
}
+
        }
#endif
+
#endif
  
public void SaveToFile (string aFileName)
+
        public void SaveToFile(string aFileName)
{
+
        {
 
#if USE_FileIO
 
#if USE_FileIO
System.IO.Directory.CreateDirectory ((new System.IO.FileInfo (aFileName)).Directory.FullName);
+
            System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName);
using (var F = System.IO.File.OpenWrite (aFileName)) {
+
            using (var F = System.IO.File.OpenWrite(aFileName))
SaveToStream (F);
+
            {
}
+
                SaveToStream(F);
#else
+
            }
 +
#else
 
throw new Exception ("Can't use File IO stuff in webplayer");
 
throw new Exception ("Can't use File IO stuff in webplayer");
#endif
+
#endif
}
+
        }
  
public string SaveToBase64 ()
+
        public string SaveToBase64()
{
+
        {
using (var stream = new System.IO.MemoryStream ()) {
+
            using (var stream = new System.IO.MemoryStream())
SaveToStream (stream);
+
            {
stream.Position = 0;
+
                SaveToStream(stream);
return System.Convert.ToBase64String (stream.ToArray ());
+
                stream.Position = 0;
}
+
                return System.Convert.ToBase64String(stream.ToArray());
}
+
            }
 +
        }
  
public static JSONNode Deserialize (System.IO.BinaryReader aReader)
+
        public static JSONNode Deserialize(System.IO.BinaryReader aReader)
{
+
        {
JSONBinaryTag type = (JSONBinaryTag)aReader.ReadByte ();
+
            JSONBinaryTag type = (JSONBinaryTag)aReader.ReadByte();
switch (type) {
+
            switch (type)
case JSONBinaryTag.Array:
+
            {
{
+
                case JSONBinaryTag.Array:
int count = aReader.ReadInt32 ();
+
                    {
JSONArray tmp = new JSONArray ();
+
                        int count = aReader.ReadInt32();
for (int i = 0; i < count; i++)
+
                        JSONArray tmp = new JSONArray();
tmp.Add (Deserialize (aReader));
+
                        for (int i = 0; i < count; i++)
return tmp;
+
                            tmp.Add(Deserialize(aReader));
}
+
                        return tmp;
case JSONBinaryTag.Class:
+
                    }
{
+
                case JSONBinaryTag.Class:
int count = aReader.ReadInt32 ();              
+
                    {
JSONClass tmp = new JSONClass ();
+
                        int count = aReader.ReadInt32();
for (int i = 0; i < count; i++) {
+
                        JSONClass tmp = new JSONClass();
string key = aReader.ReadString ();
+
                        for (int i = 0; i < count; i++)
var val = Deserialize (aReader);
+
                        {
tmp.Add (key, val);
+
                            string key = aReader.ReadString();
}
+
                            var val = Deserialize(aReader);
return tmp;
+
                            tmp.Add(key, val);
}
+
                        }
case JSONBinaryTag.Value:
+
                        return tmp;
{
+
                    }
return new JSONData (aReader.ReadString ());
+
                case JSONBinaryTag.Value:
}
+
                    {
case JSONBinaryTag.IntValue:
+
                        return new JSONData(aReader.ReadString());
{
+
                    }
return new JSONData (aReader.ReadInt32 ());
+
                case JSONBinaryTag.IntValue:
}
+
                    {
case JSONBinaryTag.DoubleValue:
+
                        return new JSONData(aReader.ReadInt32());
{
+
                    }
return new JSONData (aReader.ReadDouble ());
+
                case JSONBinaryTag.DoubleValue:
}
+
                    {
case JSONBinaryTag.BoolValue:
+
                        return new JSONData(aReader.ReadDouble());
{
+
                    }
return new JSONData (aReader.ReadBoolean ());
+
                case JSONBinaryTag.BoolValue:
}
+
                    {
case JSONBinaryTag.FloatValue:
+
                        return new JSONData(aReader.ReadBoolean());
{
+
                    }
return new JSONData (aReader.ReadSingle ());
+
                case JSONBinaryTag.FloatValue:
}
+
                    {
 +
                        return new JSONData(aReader.ReadSingle());
 +
                    }
  
default:
+
                default:
{
+
                    {
throw new Exception ("Error deserializing JSON. Unknown tag: " + type);
+
                        throw new Exception("Error deserializing JSON. Unknown tag: " + type);
}
+
                    }
}
+
            }
}
+
        }
  
#if USE_SharpZipLib
+
#if USE_SharpZipLib
 
public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
 
public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
 
{
 
{
Line 749: Line 773:
 
}
 
}
 
#else
 
#else
public static JSONNode LoadFromCompressedFile (string aFileName)
+
        public static JSONNode LoadFromCompressedFile(string aFileName)
{
+
        {
throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
}
+
        }
  
public static JSONNode LoadFromCompressedStream (System.IO.Stream aData)
+
        public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
{
+
        {
throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
}
+
        }
  
public static JSONNode LoadFromCompressedBase64 (string aBase64)
+
        public static JSONNode LoadFromCompressedBase64(string aBase64)
{
+
        {
throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
}
+
        }
#endif
+
#endif
  
public static JSONNode LoadFromStream (System.IO.Stream aData)
+
        public static JSONNode LoadFromStream(System.IO.Stream aData)
{
+
        {
using (var R = new System.IO.BinaryReader (aData)) {
+
            using (var R = new System.IO.BinaryReader(aData))
return Deserialize (R);
+
            {
}
+
                return Deserialize(R);
}
+
            }
 +
        }
  
public static JSONNode LoadFromFile (string aFileName)
+
        public static JSONNode LoadFromFile(string aFileName)
{
+
        {
#if USE_FileIO
+
#if USE_FileIO
using (var F = System.IO.File.OpenRead (aFileName)) {
+
            using (var F = System.IO.File.OpenRead(aFileName))
return LoadFromStream (F);
+
            {
}
+
                return LoadFromStream(F);
#else
+
            }
 +
#else
 
throw new Exception ("Can't use File IO stuff in webplayer");
 
throw new Exception ("Can't use File IO stuff in webplayer");
#endif
+
#endif
}
+
        }
  
public static JSONNode LoadFromBase64 (string aBase64)
+
        public static JSONNode LoadFromBase64(string aBase64)
{
+
        {
var tmp = System.Convert.FromBase64String (aBase64);
+
            var tmp = System.Convert.FromBase64String(aBase64);
var stream = new System.IO.MemoryStream (tmp);
+
            var stream = new System.IO.MemoryStream(tmp);
stream.Position = 0;
+
            stream.Position = 0;
return LoadFromStream (stream);
+
            return LoadFromStream(stream);
}
+
        }
}
+
    }
// End of JSONNode
+
    // End of JSONNode
  
public class JSONArray : JSONNode, IEnumerable
+
    public class JSONArray : JSONNode, IEnumerable
{
+
    {
private List<JSONNode> m_List = new List<JSONNode> ();
+
        private List<JSONNode> m_List = new List<JSONNode>();
  
public override JSONNode this [int aIndex]
+
        public override JSONNode this[int aIndex]
{
+
        {
get {
+
            get
if (aIndex < 0 || aIndex >= m_List.Count)
+
            {
return new JSONLazyCreator (this);
+
                if (aIndex < 0 || aIndex >= m_List.Count)
return m_List [aIndex];
+
                    return new JSONLazyCreator(this);
}
+
                return m_List[aIndex];
set {
+
            }
if (aIndex < 0 || aIndex >= m_List.Count)
+
            set
m_List.Add (value);
+
            {
else
+
                if (aIndex < 0 || aIndex >= m_List.Count)
m_List [aIndex] = value;
+
                    m_List.Add(value);
}
+
                else
}
+
                    m_List[aIndex] = value;
 +
            }
 +
        }
  
public override JSONNode this [string aKey]
+
        public override JSONNode this[string aKey]
{
+
        {
get{ return new JSONLazyCreator (this); }
+
            get { return new JSONLazyCreator(this); }
set{ m_List.Add (value); }
+
            set { m_List.Add(value); }
}
+
        }
  
public override int Count
+
        public override int Count
{
+
        {
get { return m_List.Count; }
+
            get { return m_List.Count; }
}
+
        }
  
public override void Add (string aKey, JSONNode aItem)
 
{
 
m_List.Add (aItem);
 
}
 
  
public override JSONNode Remove (int aIndex)
+
        public override void Add(string aKey, JSONNode aItem)
{
+
        {
if (aIndex < 0 || aIndex >= m_List.Count)
+
            m_List.Add(aItem);
return null;
+
        }
JSONNode tmp = m_List [aIndex];
+
m_List.RemoveAt (aIndex);
+
return tmp;
+
}
+
  
public override JSONNode Remove (JSONNode aNode)
+
        public override JSONNode Remove(int aIndex)
{
+
        {
m_List.Remove (aNode);
+
            if (aIndex < 0 || aIndex >= m_List.Count)
return aNode;
+
                return null;
}
+
            JSONNode tmp = m_List[aIndex];
 +
            m_List.RemoveAt(aIndex);
 +
            return tmp;
 +
        }
  
public override IEnumerable<JSONNode> Children
+
        public override JSONNode Remove(JSONNode aNode)
{
+
        {
get {
+
            m_List.Remove(aNode);
foreach (JSONNode N in m_List)
+
            return aNode;
yield return N;
+
        }
}
+
}
+
  
public IEnumerator GetEnumerator ()
+
        public override IEnumerable<JSONNode> Children
{
+
        {
foreach (JSONNode N in m_List)
+
            get
yield return N;
+
            {
}
+
                foreach (JSONNode N in m_List)
 +
                    yield return N;
 +
            }
 +
        }
  
public override string ToString ()
+
        public IEnumerator GetEnumerator()
{
+
        {
string result = "[ ";
+
            foreach (JSONNode N in m_List)
foreach (JSONNode N in m_List) {
+
                yield return N;
if (result.Length > 2)
+
        }
result += ", ";
+
result += N.ToString ();
+
}
+
result += " ]";
+
return result;
+
}
+
  
public override string ToString (string aPrefix)
+
        public override string ToString()
{
+
        {
string result = "[ ";
+
            string result = "[ ";
foreach (JSONNode N in m_List) {
+
            foreach (JSONNode N in m_List)
if (result.Length > 3)
+
            {
result += ", ";
+
                if (result.Length > 2)
result += "\n" + aPrefix + "  ";               
+
                    result += ", ";
result += N.ToString (aPrefix + "  ");
+
                result += N.ToString();
}
+
            }
result += "\n" + aPrefix + "]";
+
            result += " ]";
return result;
+
            return result;
}
+
        }
  
public override string ToJSON (int prefix)
+
        public override string ToString(string aPrefix)
{
+
        {
string s = new string (' ', (prefix + 1) * 2);
+
            string result = "[ ";
string ret = "[ ";
+
            foreach (JSONNode N in m_List)
foreach (JSONNode n in m_List) {
+
            {
if (ret.Length > 3)
+
                if (result.Length > 3)
ret += ", ";
+
                    result += ", ";
ret += "\n" + s;
+
                result += "\n" + aPrefix + "  ";
ret += n.ToJSON (prefix + 1);
+
                result += N.ToString(aPrefix + "  ");
 +
            }
 +
            result += "\n" + aPrefix + "]";
 +
            return result;
 +
        }
  
}
+
        public override string ToJSON(int prefix)
ret += "\n" + s + "]";
+
        {
return ret;
+
            string s = new string(' ', (prefix + 1) * 2);
}
+
            string ret = "[ ";
 +
            foreach (JSONNode n in m_List)
 +
            {
 +
                if (ret.Length > 3)
 +
                    ret += ", ";
 +
                ret += "\n" + s;
 +
                ret += n.ToJSON(prefix + 1);
  
public override void Serialize (System.IO.BinaryWriter aWriter)
+
            }
{
+
            ret += "\n" + s + "]";
aWriter.Write ((byte)JSONBinaryTag.Array);
+
            return ret;
aWriter.Write (m_List.Count);
+
        }
for (int i = 0; i < m_List.Count; i++) {
+
m_List [i].Serialize (aWriter);
+
}
+
}
+
}
+
// End of JSONArray
+
  
public class JSONClass : JSONNode, IEnumerable
+
        public override void Serialize(System.IO.BinaryWriter aWriter)
{
+
        {
private Dictionary<string,JSONNode> m_Dict = new Dictionary<string,JSONNode> ();
+
            aWriter.Write((byte)JSONBinaryTag.Array);
 +
            aWriter.Write(m_List.Count);
 +
            for (int i = 0; i < m_List.Count; i++)
 +
            {
 +
                m_List[i].Serialize(aWriter);
 +
            }
 +
        }
 +
    }
 +
    // End of JSONArray
  
public override JSONNode this [string aKey]
+
    public class JSONClass : JSONNode, IEnumerable
{
+
    {
get {
+
        private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();
if (m_Dict.ContainsKey (aKey))
+
return m_Dict [aKey];
+
else
+
return new JSONLazyCreator (this, aKey);
+
}
+
set {
+
if (m_Dict.ContainsKey (aKey))
+
m_Dict [aKey] = value;
+
else
+
m_Dict.Add (aKey, value);
+
}
+
}
+
  
public override JSONNode this [int aIndex]
+
        public override JSONNode this[string aKey]
{
+
        {
get {
+
            get
if (aIndex < 0 || aIndex >= m_Dict.Count)
+
            {
return null;
+
                if (m_Dict.ContainsKey(aKey))
return m_Dict.ElementAt (aIndex).Value;
+
                    return m_Dict[aKey];
}
+
                else
set {
+
                    return new JSONLazyCreator(this, aKey);
if (aIndex < 0 || aIndex >= m_Dict.Count)
+
            }
return;
+
            set
string key = m_Dict.ElementAt (aIndex).Key;
+
            {
m_Dict [key] = value;
+
                if (m_Dict.ContainsKey(aKey))
}
+
                    m_Dict[aKey] = value;
}
+
                else
 +
                    m_Dict.Add(aKey, value);
 +
            }
 +
        }
  
public override int Count
+
        public override JSONNode this[int aIndex]
{
+
        {
get { return m_Dict.Count; }
+
            get
}
+
            {
 +
                if (aIndex < 0 || aIndex >= m_Dict.Count)
 +
                    return null;
 +
                return m_Dict.ElementAt(aIndex).Value;
 +
            }
 +
            set
 +
            {
 +
                if (aIndex < 0 || aIndex >= m_Dict.Count)
 +
                    return;
 +
                string key = m_Dict.ElementAt(aIndex).Key;
 +
                m_Dict[key] = value;
 +
            }
 +
        }
  
 +
        public override int Count
 +
        {
 +
            get { return m_Dict.Count; }
 +
        }
  
public override void Add (string aKey, JSONNode aItem)
+
        public override void Add(string aKey, JSONNode aItem)
{
+
        {
if (!string.IsNullOrEmpty (aKey)) {
+
            if (!string.IsNullOrEmpty(aKey))
if (m_Dict.ContainsKey (aKey))
+
            {
m_Dict [aKey] = aItem;
+
                if (m_Dict.ContainsKey(aKey))
else
+
                    m_Dict[aKey] = aItem;
m_Dict.Add (aKey, aItem);
+
                else
} else
+
                    m_Dict.Add(aKey, aItem);
m_Dict.Add (Guid.NewGuid ().ToString (), aItem);
+
            }
}
+
            else
 +
                m_Dict.Add(Guid.NewGuid().ToString(), aItem);
 +
        }
  
public override JSONNode Remove (string aKey)
+
        public override JSONNode Remove(string aKey)
{
+
        {
if (!m_Dict.ContainsKey (aKey))
+
            if (!m_Dict.ContainsKey(aKey))
return null;
+
                return null;
JSONNode tmp = m_Dict [aKey];
+
            JSONNode tmp = m_Dict[aKey];
m_Dict.Remove (aKey);
+
            m_Dict.Remove(aKey);
return tmp;      
+
            return tmp;
}
+
        }
  
public override JSONNode Remove (int aIndex)
+
        public override JSONNode Remove(int aIndex)
{
+
        {
if (aIndex < 0 || aIndex >= m_Dict.Count)
+
            if (aIndex < 0 || aIndex >= m_Dict.Count)
return null;
+
                return null;
var item = m_Dict.ElementAt (aIndex);
+
            var item = m_Dict.ElementAt(aIndex);
m_Dict.Remove (item.Key);
+
            m_Dict.Remove(item.Key);
return item.Value;
+
            return item.Value;
}
+
        }
  
public override JSONNode Remove (JSONNode aNode)
+
        public override JSONNode Remove(JSONNode aNode)
{
+
        {
try {
+
            try
var item = m_Dict.Where (k => k.Value == aNode).First ();
+
            {
m_Dict.Remove (item.Key);
+
                var item = m_Dict.Where(k => k.Value == aNode).First();
return aNode;
+
                m_Dict.Remove(item.Key);
} catch {
+
                return aNode;
return null;
+
            }
}
+
            catch
}
+
            {
 +
                return null;
 +
            }
 +
        }
  
public override IEnumerable<JSONNode> Children
+
        public override IEnumerable<JSONNode> Children
{
+
        {
get {
+
            get
foreach (KeyValuePair<string,JSONNode> N in m_Dict)
+
            {
yield return N.Value;
+
                foreach (KeyValuePair<string, JSONNode> N in m_Dict)
}
+
                    yield return N.Value;
}
+
            }
 +
        }
  
public IEnumerator GetEnumerator ()
+
        public IEnumerator GetEnumerator()
{
+
        {
foreach (KeyValuePair<string, JSONNode> N in m_Dict)
+
            foreach (KeyValuePair<string, JSONNode> N in m_Dict)
yield return N;
+
                yield return N;
}
+
        }
  
public override string ToString ()
+
        public override string ToString()
{
+
        {
string result = "{";
+
            string result = "{";
foreach (KeyValuePair<string, JSONNode> N in m_Dict) {
+
            foreach (KeyValuePair<string, JSONNode> N in m_Dict)
if (result.Length > 2)
+
            {
result += ", ";
+
                if (result.Length > 2)
result += "\"" + Escape (N.Key) + "\":" + N.Value.ToString ();
+
                    result += ", ";
}
+
                result += "\"" + Escape(N.Key) + "\":" + N.Value.ToString();
result += "}";
+
            }
return result;
+
            result += "}";
}
+
            return result;
 +
        }
  
public override string ToString (string aPrefix)
+
        public override string ToString(string aPrefix)
{
+
        {
string result = "{ ";
+
            string result = "{ ";
foreach (KeyValuePair<string, JSONNode> N in m_Dict) {
+
            foreach (KeyValuePair<string, JSONNode> N in m_Dict)
if (result.Length > 3)
+
            {
result += ", ";
+
                if (result.Length > 3)
result += "\n" + aPrefix + "  ";
+
                    result += ", ";
result += "\"" + Escape (N.Key) + "\" : " + N.Value.ToString (aPrefix + "  ");
+
                result += "\n" + aPrefix + "  ";
}
+
                result += "\"" + Escape(N.Key) + "\" : " + N.Value.ToString(aPrefix + "  ");
result += "\n" + aPrefix + "}";
+
            }
return result;
+
            result += "\n" + aPrefix + "}";
}
+
            return result;
 +
        }
  
public override string ToJSON (int prefix)
+
        public override string ToJSON(int prefix)
{
+
        {
string s = new string (' ', (prefix + 1) * 2);
+
            string s = new string(' ', (prefix + 1) * 2);
string ret = "{ ";
+
            string ret = "{ ";
foreach (KeyValuePair<string,JSONNode> n in m_Dict) {
+
            foreach (KeyValuePair<string, JSONNode> n in m_Dict)
if (ret.Length > 3)
+
            {
ret += ", ";
+
                if (ret.Length > 3)
ret += "\n" + s;
+
                    ret += ", ";
ret += string.Format ("\"{0}\": {1}", n.Key, n.Value.ToJSON (prefix + 1));
+
                ret += "\n" + s;
}
+
                ret += string.Format("\"{0}\": {1}", n.Key, n.Value.ToJSON(prefix + 1));
ret += "\n" + s + "}";
+
            }
return ret;
+
            ret += "\n" + s + "}";
}
+
            return ret;
 +
        }
  
public override void Serialize (System.IO.BinaryWriter aWriter)
+
        public override void Serialize(System.IO.BinaryWriter aWriter)
{
+
        {
aWriter.Write ((byte)JSONBinaryTag.Class);
+
            aWriter.Write((byte)JSONBinaryTag.Class);
aWriter.Write (m_Dict.Count);
+
            aWriter.Write(m_Dict.Count);
foreach (string K in m_Dict.Keys) {
+
            foreach (string K in m_Dict.Keys)
aWriter.Write (K);
+
            {
m_Dict [K].Serialize (aWriter);
+
                aWriter.Write(K);
}
+
                m_Dict[K].Serialize(aWriter);
}
+
            }
}
+
        }
// End of JSONClass
+
    }
 +
    // End of JSONClass
  
public class JSONData : JSONNode
+
    public class JSONData : JSONNode
{
+
    {
private string m_Data;
+
        private string m_Data;
  
  
public override string Value
+
        public override string Value
{
+
        {
get { return m_Data; }
+
            get { return m_Data; }
set {
+
            set
m_Data = value;
+
            {
Tag = JSONBinaryTag.Value;
+
                m_Data = value;
}
+
                Tag = JSONBinaryTag.Value;
}
+
            }
 +
        }
  
public JSONData (string aData)
+
        public JSONData(string aData)
{
+
        {
m_Data = aData;
+
            m_Data = aData;
Tag = JSONBinaryTag.Value;
+
            Tag = JSONBinaryTag.Value;
}
+
        }
  
public JSONData (float aData)
+
        public JSONData(float aData)
{
+
        {
AsFloat = aData;
+
            AsFloat = aData;
}
+
        }
  
public JSONData (double aData)
+
        public JSONData(double aData)
{
+
        {
AsDouble = aData;
+
            AsDouble = aData;
}
+
        }
  
public JSONData (bool aData)
+
        public JSONData(bool aData)
{
+
        {
AsBool = aData;
+
            AsBool = aData;
}
+
        }
  
public JSONData (int aData)
+
        public JSONData(int aData)
{
+
        {
AsInt = aData;
+
            AsInt = aData;
}
+
        }
  
public override string ToString ()
+
        public override string ToString()
{
+
        {
return "\"" + Escape (m_Data) + "\"";
+
            return "\"" + Escape(m_Data) + "\"";
}
+
        }
  
public override string ToString (string aPrefix)
+
        public override string ToString(string aPrefix)
{
+
        {
return "\"" + Escape (m_Data) + "\"";
+
            return "\"" + Escape(m_Data) + "\"";
}
+
        }
  
public override string ToJSON (int prefix)
+
        public override string ToJSON(int prefix)
{
+
        {
switch (Tag) {
+
            switch (Tag)
case JSONBinaryTag.DoubleValue:
+
            {
case JSONBinaryTag.FloatValue:
+
                case JSONBinaryTag.DoubleValue:
case JSONBinaryTag.IntValue:
+
                case JSONBinaryTag.FloatValue:
return m_Data;
+
                case JSONBinaryTag.IntValue:
case JSONBinaryTag.Value:
+
                    return m_Data;
return string.Format ("\"{0}\"", Escape (m_Data));
+
                case JSONBinaryTag.Value:
default:
+
                    return string.Format("\"{0}\"", Escape(m_Data));
throw new NotSupportedException ("This shouldn't be here: " + Tag.ToString ());
+
                default:
}
+
                    throw new NotSupportedException("This shouldn't be here: " + Tag.ToString());
}
+
            }
 +
        }
  
public override void Serialize (System.IO.BinaryWriter aWriter)
+
        public override void Serialize(System.IO.BinaryWriter aWriter)
{
+
        {
var tmp = new JSONData ("");
+
            var tmp = new JSONData("");
  
tmp.AsInt = AsInt;
+
            tmp.AsInt = AsInt;
if (tmp.m_Data == this.m_Data) {
+
            if (tmp.m_Data == this.m_Data)
aWriter.Write ((byte)JSONBinaryTag.IntValue);
+
            {
aWriter.Write (AsInt);
+
                aWriter.Write((byte)JSONBinaryTag.IntValue);
return;
+
                aWriter.Write(AsInt);
}
+
                return;
tmp.AsFloat = AsFloat;
+
            }
if (tmp.m_Data == this.m_Data) {
+
            tmp.AsFloat = AsFloat;
aWriter.Write ((byte)JSONBinaryTag.FloatValue);
+
            if (tmp.m_Data == this.m_Data)
aWriter.Write (AsFloat);
+
            {
return;
+
                aWriter.Write((byte)JSONBinaryTag.FloatValue);
}
+
                aWriter.Write(AsFloat);
tmp.AsDouble = AsDouble;
+
                return;
if (tmp.m_Data == this.m_Data) {
+
            }
aWriter.Write ((byte)JSONBinaryTag.DoubleValue);
+
            tmp.AsDouble = AsDouble;
aWriter.Write (AsDouble);
+
            if (tmp.m_Data == this.m_Data)
return;
+
            {
}
+
                aWriter.Write((byte)JSONBinaryTag.DoubleValue);
 +
                aWriter.Write(AsDouble);
 +
                return;
 +
            }
  
tmp.AsBool = AsBool;
+
            tmp.AsBool = AsBool;
if (tmp.m_Data == this.m_Data) {
+
            if (tmp.m_Data == this.m_Data)
aWriter.Write ((byte)JSONBinaryTag.BoolValue);
+
            {
aWriter.Write (AsBool);
+
                aWriter.Write((byte)JSONBinaryTag.BoolValue);
return;
+
                aWriter.Write(AsBool);
}
+
                return;
aWriter.Write ((byte)JSONBinaryTag.Value);
+
            }
aWriter.Write (m_Data);
+
            aWriter.Write((byte)JSONBinaryTag.Value);
}
+
            aWriter.Write(m_Data);
}
+
        }
// End of JSONData
+
    }
 +
    // End of JSONData
  
internal class JSONLazyCreator : JSONNode
+
    internal class JSONLazyCreator : JSONNode
{
+
    {
private JSONNode m_Node = null;
+
        private JSONNode m_Node = null;
private string m_Key = null;
+
        private string m_Key = null;
  
public JSONLazyCreator (JSONNode aNode)
+
        public JSONLazyCreator(JSONNode aNode)
{
+
        {
m_Node = aNode;
+
            m_Node = aNode;
m_Key = null;
+
            m_Key = null;
}
+
        }
  
public JSONLazyCreator (JSONNode aNode, string aKey)
+
        public JSONLazyCreator(JSONNode aNode, string aKey)
{
+
        {
m_Node = aNode;
+
            m_Node = aNode;
m_Key = aKey;
+
            m_Key = aKey;
}
+
        }
  
private void Set (JSONNode aVal)
+
        private void Set(JSONNode aVal)
{
+
        {
if (m_Key == null) {
+
            if (m_Key == null)
m_Node.Add (aVal);
+
            {
} else {
+
                m_Node.Add(aVal);
m_Node.Add (m_Key, aVal);
+
            }
}
+
            else
m_Node = null; // Be GC friendly.
+
            {
}
+
                m_Node.Add(m_Key, aVal);
 +
            }
 +
            m_Node = null; // Be GC friendly.
 +
        }
  
public override JSONNode this [int aIndex]
+
        public override JSONNode this[int aIndex]
{
+
        {
get {
+
            get
return new JSONLazyCreator (this);
+
            {
}
+
                return new JSONLazyCreator(this);
set {
+
            }
var tmp = new JSONArray ();
+
            set
tmp.Add (value);
+
            {
Set (tmp);
+
                var tmp = new JSONArray();
}
+
                tmp.Add(value);
}
+
                Set(tmp);
 +
            }
 +
        }
  
public override JSONNode this [string aKey]
+
        public override JSONNode this[string aKey]
{
+
        {
get {
+
            get
return new JSONLazyCreator (this, aKey);
+
            {
}
+
                return new JSONLazyCreator(this, aKey);
set {
+
            }
var tmp = new JSONClass ();
+
            set
tmp.Add (aKey, value);
+
            {
Set (tmp);
+
                var tmp = new JSONClass();
}
+
                tmp.Add(aKey, value);
}
+
                Set(tmp);
 +
            }
 +
        }
  
public override void Add (JSONNode aItem)
+
        public override void Add(JSONNode aItem)
{
+
        {
var tmp = new JSONArray ();
+
            var tmp = new JSONArray();
tmp.Add (aItem);
+
            tmp.Add(aItem);
Set (tmp);
+
            Set(tmp);
}
+
        }
  
public override void Add (string aKey, JSONNode aItem)
+
        public override void Add(string aKey, JSONNode aItem)
{
+
        {
var tmp = new JSONClass ();
+
            var tmp = new JSONClass();
tmp.Add (aKey, aItem);
+
            tmp.Add(aKey, aItem);
Set (tmp);
+
            Set(tmp);
}
+
        }
  
public static bool operator == (JSONLazyCreator a, object b)
+
        public static bool operator ==(JSONLazyCreator a, object b)
{
+
        {
if (b == null)
+
            if (b == null)
return true;
+
                return true;
return System.Object.ReferenceEquals (a, b);
+
            return System.Object.ReferenceEquals(a, b);
}
+
        }
  
public static bool operator != (JSONLazyCreator a, object b)
+
        public static bool operator !=(JSONLazyCreator a, object b)
{
+
        {
return !(a == b);
+
            return !(a == b);
}
+
        }
  
public override bool Equals (object obj)
+
        public override bool Equals(object obj)
{
+
        {
if (obj == null)
+
            if (obj == null)
return true;
+
                return true;
return System.Object.ReferenceEquals (this, obj);
+
            return System.Object.ReferenceEquals(this, obj);
}
+
        }
  
public override int GetHashCode ()
+
        public override int GetHashCode()
{
+
        {
return base.GetHashCode ();
+
            return base.GetHashCode();
}
+
        }
  
public override string ToString ()
+
        public override string ToString()
{
+
        {
return "";
+
            return "";
}
+
        }
  
public override string ToString (string aPrefix)
+
        public override string ToString(string aPrefix)
{
+
        {
return "";
+
            return "";
}
+
        }
  
public override string ToJSON (int prefix)
+
        public override string ToJSON(int prefix)
{
+
        {
return "";
+
            return "";
}
+
        }
  
public override int AsInt
+
        public override int AsInt
{
+
        {
get {
+
            get
JSONData tmp = new JSONData (0);
+
            {
Set (tmp);
+
                JSONData tmp = new JSONData(0);
return 0;
+
                Set(tmp);
}
+
                return 0;
set {
+
            }
JSONData tmp = new JSONData (value);
+
            set
Set (tmp);
+
            {
}
+
                JSONData tmp = new JSONData(value);
}
+
                Set(tmp);
 +
            }
 +
        }
  
public override float AsFloat
+
        public override float AsFloat
{
+
        {
get {
+
            get
JSONData tmp = new JSONData (0.0f);
+
            {
Set (tmp);
+
                JSONData tmp = new JSONData(0.0f);
return 0.0f;
+
                Set(tmp);
}
+
                return 0.0f;
set {
+
            }
JSONData tmp = new JSONData (value);
+
            set
Set (tmp);
+
            {
}
+
                JSONData tmp = new JSONData(value);
}
+
                Set(tmp);
 +
            }
 +
        }
  
public override double AsDouble
+
        public override double AsDouble
{
+
        {
get {
+
            get
JSONData tmp = new JSONData (0.0);
+
            {
Set (tmp);
+
                JSONData tmp = new JSONData(0.0);
return 0.0;
+
                Set(tmp);
}
+
                return 0.0;
set {
+
            }
JSONData tmp = new JSONData (value);
+
            set
Set (tmp);
+
            {
}
+
                JSONData tmp = new JSONData(value);
}
+
                Set(tmp);
 +
            }
 +
        }
  
public override bool AsBool
+
        public override bool AsBool
{
+
        {
get {
+
            get
JSONData tmp = new JSONData (false);
+
            {
Set (tmp);
+
                JSONData tmp = new JSONData(false);
return false;
+
                Set(tmp);
}
+
                return false;
set {
+
            }
JSONData tmp = new JSONData (value);
+
            set
Set (tmp);
+
            {
}
+
                JSONData tmp = new JSONData(value);
}
+
                Set(tmp);
 +
            }
 +
        }
  
public override JSONArray AsArray
+
        public override JSONArray AsArray
{
+
        {
get {
+
            get
JSONArray tmp = new JSONArray ();
+
            {
Set (tmp);
+
                JSONArray tmp = new JSONArray();
return tmp;
+
                Set(tmp);
}
+
                return tmp;
}
+
            }
 +
        }
  
public override JSONClass AsObject
+
        public override JSONClass AsObject
{
+
        {
get {
+
            get
JSONClass tmp = new JSONClass ();
+
            {
Set (tmp);
+
                JSONClass tmp = new JSONClass();
return tmp;
+
                Set(tmp);
}
+
                return tmp;
}
+
            }
}
+
        }
// End of JSONLazyCreator
+
    }
 +
    // End of JSONLazyCreator
  
public static class JSON
+
    public static class JSON
{
+
    {
public static JSONNode Parse (string aJSON)
+
        public static JSONNode Parse(string aJSON)
{
+
        {
return JSONNode.Parse (aJSON);
+
            return JSONNode.Parse(aJSON);
}
+
        }
}
+
    }
 
}
 
}
  

Revision as of 18:12, 2 December 2016


Contents

Description

SimpleJSON is an easy to use JSON parser and builder. It uses strong typed classes for the different JSONTypes. The parser / builder does not distinguish between different value types. Number, boolean and null will be treated like strings. This might cause problems when you need to build a JSON string that requires the actual types.

In short: The parser conforms to rfc4627, the generator does not.


I've updated (only) the source code embedded in the page, and it now appears to round-trip, although this isn't particularly well tested and it's a very naive implementation. Use .ToJSON(0) to use the round-trip version. -- Opless (talk) 22:39, 21 September 2014 (CEST)OPless

Usage

To use SimpleJSON in Unity you just have to copy the SimpleJSON.cs file into your projects "plugins" folder inside your assets folder.

If you want to use the compression feature when it comes to saving and loading you have to download the SharpZipLib assembly and place it next to the SimpleJSON.cs file. In addition you have to uncomment the define at the top of the SimpleJSON.cs file.

For language specific usage see below.

CSharp

Like most assemblies SimpleJSON is contained in its own namespace to avoid name collisions.

To use SimpleJSON in C# you have to add this line at the top of your script:

using SimpleJSON;

UnityScript (Unity's Javascript)

To use SimpleJSON in UnityScript you have to add this line at the top of your script:

import SimpleJSON;

For UnityScript it's vital to place the SimpleJSON.cs (and SharpZipLib if needed) into a higher compilation group than the UnityScript file that should use it. The usual place is the Plugins folder which should work in most cases.

Examples (C# / UnityScript)

This is the JSON string which will be used in this example:

{
    "version": "1.0",
    "data": {
        "sampleArray": [
            "string value",
            5,
            {
                "name": "sub object"
            }
        ]
    }
}


var N = JSON.Parse(the_JSON_string);
var versionString = N["version"].Value;        // versionString will be a string containing "1.0"
var versionNumber = N["version"].AsFloat;      // versionNumber will be a float containing 1.0
var name = N["data"]["sampleArray"][2]["name"];// name will be a string containing "sub object"
 
//C#
string val = N["data"]["sampleArray"][0];      // val contains "string value"
 
//UnityScript
var val : String = N["data"]["sampleArray"][0];// val contains "string value"
 
var i = N["data"]["sampleArray"][1].AsInt;     // i will be an integer containing 5
N["data"]["sampleArray"][1].AsInt = i+6;       // the second value in sampleArray will contain "11"
 
N["additional"]["second"]["name"] = "FooBar";  // this will create a new object named "additional" in this object create another
                                               //object "second" in this object add a string variable "name"
 
var mCount = N["countries"]["germany"]["moronCount"].AsInt; // this will return 0 and create all the required objects and
                                                            // initialize "moronCount" with 0.
 
if (N["wrong"] != null)                        // this won't execute the if-statement since "wrong" doesn't exist
{}
if (N["wrong"].AsInt == 0)                     // this will execute the if-statement and in addition add the "wrong" value.
{}
 
N["data"]["sampleArray"][-1] = "Test";         // this will add another string to the end of the array
N["data"]["sampleArray"][-1]["name"] = "FooBar"; // this will add another object to the end of the array which contains a string named "name"
 
N["data"] = "erased";                          // this will replace the object stored in data with the string "erased"


Download

Here's the whole thing packed as unityPackage and as seperate files including example / test scripts

Media:SimpleJSON.zip


SimpleJSON.cs

//#define USE_SharpZipLib
#if !UNITY_WEBPLAYER
#define USE_FileIO
#endif
/* * * * *
 * A simple JSON Parser / builder
 * ------------------------------
 * 
 * It mainly has been written as a simple JSON parser. It can build a JSON string
 * from the node-tree, or generate a node tree from any valid JSON string.
 * 
 * If you want to use compression when saving to file / stream / B64 you have to include
 * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and
 * define "USE_SharpZipLib" at the top of the file
 * 
 * Written by Bunny83 
 * 2012-06-09
 * 
 * Modified by oPless, 2014-09-21 to round-trip properly
 *
 * Features / attributes:
 * - provides strongly typed node classes and lists / dictionaries
 * - provides easy access to class members / array items / data values
 * - the parser ignores data types. Each value is a string.
 * - only double quotes (") are used for quoting strings.
 * - values and names are not restricted to quoted strings. They simply add up and are trimmed.
 * - There are only 3 types: arrays(JSONArray), objects(JSONClass) and values(JSONData)
 * - provides "casting" properties to easily convert to / from those types:
 *   int / float / double / bool
 * - provides a common interface for each node so no explicit casting is required.
 * - the parser try to avoid errors, but if malformed JSON is parsed the result is undefined
 * 
 * 
 * 2012-12-17 Update:
 * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree
 *   Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator
 *   The class determines the required type by it's further use, creates the type and removes itself.
 * - Added binary serialization / deserialization.
 * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ )
 *   The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top
 * - The serializer uses different types when it comes to store the values. Since my data values
 *   are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string.
 *   It's not the most efficient way but for a moderate amount of data it should work on all platforms.
 * 
 * * * * */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace SimpleJSON
{
    public enum JSONBinaryTag
    {
        Array = 1,
        Class = 2,
        Value = 3,
        IntValue = 4,
        DoubleValue = 5,
        BoolValue = 6,
        FloatValue = 7,
    }
 
    public abstract partial class JSONNode
    {
        #region common interface
 
        public virtual void Add(string aKey, JSONNode aItem)
        {
        }
 
        public virtual JSONNode this[int aIndex] { get { return null; } set { } }
 
        public virtual JSONNode this[string aKey] { get { return null; } set { } }
 
        public virtual string Value { get { return ""; } set { } }
 
        public virtual int Count { get { return 0; } }
 
        public virtual void Add(JSONNode aItem)
        {
            Add("", aItem);
        }
 
        public virtual JSONNode Remove(string aKey)
        {
            return null;
        }
 
        public virtual JSONNode Remove(int aIndex)
        {
            return null;
        }
 
        public virtual JSONNode Remove(JSONNode aNode)
        {
            return aNode;
        }
 
        public virtual IEnumerable<JSONNode> Children
        {
            get
            {
                yield break;
            }
        }
 
        public IEnumerable<JSONNode> DeepChildren
        {
            get
            {
                foreach (var C in Children)
                    foreach (var D in C.DeepChildren)
                        yield return D;
            }
        }
 
        public override string ToString()
        {
            return "JSONNode";
        }
 
        public virtual string ToString(string aPrefix)
        {
            return "JSONNode";
        }
 
        public abstract string ToJSON(int prefix);
 
        #endregion common interface
 
        #region typecasting properties
 
        public virtual JSONBinaryTag Tag { get; set; }
 
        public virtual int AsInt
        {
            get
            {
                int v = 0;
                if (int.TryParse(Value, out v))
                    return v;
                return 0;
            }
            set
            {
                Value = value.ToString();
                Tag = JSONBinaryTag.IntValue;
            }
        }
 
        public virtual float AsFloat
        {
            get
            {
                float v = 0.0f;
                if (float.TryParse(Value, out v))
                    return v;
                return 0.0f;
            }
            set
            {
                Value = value.ToString();
                Tag = JSONBinaryTag.FloatValue;
            }
        }
 
        public virtual double AsDouble
        {
            get
            {
                double v = 0.0;
                if (double.TryParse(Value, out v))
                    return v;
                return 0.0;
            }
            set
            {
                Value = value.ToString();
                Tag = JSONBinaryTag.DoubleValue;
 
            }
        }
 
        public virtual bool AsBool
        {
            get
            {
                bool v = false;
                if (bool.TryParse(Value, out v))
                    return v;
                return !string.IsNullOrEmpty(Value);
            }
            set
            {
                Value = (value) ? "true" : "false";
                Tag = JSONBinaryTag.BoolValue;
 
            }
        }
 
        public virtual JSONArray AsArray
        {
            get
            {
                return this as JSONArray;
            }
        }
 
        public virtual JSONClass AsObject
        {
            get
            {
                return this as JSONClass;
            }
        }
 
 
        #endregion typecasting properties
 
        #region operators
 
        public static implicit operator JSONNode(string s)
        {
            return new JSONData(s);
        }
 
        public static implicit operator string(JSONNode d)
        {
            return (d == null) ? null : d.Value;
        }
 
        public static bool operator ==(JSONNode a, object b)
        {
            if (b == null && a is JSONLazyCreator)
                return true;
            return System.Object.ReferenceEquals(a, b);
        }
 
        public static bool operator !=(JSONNode a, object b)
        {
            return !(a == b);
        }
 
        public override bool Equals(object obj)
        {
            return System.Object.ReferenceEquals(this, obj);
        }
 
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
 
        #endregion operators
 
        internal static string Escape(string aText)
        {
            string result = "";
            foreach (char c in aText)
            {
                switch (c)
                {
                    case '\\':
                        result += "\\\\";
                        break;
                    case '\"':
                        result += "\\\"";
                        break;
                    case '\n':
                        result += "\\n";
                        break;
                    case '\r':
                        result += "\\r";
                        break;
                    case '\t':
                        result += "\\t";
                        break;
                    case '\b':
                        result += "\\b";
                        break;
                    case '\f':
                        result += "\\f";
                        break;
                    default:
                        result += c;
                        break;
                }
            }
            return result;
        }
 
        static JSONData Numberize(string token)
        {
            bool flag = false;
            int integer = 0;
            double real = 0;
 
            if (int.TryParse(token, out integer))
            {
                return new JSONData(integer);
            }
 
            if (double.TryParse(token, out real))
            {
                return new JSONData(real);
            }
 
            if (bool.TryParse(token, out flag))
            {
                return new JSONData(flag);
            }
 
            throw new NotImplementedException(token);
        }
 
        static void AddElement(JSONNode ctx, string token, string tokenName, bool tokenIsString)
        {
            if (tokenIsString)
            {
                if (ctx is JSONArray)
                    ctx.Add(token);
                else
                    ctx.Add(tokenName, token); // assume dictionary/object
            }
            else
            {
                JSONData number = Numberize(token);
                if (ctx is JSONArray)
                    ctx.Add(number);
                else
                    ctx.Add(tokenName, number);
 
            }
        }
 
        public static JSONNode Parse(string aJSON)
        {
            Stack<JSONNode> stack = new Stack<JSONNode>();
            JSONNode ctx = null;
            int i = 0;
            StringBuilder Token = new StringBuilder();
            StringBuilder TokenName = new StringBuilder();
            bool QuoteMode = false;
            bool TokenIsString = false;
            while (i < aJSON.Length)
            {
                switch (aJSON[i])
                {
                    case '{':
                        if (QuoteMode)
                        {
                            Token.Append(aJSON[i]);
                            break;
                        }
                        stack.Push(new JSONClass());
                        if (ctx != null)
                        {
                            string tmpName = TokenName.ToString().Trim();
                            if (ctx is JSONArray)
                                ctx.Add(stack.Peek());
                            else if (tmpName != "")
                                ctx.Add(tmpName, stack.Peek());
                        }
                        TokenName.Length = 0;
                        Token.Length = 0;
                        ctx = stack.Peek();
                        break;
 
                    case '[':
                        if (QuoteMode)
                        {
                            Token.Append(aJSON[i]);
                            break;
                        }
 
                        stack.Push(new JSONArray());
                        if (ctx != null)
                        {
                            string tmpName = TokenName.ToString().Trim();
                            if (ctx is JSONArray)
                                ctx.Add(stack.Peek());
                            else if (tmpName != "")
                                ctx.Add(tmpName, stack.Peek());
                        }
                        TokenName.Length = 0;
                        Token.Length = 0;
                        ctx = stack.Peek();
                        break;
 
                    case '}':
                    case ']':
                        if (QuoteMode)
                        {
 
                            Token.Append(aJSON[i]);
                            break;
                        }
                        if (stack.Count == 0)
                            throw new Exception("JSON Parse: Too many closing brackets");
 
                        stack.Pop();
                        if (Token.Length > 0)
                        {
                            string tmpName = TokenName.ToString().Trim();
                            AddElement(ctx, Token.ToString(), TokenName.ToString(), TokenIsString);
                            TokenIsString = false;
                        }
                        TokenName.Length = 0;
                        Token.Length = 0;
                        if (stack.Count > 0)
                            ctx = stack.Peek();
                        break;
 
                    case ':':
                        if (QuoteMode)
                        {
                            Token.Append(aJSON[i]);
                            break;
                        }
                        TokenName.Length = 0;
                        TokenName.Append(Token);
                        Token.Length = 0;
                        TokenIsString = false;
                        break;
 
                    case '"':
                        QuoteMode ^= true;
                        TokenIsString = QuoteMode == true ? true : TokenIsString;
                        break;
 
                    case ',':
                        if (QuoteMode)
                        {
                            Token.Append(aJSON[i]);
                            break;
                        }
                        if (Token.Length > 0)
                        {
                            AddElement(ctx, Token.ToString(), TokenName.ToString(), TokenIsString);
                            TokenIsString = false;
                        }
                        TokenName.Length = 0;
                        Token.Length = 0;
                        TokenIsString = false;
                        break;
 
                    case '\r':
                    case '\n':
                        break;
 
                    case ' ':
                    case '\t':
                        if (QuoteMode)
                            Token.Append(aJSON[i]);
                        break;
 
                    case '\\':
                        ++i;
                        if (QuoteMode)
                        {
                            char C = aJSON[i];
                            switch (C)
                            {
                                case 't':
                                    Token.Append('\t');
                                    break;
                                case 'r':
                                    Token.Append('\r');
                                    break;
                                case 'n':
                                    Token.Append('\n');
                                    break;
                                case 'b':
                                    Token.Append('\b');
                                    break;
                                case 'f':
                                    Token.Append('\f');
                                    break;
                                case 'u':
                                    {
                                        string s = aJSON.Substring(i + 1, 4);
                                        Token.Append((char)int.Parse(
                                            s,
                                            System.Globalization.NumberStyles.AllowHexSpecifier));
                                        i += 4;
                                        break;
                                    }
                                default:
                                    Token.Append(C);
                                    break;
                            }
                        }
                        break;
 
                    default:
                        Token.Append(aJSON[i]);
                        break;
                }
                ++i;
            }
            if (QuoteMode)
            {
                throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
            }
            return ctx;
        }
 
        public virtual void Serialize(System.IO.BinaryWriter aWriter)
        {
        }
 
        public void SaveToStream(System.IO.Stream aData)
        {
            var W = new System.IO.BinaryWriter(aData);
            Serialize(W);
        }
 
#if USE_SharpZipLib
		public void SaveToCompressedStream(System.IO.Stream aData)
		{
			using (var gzipOut = new ICSharpCode.SharpZipLib.BZip2.BZip2OutputStream(aData))
			{
				gzipOut.IsStreamOwner = false;
				SaveToStream(gzipOut);
				gzipOut.Close();
			}
		}
 
		public void SaveToCompressedFile(string aFileName)
		{
 
#if USE_FileIO
			System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName);
			using(var F = System.IO.File.OpenWrite(aFileName))
			{
				SaveToCompressedStream(F);
			}
 
#else
			throw new Exception("Can't use File IO stuff in webplayer");
#endif
		}
		public string SaveToCompressedBase64()
		{
			using (var stream = new System.IO.MemoryStream())
			{
				SaveToCompressedStream(stream);
				stream.Position = 0;
				return System.Convert.ToBase64String(stream.ToArray());
			}
		}
 
#else
        public void SaveToCompressedStream(System.IO.Stream aData)
        {
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
        }
 
        public void SaveToCompressedFile(string aFileName)
        {
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
        }
 
        public string SaveToCompressedBase64()
        {
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
        }
#endif
 
        public void SaveToFile(string aFileName)
        {
#if USE_FileIO
            System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName);
            using (var F = System.IO.File.OpenWrite(aFileName))
            {
                SaveToStream(F);
            }
#else
			throw new Exception ("Can't use File IO stuff in webplayer");
#endif
        }
 
        public string SaveToBase64()
        {
            using (var stream = new System.IO.MemoryStream())
            {
                SaveToStream(stream);
                stream.Position = 0;
                return System.Convert.ToBase64String(stream.ToArray());
            }
        }
 
        public static JSONNode Deserialize(System.IO.BinaryReader aReader)
        {
            JSONBinaryTag type = (JSONBinaryTag)aReader.ReadByte();
            switch (type)
            {
                case JSONBinaryTag.Array:
                    {
                        int count = aReader.ReadInt32();
                        JSONArray tmp = new JSONArray();
                        for (int i = 0; i < count; i++)
                            tmp.Add(Deserialize(aReader));
                        return tmp;
                    }
                case JSONBinaryTag.Class:
                    {
                        int count = aReader.ReadInt32();
                        JSONClass tmp = new JSONClass();
                        for (int i = 0; i < count; i++)
                        {
                            string key = aReader.ReadString();
                            var val = Deserialize(aReader);
                            tmp.Add(key, val);
                        }
                        return tmp;
                    }
                case JSONBinaryTag.Value:
                    {
                        return new JSONData(aReader.ReadString());
                    }
                case JSONBinaryTag.IntValue:
                    {
                        return new JSONData(aReader.ReadInt32());
                    }
                case JSONBinaryTag.DoubleValue:
                    {
                        return new JSONData(aReader.ReadDouble());
                    }
                case JSONBinaryTag.BoolValue:
                    {
                        return new JSONData(aReader.ReadBoolean());
                    }
                case JSONBinaryTag.FloatValue:
                    {
                        return new JSONData(aReader.ReadSingle());
                    }
 
                default:
                    {
                        throw new Exception("Error deserializing JSON. Unknown tag: " + type);
                    }
            }
        }
 
#if USE_SharpZipLib
		public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
		{
			var zin = new ICSharpCode.SharpZipLib.BZip2.BZip2InputStream(aData);
			return LoadFromStream(zin);
		}
		public static JSONNode LoadFromCompressedFile(string aFileName)
		{
#if USE_FileIO
			using(var F = System.IO.File.OpenRead(aFileName))
			{
				return LoadFromCompressedStream(F);
			}
#else
			throw new Exception("Can't use File IO stuff in webplayer");
#endif
		}
		public static JSONNode LoadFromCompressedBase64(string aBase64)
		{
			var tmp = System.Convert.FromBase64String(aBase64);
			var stream = new System.IO.MemoryStream(tmp);
			stream.Position = 0;
			return LoadFromCompressedStream(stream);
		}
#else
        public static JSONNode LoadFromCompressedFile(string aFileName)
        {
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
        }
 
        public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
        {
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
        }
 
        public static JSONNode LoadFromCompressedBase64(string aBase64)
        {
            throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
        }
#endif
 
        public static JSONNode LoadFromStream(System.IO.Stream aData)
        {
            using (var R = new System.IO.BinaryReader(aData))
            {
                return Deserialize(R);
            }
        }
 
        public static JSONNode LoadFromFile(string aFileName)
        {
#if USE_FileIO
            using (var F = System.IO.File.OpenRead(aFileName))
            {
                return LoadFromStream(F);
            }
#else
			throw new Exception ("Can't use File IO stuff in webplayer");
#endif
        }
 
        public static JSONNode LoadFromBase64(string aBase64)
        {
            var tmp = System.Convert.FromBase64String(aBase64);
            var stream = new System.IO.MemoryStream(tmp);
            stream.Position = 0;
            return LoadFromStream(stream);
        }
    }
    // End of JSONNode
 
    public class JSONArray : JSONNode, IEnumerable
    {
        private List<JSONNode> m_List = new List<JSONNode>();
 
        public override JSONNode this[int aIndex]
        {
            get
            {
                if (aIndex < 0 || aIndex >= m_List.Count)
                    return new JSONLazyCreator(this);
                return m_List[aIndex];
            }
            set
            {
                if (aIndex < 0 || aIndex >= m_List.Count)
                    m_List.Add(value);
                else
                    m_List[aIndex] = value;
            }
        }
 
        public override JSONNode this[string aKey]
        {
            get { return new JSONLazyCreator(this); }
            set { m_List.Add(value); }
        }
 
        public override int Count
        {
            get { return m_List.Count; }
        }
 
 
        public override void Add(string aKey, JSONNode aItem)
        {
            m_List.Add(aItem);
        }
 
        public override JSONNode Remove(int aIndex)
        {
            if (aIndex < 0 || aIndex >= m_List.Count)
                return null;
            JSONNode tmp = m_List[aIndex];
            m_List.RemoveAt(aIndex);
            return tmp;
        }
 
        public override JSONNode Remove(JSONNode aNode)
        {
            m_List.Remove(aNode);
            return aNode;
        }
 
        public override IEnumerable<JSONNode> Children
        {
            get
            {
                foreach (JSONNode N in m_List)
                    yield return N;
            }
        }
 
        public IEnumerator GetEnumerator()
        {
            foreach (JSONNode N in m_List)
                yield return N;
        }
 
        public override string ToString()
        {
            string result = "[ ";
            foreach (JSONNode N in m_List)
            {
                if (result.Length > 2)
                    result += ", ";
                result += N.ToString();
            }
            result += " ]";
            return result;
        }
 
        public override string ToString(string aPrefix)
        {
            string result = "[ ";
            foreach (JSONNode N in m_List)
            {
                if (result.Length > 3)
                    result += ", ";
                result += "\n" + aPrefix + "   ";
                result += N.ToString(aPrefix + "   ");
            }
            result += "\n" + aPrefix + "]";
            return result;
        }
 
        public override string ToJSON(int prefix)
        {
            string s = new string(' ', (prefix + 1) * 2);
            string ret = "[ ";
            foreach (JSONNode n in m_List)
            {
                if (ret.Length > 3)
                    ret += ", ";
                ret += "\n" + s;
                ret += n.ToJSON(prefix + 1);
 
            }
            ret += "\n" + s + "]";
            return ret;
        }
 
        public override void Serialize(System.IO.BinaryWriter aWriter)
        {
            aWriter.Write((byte)JSONBinaryTag.Array);
            aWriter.Write(m_List.Count);
            for (int i = 0; i < m_List.Count; i++)
            {
                m_List[i].Serialize(aWriter);
            }
        }
    }
    // End of JSONArray
 
    public class JSONClass : JSONNode, IEnumerable
    {
        private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();
 
        public override JSONNode this[string aKey]
        {
            get
            {
                if (m_Dict.ContainsKey(aKey))
                    return m_Dict[aKey];
                else
                    return new JSONLazyCreator(this, aKey);
            }
            set
            {
                if (m_Dict.ContainsKey(aKey))
                    m_Dict[aKey] = value;
                else
                    m_Dict.Add(aKey, value);
            }
        }
 
        public override JSONNode this[int aIndex]
        {
            get
            {
                if (aIndex < 0 || aIndex >= m_Dict.Count)
                    return null;
                return m_Dict.ElementAt(aIndex).Value;
            }
            set
            {
                if (aIndex < 0 || aIndex >= m_Dict.Count)
                    return;
                string key = m_Dict.ElementAt(aIndex).Key;
                m_Dict[key] = value;
            }
        }
 
        public override int Count
        {
            get { return m_Dict.Count; }
        }
 
        public override void Add(string aKey, JSONNode aItem)
        {
            if (!string.IsNullOrEmpty(aKey))
            {
                if (m_Dict.ContainsKey(aKey))
                    m_Dict[aKey] = aItem;
                else
                    m_Dict.Add(aKey, aItem);
            }
            else
                m_Dict.Add(Guid.NewGuid().ToString(), aItem);
        }
 
        public override JSONNode Remove(string aKey)
        {
            if (!m_Dict.ContainsKey(aKey))
                return null;
            JSONNode tmp = m_Dict[aKey];
            m_Dict.Remove(aKey);
            return tmp;
        }
 
        public override JSONNode Remove(int aIndex)
        {
            if (aIndex < 0 || aIndex >= m_Dict.Count)
                return null;
            var item = m_Dict.ElementAt(aIndex);
            m_Dict.Remove(item.Key);
            return item.Value;
        }
 
        public override JSONNode Remove(JSONNode aNode)
        {
            try
            {
                var item = m_Dict.Where(k => k.Value == aNode).First();
                m_Dict.Remove(item.Key);
                return aNode;
            }
            catch
            {
                return null;
            }
        }
 
        public override IEnumerable<JSONNode> Children
        {
            get
            {
                foreach (KeyValuePair<string, JSONNode> N in m_Dict)
                    yield return N.Value;
            }
        }
 
        public IEnumerator GetEnumerator()
        {
            foreach (KeyValuePair<string, JSONNode> N in m_Dict)
                yield return N;
        }
 
        public override string ToString()
        {
            string result = "{";
            foreach (KeyValuePair<string, JSONNode> N in m_Dict)
            {
                if (result.Length > 2)
                    result += ", ";
                result += "\"" + Escape(N.Key) + "\":" + N.Value.ToString();
            }
            result += "}";
            return result;
        }
 
        public override string ToString(string aPrefix)
        {
            string result = "{ ";
            foreach (KeyValuePair<string, JSONNode> N in m_Dict)
            {
                if (result.Length > 3)
                    result += ", ";
                result += "\n" + aPrefix + "   ";
                result += "\"" + Escape(N.Key) + "\" : " + N.Value.ToString(aPrefix + "   ");
            }
            result += "\n" + aPrefix + "}";
            return result;
        }
 
        public override string ToJSON(int prefix)
        {
            string s = new string(' ', (prefix + 1) * 2);
            string ret = "{ ";
            foreach (KeyValuePair<string, JSONNode> n in m_Dict)
            {
                if (ret.Length > 3)
                    ret += ", ";
                ret += "\n" + s;
                ret += string.Format("\"{0}\": {1}", n.Key, n.Value.ToJSON(prefix + 1));
            }
            ret += "\n" + s + "}";
            return ret;
        }
 
        public override void Serialize(System.IO.BinaryWriter aWriter)
        {
            aWriter.Write((byte)JSONBinaryTag.Class);
            aWriter.Write(m_Dict.Count);
            foreach (string K in m_Dict.Keys)
            {
                aWriter.Write(K);
                m_Dict[K].Serialize(aWriter);
            }
        }
    }
    // End of JSONClass
 
    public class JSONData : JSONNode
    {
        private string m_Data;
 
 
        public override string Value
        {
            get { return m_Data; }
            set
            {
                m_Data = value;
                Tag = JSONBinaryTag.Value;
            }
        }
 
        public JSONData(string aData)
        {
            m_Data = aData;
            Tag = JSONBinaryTag.Value;
        }
 
        public JSONData(float aData)
        {
            AsFloat = aData;
        }
 
        public JSONData(double aData)
        {
            AsDouble = aData;
        }
 
        public JSONData(bool aData)
        {
            AsBool = aData;
        }
 
        public JSONData(int aData)
        {
            AsInt = aData;
        }
 
        public override string ToString()
        {
            return "\"" + Escape(m_Data) + "\"";
        }
 
        public override string ToString(string aPrefix)
        {
            return "\"" + Escape(m_Data) + "\"";
        }
 
        public override string ToJSON(int prefix)
        {
            switch (Tag)
            {
                case JSONBinaryTag.DoubleValue:
                case JSONBinaryTag.FloatValue:
                case JSONBinaryTag.IntValue:
                    return m_Data;
                case JSONBinaryTag.Value:
                    return string.Format("\"{0}\"", Escape(m_Data));
                default:
                    throw new NotSupportedException("This shouldn't be here: " + Tag.ToString());
            }
        }
 
        public override void Serialize(System.IO.BinaryWriter aWriter)
        {
            var tmp = new JSONData("");
 
            tmp.AsInt = AsInt;
            if (tmp.m_Data == this.m_Data)
            {
                aWriter.Write((byte)JSONBinaryTag.IntValue);
                aWriter.Write(AsInt);
                return;
            }
            tmp.AsFloat = AsFloat;
            if (tmp.m_Data == this.m_Data)
            {
                aWriter.Write((byte)JSONBinaryTag.FloatValue);
                aWriter.Write(AsFloat);
                return;
            }
            tmp.AsDouble = AsDouble;
            if (tmp.m_Data == this.m_Data)
            {
                aWriter.Write((byte)JSONBinaryTag.DoubleValue);
                aWriter.Write(AsDouble);
                return;
            }
 
            tmp.AsBool = AsBool;
            if (tmp.m_Data == this.m_Data)
            {
                aWriter.Write((byte)JSONBinaryTag.BoolValue);
                aWriter.Write(AsBool);
                return;
            }
            aWriter.Write((byte)JSONBinaryTag.Value);
            aWriter.Write(m_Data);
        }
    }
    // End of JSONData
 
    internal class JSONLazyCreator : JSONNode
    {
        private JSONNode m_Node = null;
        private string m_Key = null;
 
        public JSONLazyCreator(JSONNode aNode)
        {
            m_Node = aNode;
            m_Key = null;
        }
 
        public JSONLazyCreator(JSONNode aNode, string aKey)
        {
            m_Node = aNode;
            m_Key = aKey;
        }
 
        private void Set(JSONNode aVal)
        {
            if (m_Key == null)
            {
                m_Node.Add(aVal);
            }
            else
            {
                m_Node.Add(m_Key, aVal);
            }
            m_Node = null; // Be GC friendly.
        }
 
        public override JSONNode this[int aIndex]
        {
            get
            {
                return new JSONLazyCreator(this);
            }
            set
            {
                var tmp = new JSONArray();
                tmp.Add(value);
                Set(tmp);
            }
        }
 
        public override JSONNode this[string aKey]
        {
            get
            {
                return new JSONLazyCreator(this, aKey);
            }
            set
            {
                var tmp = new JSONClass();
                tmp.Add(aKey, value);
                Set(tmp);
            }
        }
 
        public override void Add(JSONNode aItem)
        {
            var tmp = new JSONArray();
            tmp.Add(aItem);
            Set(tmp);
        }
 
        public override void Add(string aKey, JSONNode aItem)
        {
            var tmp = new JSONClass();
            tmp.Add(aKey, aItem);
            Set(tmp);
        }
 
        public static bool operator ==(JSONLazyCreator a, object b)
        {
            if (b == null)
                return true;
            return System.Object.ReferenceEquals(a, b);
        }
 
        public static bool operator !=(JSONLazyCreator a, object b)
        {
            return !(a == b);
        }
 
        public override bool Equals(object obj)
        {
            if (obj == null)
                return true;
            return System.Object.ReferenceEquals(this, obj);
        }
 
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
 
        public override string ToString()
        {
            return "";
        }
 
        public override string ToString(string aPrefix)
        {
            return "";
        }
 
        public override string ToJSON(int prefix)
        {
            return "";
        }
 
        public override int AsInt
        {
            get
            {
                JSONData tmp = new JSONData(0);
                Set(tmp);
                return 0;
            }
            set
            {
                JSONData tmp = new JSONData(value);
                Set(tmp);
            }
        }
 
        public override float AsFloat
        {
            get
            {
                JSONData tmp = new JSONData(0.0f);
                Set(tmp);
                return 0.0f;
            }
            set
            {
                JSONData tmp = new JSONData(value);
                Set(tmp);
            }
        }
 
        public override double AsDouble
        {
            get
            {
                JSONData tmp = new JSONData(0.0);
                Set(tmp);
                return 0.0;
            }
            set
            {
                JSONData tmp = new JSONData(value);
                Set(tmp);
            }
        }
 
        public override bool AsBool
        {
            get
            {
                JSONData tmp = new JSONData(false);
                Set(tmp);
                return false;
            }
            set
            {
                JSONData tmp = new JSONData(value);
                Set(tmp);
            }
        }
 
        public override JSONArray AsArray
        {
            get
            {
                JSONArray tmp = new JSONArray();
                Set(tmp);
                return tmp;
            }
        }
 
        public override JSONClass AsObject
        {
            get
            {
                JSONClass tmp = new JSONClass();
                Set(tmp);
                return tmp;
            }
        }
    }
    // End of JSONLazyCreator
 
    public static class JSON
    {
        public static JSONNode Parse(string aJSON)
        {
            return JSONNode.Parse(aJSON);
        }
    }
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox