Last active
October 16, 2016 06:33
-
-
Save subnomo/39dfb75f33807250bcb5 to your computer and use it in GitHub Desktop.
SimpleJSON from http://wiki.unity3d.com/index.php/SimpleJSON with added support for long datatype
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#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 | |
* | |
* Modified by subnomo, 2016-02-14 to add long datatype | |
* | |
* 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; | |
namespace SimpleJSON { | |
public enum JSONBinaryTag { | |
Array = 1, | |
Class = 2, | |
Value = 3, | |
IntValue = 4, | |
DoubleValue = 5, | |
BoolValue = 6, | |
FloatValue = 7, | |
LongValue = 8, | |
} | |
public abstract 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 long AsLong | |
{ | |
get | |
{ | |
long v = 0L; | |
if (long.TryParse(Value, out v)) | |
return v; | |
return 0L; | |
} | |
set | |
{ | |
Value = value.ToString(); | |
Tag = JSONBinaryTag.LongValue; | |
} | |
} | |
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; | |
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 '[': | |
if (QuoteMode) { | |
Token += aJSON[i]; | |
break; | |
} | |
stack.Push(new JSONArray()); | |
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 '}': | |
case ']': | |
if (QuoteMode) { | |
Token += aJSON[i]; | |
break; | |
} | |
if (stack.Count == 0) | |
throw new Exception("JSON Parse: Too many closing brackets"); | |
stack.Pop(); | |
if (Token != "") { | |
TokenName = TokenName.Trim(); | |
/* | |
if (ctx is JSONArray) | |
ctx.Add (Token); | |
else if (TokenName != "") | |
ctx.Add (TokenName, Token); | |
*/ | |
AddElement(ctx, Token, TokenName, TokenIsString); | |
TokenIsString = false; | |
} | |
TokenName = ""; | |
Token = ""; | |
if (stack.Count > 0) | |
ctx = stack.Peek(); | |
break; | |
case ':': | |
if (QuoteMode) { | |
Token += aJSON[i]; | |
break; | |
} | |
TokenName = Token; | |
Token = ""; | |
TokenIsString = false; | |
break; | |
case '"': | |
QuoteMode ^= true; | |
TokenIsString = QuoteMode == true ? true : TokenIsString; | |
break; | |
case ',': | |
if (QuoteMode) { | |
Token += aJSON[i]; | |
break; | |
} | |
if (Token != "") { | |
/* | |
if (ctx is JSONArray) { | |
ctx.Add (Token); | |
} else if (TokenName != "") { | |
ctx.Add (TokenName, Token); | |
} | |
*/ | |
AddElement(ctx, Token, TokenName, TokenIsString); | |
TokenIsString = false; | |
} | |
TokenName = ""; | |
Token = ""; | |
TokenIsString = false; | |
break; | |
case '\r': | |
case '\n': | |
break; | |
case ' ': | |
case '\t': | |
if (QuoteMode) | |
Token += aJSON[i]; | |
break; | |
case '\\': | |
++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: | |
Token += 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.LongValue: { | |
return new JSONData(aReader.ReadInt64()); | |
} | |
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(long aData) { | |
AsLong = 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.LongValue: | |
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.AsLong = AsLong; | |
if (tmp.m_Data == this.m_Data) { | |
aWriter.Write((byte)JSONBinaryTag.LongValue); | |
aWriter.Write(AsFloat); | |
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 long AsLong | |
{ | |
get | |
{ | |
JSONData tmp = new JSONData(0L); | |
Set(tmp); | |
return 0L; | |
} | |
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); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment