#region Header /** * JsonData.cs * Generic type to hold JSON data (objects, arrays, and so on). This is * the default type returned by JsonMapper.ToObject(). * * The authors disclaim copyright to this source code. For more details, see * the COPYING file included with this distribution. **/ #endregion using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; namespace LitJson { public class JsonData : IJsonWrapper, IEquatable { #region Fields private IList inst_array; private bool inst_boolean; private double inst_double; private int inst_int; private long inst_long; private IDictionary inst_object; private string inst_string; private string json; private JsonType type; // Used to implement the IOrderedDictionary interface private IList> object_list; #endregion #region Properties public int Count { get { return EnsureCollection().Count; } } public bool IsArray { get { return type == JsonType.Array; } } public bool IsBoolean { get { return type == JsonType.Boolean; } } public bool IsDouble { get { return type == JsonType.Double; } } public bool IsInt { get { return type == JsonType.Int; } } public bool IsLong { get { return type == JsonType.Long; } } public bool IsObject { get { return type == JsonType.Object; } } public bool IsString { get { return type == JsonType.String; } } public ICollection Keys { get { EnsureDictionary(); return inst_object.Keys; } } #endregion #region ICollection Properties int ICollection.Count { get { return Count; } } bool ICollection.IsSynchronized { get { return EnsureCollection().IsSynchronized; } } object ICollection.SyncRoot { get { return EnsureCollection().SyncRoot; } } #endregion #region IDictionary Properties bool IDictionary.IsFixedSize { get { return EnsureDictionary().IsFixedSize; } } bool IDictionary.IsReadOnly { get { return EnsureDictionary().IsReadOnly; } } ICollection IDictionary.Keys { get { EnsureDictionary(); IList keys = new List(); foreach (KeyValuePair entry in object_list) { keys.Add(entry.Key); } return (ICollection)keys; } } ICollection IDictionary.Values { get { EnsureDictionary(); IList values = new List(); foreach (KeyValuePair entry in object_list) { values.Add(entry.Value); } return (ICollection)values; } } #endregion #region IJsonWrapper Properties bool IJsonWrapper.IsArray { get { return IsArray; } } bool IJsonWrapper.IsBoolean { get { return IsBoolean; } } bool IJsonWrapper.IsDouble { get { return IsDouble; } } bool IJsonWrapper.IsInt { get { return IsInt; } } bool IJsonWrapper.IsLong { get { return IsLong; } } bool IJsonWrapper.IsObject { get { return IsObject; } } bool IJsonWrapper.IsString { get { return IsString; } } #endregion #region IList Properties bool IList.IsFixedSize { get { return EnsureList().IsFixedSize; } } bool IList.IsReadOnly { get { return EnsureList().IsReadOnly; } } #endregion #region IDictionary Indexer object IDictionary.this[object key] { get { return EnsureDictionary()[key]; } set { if (!(key is String)) throw new ArgumentException( "The key has to be a string"); JsonData data = ToJsonData(value); this[(string)key] = data; } } #endregion #region IOrderedDictionary Indexer object IOrderedDictionary.this[int idx] { get { EnsureDictionary(); return object_list[idx].Value; } set { EnsureDictionary(); JsonData data = ToJsonData(value); KeyValuePair old_entry = object_list[idx]; inst_object[old_entry.Key] = data; KeyValuePair entry = new KeyValuePair(old_entry.Key, data); object_list[idx] = entry; } } #endregion #region IList Indexer object IList.this[int index] { get { return EnsureList()[index]; } set { EnsureList(); JsonData data = ToJsonData(value); this[index] = data; } } #endregion #region Public Indexers public JsonData this[string prop_name] { get { EnsureDictionary(); return inst_object[prop_name]; } set { EnsureDictionary(); KeyValuePair entry = new KeyValuePair(prop_name, value); if (inst_object.ContainsKey(prop_name)) { for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == prop_name) { object_list[i] = entry; break; } } } else object_list.Add(entry); inst_object[prop_name] = value; json = null; } } public JsonData this[int index] { get { EnsureCollection(); if (type == JsonType.Array) return inst_array[index]; return object_list[index].Value; } set { EnsureCollection(); if (type == JsonType.Array) inst_array[index] = value; else { KeyValuePair entry = object_list[index]; KeyValuePair new_entry = new KeyValuePair(entry.Key, value); object_list[index] = new_entry; inst_object[entry.Key] = value; } json = null; } } #endregion #region Constructors public JsonData() { } public JsonData(bool boolean) { type = JsonType.Boolean; inst_boolean = boolean; } public JsonData(double number) { type = JsonType.Double; inst_double = number; } public JsonData(int number) { type = JsonType.Int; inst_int = number; } public JsonData(long number) { type = JsonType.Long; inst_long = number; } public JsonData(object obj) { if (obj is Boolean) { type = JsonType.Boolean; inst_boolean = (bool)obj; return; } if (obj is Double) { type = JsonType.Double; inst_double = (double)obj; return; } if (obj is Int32) { type = JsonType.Int; inst_int = (int)obj; return; } if (obj is Int64) { type = JsonType.Long; inst_long = (long)obj; return; } if (obj is String) { type = JsonType.String; inst_string = (string)obj; return; } throw new ArgumentException( "Unable to wrap the given object with JsonData"); } public JsonData(string str) { type = JsonType.String; inst_string = str; } #endregion #region Implicit Conversions public static implicit operator JsonData(Boolean data) { return new JsonData(data); } public static implicit operator JsonData(Double data) { return new JsonData(data); } public static implicit operator JsonData(Int32 data) { return new JsonData(data); } public static implicit operator JsonData(Int64 data) { return new JsonData(data); } public static implicit operator JsonData(String data) { return new JsonData(data); } #endregion #region Explicit Conversions public static explicit operator Boolean(JsonData data) { if (data.type != JsonType.Boolean) throw new InvalidCastException( "Instance of JsonData doesn't hold a double"); return data.inst_boolean; } public static explicit operator Double(JsonData data) { if (data.type != JsonType.Double) throw new InvalidCastException( "Instance of JsonData doesn't hold a double"); return data.inst_double; } public static explicit operator Int32(JsonData data) { if (data.type != JsonType.Int) throw new InvalidCastException( "Instance of JsonData doesn't hold an int"); return data.inst_int; } public static explicit operator Int64(JsonData data) { if (data.type != JsonType.Long) throw new InvalidCastException( "Instance of JsonData doesn't hold an int"); return data.inst_long; } public static explicit operator String(JsonData data) { if (data.type != JsonType.String) throw new InvalidCastException( "Instance of JsonData doesn't hold a string"); return data.inst_string; } #endregion #region ICollection Methods void ICollection.CopyTo(Array array, int index) { EnsureCollection().CopyTo(array, index); } #endregion #region IDictionary Methods void IDictionary.Add(object key, object value) { JsonData data = ToJsonData(value); EnsureDictionary().Add(key, data); KeyValuePair entry = new KeyValuePair((string)key, data); object_list.Add(entry); json = null; } void IDictionary.Clear() { EnsureDictionary().Clear(); object_list.Clear(); json = null; } bool IDictionary.Contains(object key) { return EnsureDictionary().Contains(key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return ((IOrderedDictionary)this).GetEnumerator(); } void IDictionary.Remove(object key) { EnsureDictionary().Remove(key); for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == (string)key) { object_list.RemoveAt(i); break; } } json = null; } #endregion #region IEnumerable Methods IEnumerator IEnumerable.GetEnumerator() { return EnsureCollection().GetEnumerator(); } #endregion #region IJsonWrapper Methods bool IJsonWrapper.GetBoolean() { if (type != JsonType.Boolean) throw new InvalidOperationException( "JsonData instance doesn't hold a boolean"); return inst_boolean; } double IJsonWrapper.GetDouble() { if (type != JsonType.Double) throw new InvalidOperationException( "JsonData instance doesn't hold a double"); return inst_double; } int IJsonWrapper.GetInt() { if (type != JsonType.Int) throw new InvalidOperationException( "JsonData instance doesn't hold an int"); return inst_int; } long IJsonWrapper.GetLong() { if (type != JsonType.Long) throw new InvalidOperationException( "JsonData instance doesn't hold a long"); return inst_long; } string IJsonWrapper.GetString() { if (type != JsonType.String) throw new InvalidOperationException( "JsonData instance doesn't hold a string"); return inst_string; } void IJsonWrapper.SetBoolean(bool val) { type = JsonType.Boolean; inst_boolean = val; json = null; } void IJsonWrapper.SetDouble(double val) { type = JsonType.Double; inst_double = val; json = null; } void IJsonWrapper.SetInt(int val) { type = JsonType.Int; inst_int = val; json = null; } void IJsonWrapper.SetLong(long val) { type = JsonType.Long; inst_long = val; json = null; } void IJsonWrapper.SetString(string val) { type = JsonType.String; inst_string = val; json = null; } string IJsonWrapper.ToJson() { return ToJson(); } void IJsonWrapper.ToJson(JsonWriter writer) { ToJson(writer); } #endregion #region IList Methods int IList.Add(object value) { return Add(value); } void IList.Clear() { EnsureList().Clear(); json = null; } bool IList.Contains(object value) { return EnsureList().Contains(value); } int IList.IndexOf(object value) { return EnsureList().IndexOf(value); } void IList.Insert(int index, object value) { EnsureList().Insert(index, value); json = null; } void IList.Remove(object value) { EnsureList().Remove(value); json = null; } void IList.RemoveAt(int index) { EnsureList().RemoveAt(index); json = null; } #endregion #region IOrderedDictionary Methods IDictionaryEnumerator IOrderedDictionary.GetEnumerator() { EnsureDictionary(); return new OrderedDictionaryEnumerator( object_list.GetEnumerator()); } void IOrderedDictionary.Insert(int idx, object key, object value) { string property = (string)key; JsonData data = ToJsonData(value); this[property] = data; KeyValuePair entry = new KeyValuePair(property, data); object_list.Insert(idx, entry); } void IOrderedDictionary.RemoveAt(int idx) { EnsureDictionary(); inst_object.Remove(object_list[idx].Key); object_list.RemoveAt(idx); } #endregion #region Private Methods private ICollection EnsureCollection() { if (type == JsonType.Array) return (ICollection)inst_array; if (type == JsonType.Object) return (ICollection)inst_object; throw new InvalidOperationException( "The JsonData instance has to be initialized first"); } private IDictionary EnsureDictionary() { if (type == JsonType.Object) return (IDictionary)inst_object; if (type != JsonType.None) throw new InvalidOperationException( "Instance of JsonData is not a dictionary"); type = JsonType.Object; inst_object = new Dictionary(); object_list = new List>(); return (IDictionary)inst_object; } private IList EnsureList() { if (type == JsonType.Array) return (IList)inst_array; if (type != JsonType.None) throw new InvalidOperationException( "Instance of JsonData is not a list"); type = JsonType.Array; inst_array = new List(); return (IList)inst_array; } private JsonData ToJsonData(object obj) { if (obj == null) return null; if (obj is JsonData) return (JsonData)obj; return new JsonData(obj); } private static void WriteJson(IJsonWrapper obj, JsonWriter writer) { if (obj == null) { writer.Write(null); return; } if (obj.IsString) { writer.Write(obj.GetString()); return; } if (obj.IsBoolean) { writer.Write(obj.GetBoolean()); return; } if (obj.IsDouble) { writer.Write(obj.GetDouble()); return; } if (obj.IsInt) { writer.Write(obj.GetInt()); return; } if (obj.IsLong) { writer.Write(obj.GetLong()); return; } if (obj.IsArray) { writer.WriteArrayStart(); foreach (object elem in (IList)obj) WriteJson((JsonData)elem, writer); writer.WriteArrayEnd(); return; } if (obj.IsObject) { writer.WriteObjectStart(); foreach (DictionaryEntry entry in ((IDictionary)obj)) { writer.WritePropertyName((string)entry.Key); WriteJson((JsonData)entry.Value, writer); } writer.WriteObjectEnd(); return; } } #endregion public int Add(object value) { JsonData data = ToJsonData(value); json = null; return EnsureList().Add(data); } /**add by dgq**/ public JsonData GetObjectFromArrary_ByKeyValue(string Key, string value) { if (this.IsArray == true) { JsonData arrary = (JsonData)(this); for (int i = 0, j = arrary.Count; i < j; i++) { if (!arrary[i].Keys.Contains(Key)) continue; if (arrary[i].IsObject == true && arrary[i][Key].ToString() == value) return arrary[i]; } } return null; } public void Clear() { if (IsObject) { ((IDictionary)this).Clear(); return; } if (IsArray) { ((IList)this).Clear(); return; } } public bool Equals(JsonData x) { if (x == null) return false; if (x.type != this.type) return false; switch (this.type) { case JsonType.None: return true; case JsonType.Object: return this.inst_object.Equals(x.inst_object); case JsonType.Array: return this.inst_array.Equals(x.inst_array); case JsonType.String: return this.inst_string.Equals(x.inst_string); case JsonType.Int: return this.inst_int.Equals(x.inst_int); case JsonType.Long: return this.inst_long.Equals(x.inst_long); case JsonType.Double: return this.inst_double.Equals(x.inst_double); case JsonType.Boolean: return this.inst_boolean.Equals(x.inst_boolean); } return false; } public JsonType GetJsonType() { return type; } public void SetJsonType(JsonType type) { if (this.type == type) return; switch (type) { case JsonType.None: break; case JsonType.Object: inst_object = new Dictionary(); object_list = new List>(); break; case JsonType.Array: inst_array = new List(); break; case JsonType.String: inst_string = default(String); break; case JsonType.Int: inst_int = default(Int32); break; case JsonType.Long: inst_long = default(Int64); break; case JsonType.Double: inst_double = default(Double); break; case JsonType.Boolean: inst_boolean = default(Boolean); break; } this.type = type; } public string ToJson() { if (json != null) return json; StringWriter sw = new StringWriter(); JsonWriter writer = new JsonWriter(sw); writer.Validate = false; WriteJson(this, writer); json = sw.ToString(); return json; } public void ToJson(JsonWriter writer) { bool old_validate = writer.Validate; writer.Validate = false; WriteJson(this, writer); writer.Validate = old_validate; } public override string ToString() { switch (type) { case JsonType.Array: return "JsonData array"; case JsonType.Boolean: return inst_boolean.ToString(); case JsonType.Double: return inst_double.ToString(); case JsonType.Int: return inst_int.ToString(); case JsonType.Long: return inst_long.ToString(); case JsonType.Object: return "JsonData object"; case JsonType.String: return inst_string; } return "Uninitialized JsonData"; } } internal class OrderedDictionaryEnumerator : IDictionaryEnumerator { IEnumerator> list_enumerator; public object Current { get { return Entry; } } public DictionaryEntry Entry { get { KeyValuePair curr = list_enumerator.Current; return new DictionaryEntry(curr.Key, curr.Value); } } public object Key { get { return list_enumerator.Current.Key; } } public object Value { get { return list_enumerator.Current.Value; } } public OrderedDictionaryEnumerator( IEnumerator> enumerator) { list_enumerator = enumerator; } public bool MoveNext() { return list_enumerator.MoveNext(); } public void Reset() { list_enumerator.Reset(); } } }