Last active
August 29, 2015 14:02
-
-
Save lunasorcery/aff9eb05b7bcd453aedd to your computer and use it in GitHub Desktop.
This file contains hidden or 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
using System; | |
using System.CodeDom; | |
using System.CodeDom.Compiler; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Web.Script.Serialization; | |
namespace Json | |
{ | |
public enum JsonObjectType | |
{ | |
Array, | |
Boolean, | |
Dict, | |
Integer, | |
Real, | |
String | |
} | |
public class JsonObject | |
{ | |
private const string k_warningIntegerTruncation = "Warning: this value is too large for an Int32 and will be truncated.\nConsider using a larger data-type.\nSuppress this warning by disabling JsonObject.ShowWarnings."; | |
public static bool ShowWarnings = true; | |
private JsonObjectType m_type = 0; | |
private JsonObject[] m_dataArray = null; | |
private bool m_dataBool = false; | |
private Dictionary<string, JsonObject> m_dataDict = null; | |
private long /* yaay, Dictionary */ m_dataInteger = 0; | |
private decimal /* screwing with my */ m_dataReal = 0; | |
private string /* lovely alignment */ m_dataString = null; | |
public static JsonObject CreateFromString(string s) | |
{ | |
JavaScriptSerializer js = new JavaScriptSerializer(); | |
js.MaxJsonLength = s.Length; | |
object bufferObj; | |
try | |
{ | |
bufferObj = js.DeserializeObject(s); | |
} | |
catch (ArgumentException ex) | |
{ | |
throw ex; | |
} | |
return Create(bufferObj); | |
} | |
public JsonObject(JsonObject[] p_value) | |
{ | |
m_type = JsonObjectType.Array; | |
m_dataArray = p_value; | |
} | |
public JsonObject(bool p_value) | |
{ | |
m_type = JsonObjectType.Boolean; | |
m_dataBool = p_value; | |
} | |
public JsonObject(Dictionary<string,JsonObject> p_value) | |
{ | |
m_type = JsonObjectType.Dict; | |
m_dataDict= p_value; | |
} | |
public JsonObject(long p_value) | |
{ | |
m_type = JsonObjectType.Integer; | |
m_dataInteger = p_value; | |
} | |
public JsonObject(decimal p_value) | |
{ | |
m_type = JsonObjectType.Real; | |
m_dataReal = p_value; | |
} | |
public JsonObject(double p_value) | |
{ | |
m_type = JsonObjectType.Real; | |
m_dataReal = (decimal)p_value; | |
} | |
public JsonObject(string p_value) | |
{ | |
m_type = JsonObjectType.String; | |
m_dataString = p_value; | |
} | |
private static JsonObject Create(object p_baseObject) | |
{ | |
if (p_baseObject is object[]) | |
{ | |
object[] srcArray = p_baseObject as object[]; | |
JsonObject[] dstArray = new JsonObject[srcArray.Length]; | |
for (int i = 0; i < dstArray.Length; ++i) | |
{ | |
dstArray[i] = Create(srcArray[i]); | |
} | |
return new JsonObject(dstArray); | |
} | |
else if (p_baseObject is Dictionary<string, object>) | |
{ | |
Dictionary<string, object> srcDict = p_baseObject as Dictionary<string, object>; | |
Dictionary<string, JsonObject> dstDict = new Dictionary<string, JsonObject>(); | |
foreach (string key in srcDict.Keys) | |
{ | |
dstDict[key] = Create(srcDict[key]); | |
} | |
return new JsonObject(dstDict); | |
} | |
else if (p_baseObject is bool) | |
{ | |
return new JsonObject((bool)p_baseObject); | |
} | |
else if (p_baseObject is int) | |
{ | |
return new JsonObject((int)p_baseObject); | |
} | |
else if (p_baseObject is long) | |
{ | |
return new JsonObject((long)p_baseObject); | |
} | |
else if (p_baseObject is decimal) | |
{ | |
return new JsonObject((decimal)p_baseObject); | |
} | |
else if (p_baseObject is string) | |
{ | |
return new JsonObject((string)p_baseObject); | |
} | |
else | |
{ | |
throw new Exception(string.Format( | |
"Unexpected type {0}!", | |
p_baseObject.GetType().FullName | |
)); | |
} | |
} | |
public JsonObjectType Type | |
{ | |
get { return m_type; } | |
} | |
public JsonObject[] Array | |
{ | |
get | |
{ | |
AssertType(JsonObjectType.Array); | |
return m_dataArray; | |
} | |
} | |
public bool Bool | |
{ | |
get | |
{ | |
AssertType(JsonObjectType.Boolean); | |
return m_dataBool; | |
} | |
} | |
public Dictionary<string,JsonObject> Dict | |
{ | |
get | |
{ | |
AssertType(JsonObjectType.Dict); | |
return m_dataDict; | |
} | |
} | |
public long Integer | |
{ | |
get | |
{ | |
AssertType(JsonObjectType.Integer); | |
return m_dataInteger; | |
} | |
} | |
public decimal Real | |
{ | |
get | |
{ | |
AssertType(JsonObjectType.Real); | |
return m_dataReal; | |
} | |
} | |
public string String | |
{ | |
get | |
{ | |
AssertType(JsonObjectType.String); | |
return m_dataString; | |
} | |
} | |
public static implicit operator JsonObject[](JsonObject p_object) | |
{ | |
return p_object.Array; | |
} | |
public static implicit operator bool(JsonObject p_object) | |
{ | |
return p_object.Bool; | |
} | |
public static implicit operator Dictionary<string,JsonObject>(JsonObject p_object) | |
{ | |
return p_object.Dict; | |
} | |
public static implicit operator int(JsonObject p_object) | |
{ | |
long value = p_object.Integer; | |
if (ShowWarnings && value > Int32.MaxValue) | |
{ | |
throw new Exception(k_warningIntegerTruncation); | |
} | |
return (int)value; | |
} | |
public static implicit operator long(JsonObject p_object) | |
{ | |
return p_object.Integer; | |
} | |
public static implicit operator decimal(JsonObject p_object) | |
{ | |
return p_object.Real; | |
} | |
public static implicit operator double(JsonObject p_object) | |
{ | |
return (double)p_object.Real; | |
} | |
public static implicit operator float(JsonObject p_object) | |
{ | |
return (float)p_object.Real; | |
} | |
public static implicit operator string(JsonObject p_object) | |
{ | |
return p_object.String; | |
} | |
private void AssertType(JsonObjectType p_type) | |
{ | |
if (m_type != p_type) | |
{ | |
throw new Exception(string.Format( | |
"JsonObject is of type '{0}', need type '{1}'", | |
m_type, | |
p_type | |
)); | |
} | |
} | |
public JsonObject this[int p_index] | |
{ | |
get | |
{ | |
AssertType(JsonObjectType.Array); | |
return m_dataArray[p_index]; | |
} | |
} | |
public JsonObject this[string p_key] | |
{ | |
get | |
{ | |
AssertType(JsonObjectType.Dict); | |
return m_dataDict[p_key]; | |
} | |
} | |
private static string ToLiteral(string p_input) | |
{ | |
using (var writer = new StringWriter()) | |
{ | |
using (var provider = CodeDomProvider.CreateProvider("CSharp")) | |
{ | |
provider.GenerateCodeFromExpression( | |
new CodePrimitiveExpression(p_input), | |
writer, | |
null | |
); | |
} | |
return writer.ToString(); | |
} | |
} | |
public override string ToString() | |
{ | |
switch (m_type) | |
{ | |
case JsonObjectType.Array: | |
{ | |
List<string> buffer = new List<string>(m_dataArray.Length); | |
foreach (var item in m_dataArray) | |
{ | |
buffer.Add(item.ToString()); | |
} | |
return string.Format( | |
"[{0}]", | |
string.Join(",", buffer) | |
); | |
} | |
case JsonObjectType.Boolean: | |
{ | |
return m_dataBool.ToString().ToLower(); | |
} | |
case JsonObjectType.Dict: | |
{ | |
List<string> buffer = new List<string>(m_dataDict.Count); | |
foreach (var kvp in m_dataDict) | |
{ | |
buffer.Add(string.Format( | |
"{0}:{1}", | |
ToLiteral(kvp.Key), | |
kvp.Value.ToString() | |
)); | |
} | |
return string.Format( | |
"{{{0}}}", | |
string.Join(",", buffer) | |
); | |
} | |
case JsonObjectType.Integer: | |
{ | |
return m_dataInteger.ToString(); | |
} | |
case JsonObjectType.Real: | |
{ | |
return m_dataReal.ToString(); | |
} | |
case JsonObjectType.String: | |
{ | |
return ToLiteral(m_dataString); | |
} | |
default: | |
{ | |
return ""; | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment