Skip to content

Instantly share code, notes, and snippets.

@lunasorcery
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lunasorcery/aff9eb05b7bcd453aedd to your computer and use it in GitHub Desktop.
Save lunasorcery/aff9eb05b7bcd453aedd to your computer and use it in GitHub Desktop.
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