The usage is fairly simply. Some examples:
Variant v = Variant.NewObject();
v.Add("func", "someString");
v["arg"] = 1.2345f;
Variant v2 = Variant.NewArray();
v2.Add(12345);
v2.Add(false);
foreach (Variant x in v2) {
Console.Out.WriteLine( x.PrettyPrint() );
}
v.Add("someArray", v2);
Console.Out.WriteLine(v);
Variant v3 = Variant.Parse("{\"xyz\":0.981f}");
Console.Out.WriteLine(v3["xyz"]);
File: Variant.cs
#region License
// Copyright (c) 2014 Moritz Molch <mail@moritzmolch.com>
//
// Permission is hereby granted to do with this file whatever
// you want to with the only exception that this copyright
// and permission notice shall never be altered or removed.
#endregion
using System.Collections.Generic;
using System.Collections;
namespace MoritzMolch.Json
{
public class Variant : IEnumerable {
protected Types m_type = Types.Null;
protected string m_string;
protected int m_int;
protected float m_float;
protected bool m_bool;
protected List<Variant> m_array;
protected Dictionary<string, Variant> m_object;
protected enum Types {
String,
Int,
Float,
Bool,
Array,
Object,
Null,
Error
}
#region IEnumerable implementation
public IEnumerator GetEnumerator()
{
switch (m_type) {
case Types.Array:
return m_array.GetEnumerator();
case Types.Object:
return m_object.GetEnumerator();
default:
return new IEnumeratorClass(this) as IEnumerator;
}
}
#endregion
#region IEnumerator implementation
protected class IEnumeratorClass : IEnumerator
{
Variant value;
bool hasNext;
public IEnumeratorClass( Variant value )
{
this.value = value;
hasNext = true;
}
public bool MoveNext() { return hasNext; }
public void Reset() { hasNext = true; }
public object Current { get { hasNext = false; return value; } }
}
#endregion
public static Variant NewError( string message = "An error occurred" )
{
Variant outp = new Variant();
outp.m_type = Types.Error;
outp.m_string = message;
return outp;
}
public bool isError
{
get {
return (m_type == Types.Error);
}
}
public static Variant NewObject()
{
Variant outp = new Variant();
outp.m_type = Types.Object;
outp.m_object = new Dictionary<string, Variant>();
return outp;
}
public static Variant NewArray()
{
Variant outp = new Variant();
outp.m_type = Types.Array;
outp.m_array = new List<Variant>();
return outp;
}
public Dictionary<string, Variant> Add(string key, Variant value)
{
if (m_type != Types.Object)
return null;
m_object.Add(key, value);
return m_object;
}
public List<Variant> Add(Variant value)
{
if (m_type != Types.Array)
return null;
m_array.Add(value);
return m_array;
}
public Variant this[string key]
{
get {
if (m_type != Types.Object)
return null;
return m_object[key];
}
set {
if (m_type != Types.Object)
return;
m_object[key] = value;
}
}
public int Count
{
get {
if (m_type == Types.Array)
return m_array.Count;
if (m_type == Types.Object)
return m_object.Count;
return 1;
}
}
public Variant this[int num]
{
get {
if (m_type == Types.Array)
return m_array[num];
return this;
}
}
public static implicit operator Variant(string value)
{
Variant outp = new Variant();
outp.m_type = Types.String;
outp.m_string = value;
return outp;
}
public static implicit operator string(Variant value)
{
switch (value.m_type) {
case Types.String:
return value.m_string;
case Types.Int:
return value.m_int.ToString();
case Types.Float:
return value.m_float.ToString();
case Types.Bool:
if (value.m_bool) return "true";
else return "false";
case Types.Array:
return value.ToString();
case Types.Object:
return value.ToString();
case Types.Error:
return value.m_string;
}
return default(string);
}
public static implicit operator Variant(int value)
{
Variant outp = new Variant();
outp.m_type = Types.Int;
outp.m_int = value;
return outp;
}
public static implicit operator int(Variant value)
{
switch (value.m_type) {
case Types.String:
return int.Parse(value.m_string);
case Types.Int:
return value.m_int;
case Types.Float:
return (int)value.m_float;
case Types.Bool:
if (value.m_bool) return 0;
else return 1;
}
return default(int);
}
public static implicit operator Variant(float value)
{
Variant outp = new Variant();
outp.m_type = Types.Float;
outp.m_float = value;
return outp;
}
public static implicit operator float(Variant value)
{
switch (value.m_type) {
case Types.String:
return float.Parse(value.m_string);
case Types.Int:
return (float)value.m_int;
case Types.Float:
return value.m_float;
case Types.Bool:
if (value.m_bool) return 0f;
else return 1f;
}
return default(float);
}
public static implicit operator Variant(bool value)
{
Variant outp = new Variant();
outp.m_type = Types.Bool;
outp.m_bool = value;
return outp;
}
public static implicit operator bool(Variant value)
{
switch (value.m_type) {
case Types.String:
return bool.Parse(value.m_string);
case Types.Int:
return (value.m_int == 0);
case Types.Float:
return (value.m_float == 0f);
case Types.Bool:
return value.m_bool;
}
return default(bool);
}
public static implicit operator Variant(List<Variant> value)
{
Variant outp = new Variant();
outp.m_type = Types.Array;
outp.m_array = value;
return outp;
}
public static implicit operator List<Variant>(Variant value)
{
return value.m_array;
}
public static implicit operator Variant(Variant[] value)
{
Variant outp = new Variant();
outp.m_array = new List<Variant>();
outp.m_type = Types.Array;
foreach (Variant v in value) {
outp.m_array.Add(v);
}
return outp;
}
public static implicit operator Variant[](Variant value)
{
return value.m_array.ToArray();
}
public static implicit operator Variant(Dictionary<string, Variant> value)
{
Variant outp = new Variant();
outp.m_type = Types.Object;
outp.m_object = value;
return outp;
}
public static implicit operator Dictionary<string, Variant>(Variant value)
{
return value.m_object;
}
public override string ToString()
{
switch (m_type) {
case Types.Array: {
string outp = "[";
int i = m_array.Count;
foreach (Variant vari in m_array) {
i--;
if (vari.m_type == Types.String)
outp += "\""+vari.ToString()+"\"";
else
outp += vari.ToString();
if (i > 0) outp += ",";
}
outp += "]";
return outp;
}
case Types.Object: {
string outp = "{";
int i = m_object.Count;
foreach(KeyValuePair<string, Variant> entry in m_object) {
i--;
if (entry.Value.m_type == Types.String)
outp += "\""+entry.Key+"\":\""+entry.Value.ToString()+"\"";
else
outp += "\""+entry.Key+"\":"+entry.Value.ToString();
if (i > 0) outp += ",";
}
outp += "}";
return outp;
}
default:
return this;
}
}
public string PrettyPrint(int depth = 0)
{
switch (m_type) {
case Types.Array: {
string outp = "[\n";
int i = m_array.Count;
foreach (Variant vari in m_array) {
i--;
for (int d=0; d<=depth; d++) outp += "\t";
if (vari.m_type == Types.String)
outp += "\""+vari.PrettyPrint(depth+1)+"\"";
else
outp += vari.PrettyPrint(depth+1);
if (i > 0) outp += ",\n";
}
outp += "\n";
for (int d=0; d<depth; d++) outp += "\t";
outp += "]";
return outp;
}
case Types.Object: {
string outp = "{\n";
int i = m_object.Count;
foreach(KeyValuePair<string, Variant> entry in m_object) {
i--;
for (int d=0; d<=depth; d++) outp += "\t";
if (entry.Value.m_type == Types.String)
outp += "\""+entry.Key+"\" : \""+entry.Value.PrettyPrint(depth+1)+"\"";
else
outp += "\""+entry.Key+"\" : "+entry.Value.PrettyPrint(depth+1);
if (i > 0) outp += ",\n";
}
outp += "\n";
for (int d=0; d<depth; d++) outp += "\t";
outp += "}";
return outp;
}
default:
return this;
}
}
public static Variant Parse(string json)
{
json = json.Trim();
if ((json[0] == '"') && (json[json.Length - 1] == '"')) {
return json.Substring(1, json.Length - 2);
}
if ((json[0] == '{') && (json[json.Length - 1] == '}')) {
Variant outp = new Dictionary<string, Variant>();
Stack<char> currElem = new Stack<char>();
int lastParsePos = 0;
int currPos = 0;
bool omitNext = false;
Variant key = null;
foreach (char c in json) {
if (omitNext) {
currPos++;
omitNext = false;
continue;
}
switch (c) {
case '{':
currElem.Push('{');
break;
case '}':
if (currElem.Count == 1) {
outp.Add(key, Variant.Parse(json.Substring(lastParsePos + 1, currPos - lastParsePos - 1)));
lastParsePos = currPos;
}
currElem.Pop();
break;
case '[':
currElem.Push('[');
break;
case ']':
currElem.Pop();
break;
case ',':
if (currElem.Count == 1) {
outp.Add(key, Variant.Parse(json.Substring(lastParsePos + 1, currPos - lastParsePos - 1)));
lastParsePos = currPos;
}
break;
case ':':
if (currElem.Count == 1) {
key = Variant.Parse(json.Substring(lastParsePos + 1, currPos - lastParsePos - 1));
lastParsePos = currPos;
}
break;
case '"':
if (currElem.Peek() == '"') {
currElem.Pop();
} else {
currElem.Push('"');
}
break;
case '\\':
if (currElem.Peek() == '"') {
omitNext = true;
}
break;
}
currPos++;
}
return outp;
}
if ((json[0] == '[') && (json[json.Length - 1] == ']')) {
Variant outp = new List<Variant>();
Stack<char> currElem = new Stack<char>();
int lastParsePos = 0;
int currPos = 0;
bool omitNext = false;
foreach (char c in json) {
if (omitNext) {
currPos++;
omitNext = false;
continue;
}
switch (c) {
case '[':
currElem.Push('[');
break;
case ']':
if (currElem.Count == 1) {
outp.Add(Variant.Parse(json.Substring(lastParsePos + 1, currPos - lastParsePos - 1)));
lastParsePos = currPos;
}
currElem.Pop();
break;
case '{':
currElem.Push('{');
break;
case '}':
currElem.Pop();
break;
case ',':
if (currElem.Count == 1) {
outp.Add(Variant.Parse(json.Substring(lastParsePos + 1, currPos - lastParsePos - 1)));
lastParsePos = currPos;
}
break;
case '"':
if (currElem.Peek() == '"') {
currElem.Pop();
} else {
currElem.Push('"');
}
break;
case '\\':
if (currElem.Peek() == '"') {
omitNext = true;
}
break;
}
currPos++;
}
return outp;
}
{
int x;
if (int.TryParse(json, out x))
return x;
}
{
float x;
if (float.TryParse(json, out x))
return x;
}
{
bool x;
if (bool.TryParse(json, out x))
return x;
}
return null;
}
}
} // namespace MoritzMolch.Json