PageRenderTime 2ms CodeModel.GetById 26ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 1ms

/ED47.Stack.Web/Json/JsonObject.cs

https://github.com/ed47/ED47.Stack
C# | 418 lines | 326 code | 64 blank | 28 comment | 60 complexity | 365e170ef41e5c2cab21a214c182c276 MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Diagnostics.CodeAnalysis;
  4using System.Linq;
  5using System.Runtime.Serialization;
  6using System.Text.RegularExpressions;
  7using System.Xml.Linq;
  8using Newtonsoft.Json;
  9using Newtonsoft.Json.Linq;
 10
 11namespace ED47.Stack.Web
 12{
 13
 14    [Serializable]
 15    [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
 16    public class JsonObject : ISerializable
 17    {
 18      
 19
 20        private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();
 21        private JsonObjectSerialization _serializationType = JsonObjectSerialization.DataOnly;
 22
 23        private readonly object _source;
 24        private string _typeName = "";
 25
 26        public JsonObject()
 27        {
 28        }
 29
 30        public JsonObject(string json)
 31        {
 32            if (String.IsNullOrWhiteSpace(json)) return;
 33
 34            JObject obj = JsonConvert.DeserializeObject(json) as JObject;
 35
 36            foreach (var property in obj.Properties())
 37            {
 38                AddProperty(property.Name, property.Value);
 39            }
 40        }
 41
 42        /// <summary>
 43        /// Creates a JsonObject from a XDocument.
 44        /// </summary>
 45        /// <param name="source">The XDocument to build the JsonObject from.</param>
 46        public JsonObject(XDocument source)
 47        {
 48            if (source == null) return;
 49            if (source.Root == null) return;
 50            
 51            XmlAddRecursive(source.Root.Elements());
 52        }
 53
 54        /// <summary>
 55        /// Recursively traverse the XDocument and add properties when a bottom element is found.
 56        /// </summary>
 57        /// <param name="elements">The elements to explore.</param>
 58        /// <param name="path">The path to this dept.</param>
 59        private void XmlAddRecursive(IEnumerable<XElement> elements, string path = "")
 60        {
 61            foreach (var element in elements)
 62            {
 63                var nextPath = String.IsNullOrWhiteSpace(path) ? element.Name.ToString() : path + "." + element.Name;
 64                if (element.HasElements)
 65                {
 66                    XmlAddRecursive(element.Elements(), nextPath);
 67                }
 68                else
 69                {
 70                    AddProperty(nextPath, element.Value);
 71                }
 72            }
 73        }
 74
 75        public JsonObject(object source)
 76        {
 77            if (source == null) return;
 78            
 79            _source = source;
 80            dynamic t = new { };
 81            
 82            var pps = source.GetType().GetProperties();
 83            foreach (var p in pps)
 84            {
 85                AddProperty(p.Name, p.GetValue(source, null));
 86            }
 87        }
 88
 89      
 90
 91        public JsonObjectSerialization SerializationType
 92        {
 93            get { return _serializationType; }
 94            set { _serializationType = value; }
 95        }
 96
 97        public JsonObject Parent { get; set; }
 98
 99        public object Source
100        {
101            get { return _source; }
102        }
103
104
105        public string[] Properties
106        {
107            get { return _properties.Keys.ToArray(); }
108        }
109
110        public object this[string propertyName]
111        {
112            get
113            {
114                if (_properties.ContainsKey(propertyName))
115                    return _properties[propertyName];
116                if (propertyName == "parent")
117                    return Parent;
118
119                return null;
120            }
121            set
122            {
123                if (_properties.ContainsKey(propertyName))
124                    _properties[propertyName] = value;
125                else
126                    _properties.Add(propertyName, value);
127            }
128        }
129
130        public string TypeName
131        {
132            get { return _typeName; }
133            set { _typeName = value; }
134        }
135
136       
137
138        public void RemoveProperty(string name)
139        {
140            if (_properties.ContainsKey(name))
141                _properties.Remove(name);
142        }
143
144        public bool HasProperty(string propertyName)
145        {
146            return _properties.ContainsKey(propertyName) || (Parent != null && propertyName == "parent");
147        }
148
149        public void AddProperty(string name, object value)
150        {
151            var jsonObject = value as JsonObject;
152            if (jsonObject != null)
153            {
154                (jsonObject).Parent = this;
155            }
156            var jsonObjectList = value as JsonObjectList;
157            if (jsonObjectList != null)
158            {
159                (jsonObjectList).Parent = this;
160            }
161            if (_properties.ContainsKey(name))
162                this[name] = value;
163            else
164                _properties.Add(name, value);
165        }
166        
167
168        public static void FindAllChildren(JsonObject obj, List<JsonObject> result)
169        {
170            result.Add(obj);
171            foreach (var p in obj._properties.Values)
172            {
173                if (p is JsonObjectList)
174                {
175                    foreach (JsonObject o in (JsonObjectList)p)
176                    {
177                        FindAllChildren(o, result);
178                    }
179                }
180                else if (p is JsonObject)
181                {
182                    FindAllChildren((JsonObject)p, result);
183                }
184            }
185        }
186
187        public List<JsonObject> FindChildrenByRegex(string pattern)
188        {
189            var reg = new Regex(pattern);
190
191            var result = new List<JsonObject>();
192
193            if (String.IsNullOrEmpty(pattern))
194            {
195                FindAllChildren(this, result);
196            }
197            else
198            {
199                FindChildren(this, reg, result);
200            }
201
202            return result;
203        }
204
205        public void Apply(Action<JsonObject> fn)
206        {
207            fn(this);
208            var children = new List<JsonObject>();
209            FindAllChildren(this, children);
210            foreach (var o in children)
211            {
212                if (o != this)
213                    o.Apply(fn);
214            }
215        }
216
217        public IEnumerable<TResult> Apply<TResult>(Func<JsonObject,TResult> fn)
218        {
219            var res = new List<TResult>();
220            res.Add(fn(this));
221            var children = new List<JsonObject>();
222            FindAllChildren(this, children);
223            foreach (var o in children)
224            {
225                if (o != this)
226                    res.AddRange(o.Apply(fn));
227            }
228            return res;
229        }
230
231        [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
232        private static void FindChildren(JsonObject o, Regex pattern, string path, ref List<JsonObject> result)
233        {
234            if (pattern.Match(path).Success)
235                result.Add(o);
236            foreach (var k in o._properties.Keys)
237            {
238                var p = o._properties[k];
239                var list = p as JsonObjectList;
240                if (list != null)
241                {
242                    foreach (JsonObject obj in list)
243                    {
244                        FindChildren(obj, pattern, path + (!String.IsNullOrEmpty(path) ? "." : "") + k, ref result);
245                    }
246                }
247                else
248                {
249                    var jsonObject = p as JsonObject;
250                    if (jsonObject != null)
251                    {
252                        FindChildren(jsonObject, pattern, path + (!String.IsNullOrEmpty(path) ? "." : "") + k, ref result);
253                    }
254                }
255            }
256        }
257
258        public static void FindChildren(JsonObject o, Regex pattern, List<JsonObject> result)
259        {
260            FindChildren(o, pattern, "", ref result);
261        }
262
263        /// <summary>
264        /// Finds the children.
265        /// </summary>
266        /// <param name="o">The o.</param>
267        /// <param name="path">The path to find the children</param>
268        /// <param name="result">The result list to be filled</param>
269       [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
270        public static void FindChildren(JsonObject o, string path, List<JsonObject> result)
271        {
272            var i = path.IndexOf(".", System.StringComparison.Ordinal);
273            if (i > 0)
274            {
275                var field = path.Substring(0, i);
276                var child = o[field];
277                if (child is JsonObjectList)
278                {
279                    var col = child as JsonObjectList;
280                    foreach (JsonObject c in col)
281                    {
282                        FindChildren(c, path.Substring(i + 1), result);
283                    }
284                }
285                else if (child is JsonObject)
286                {
287                    FindChildren(child as JsonObject, path.Substring(i + 1), result);
288                }
289            }
290            else
291            {
292                var child = o[path];
293                if (child is JsonObjectList)
294                {
295                    var col = child as JsonObjectList;
296                    result.AddRange(col.Cast<JsonObject>());
297                }
298                else
299                {
300                    result.Add(child as JsonObject);
301                }
302            }
303        }
304
305       /// <summary>
306       /// Adds and merges an object to the current JsonObject.
307       /// </summary>
308       /// <param name="obj">The object to be merge</param>
309        public void AddObject(JsonObject obj)
310        {
311            foreach (var k in obj._properties.Keys.Where(k => !_properties.ContainsKey(k)))
312            {
313                this[k] = obj[k];
314            }
315        }
316
317        private static object GetPropertyValue(object obj, string property)
318        {
319            if (obj is JsonObject && ((JsonObject)obj).HasProperty(property))
320            {
321                var res = ((JsonObject)obj)[property];
322                if (res != null)
323                    return res;
324            }
325
326            var pinfo = obj != null ? obj.GetType().GetProperty(property) : null;
327            if (pinfo != null)
328            {
329                return pinfo.GetValue(obj, null);
330            }
331            if (property == "this" || property == "values")
332            {
333                return obj;
334            }
335
336            return null;
337        }
338
339        /// <summary>
340        /// Get the value of a property of a child property (with a path like prop1.prop2)
341        /// </summary>
342        /// <param name="propertyName">The name or path of the property</param>
343        /// <param name="dataObject">The data object to explore (by default the current JsonObject)</param>
344        /// <returns></returns>
345        public object GetValue(string propertyName, object dataObject = null)
346        {
347            var obj = dataObject ?? this;
348            if (propertyName == "this" || propertyName == ".")
349                return obj;
350
351            
352            var path = propertyName.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
353
354            if (path.Length == 0)
355                return obj;
356
357            var index = 0;
358            var child = GetPropertyValue(obj, path[0]);
359            index++;
360            var scope = child;
361            while (index < path.Length)
362            {
363                if (child != null)
364                {
365                    child = GetPropertyValue(child, path[index]);
366                    scope = child ?? scope;
367                }
368                else
369                {
370                    break;
371                }
372                index++;
373            }
374            //var lastIdent = path[path.Length - 1];
375            //Match mfunc = new Regex(_RegSimpleFunc).Match(lastIdent);
376            
377            return child;
378        }
379
380        public override string ToString()
381        {
382            return Serialize();
383        }
384
385        private string Serialize()
386        {
387            return JsonConvert.SerializeObject(this, Formatting.None);
388
389        }
390
391        public static object Deserialize(string str)
392        {
393            return JsonConvert.DeserializeObject(str);
394        }
395
396       
397        #region ISerializable Membres
398
399        protected  JsonObject(SerializationInfo info, StreamingContext context)
400        {
401          
402
403            //Deserialize(info.GetString("data"));
404        }
405
406        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
407        {
408            foreach (var property in _properties)
409            {
410                info.AddValue(property.Key, property.Value);
411            }
412
413          
414        }
415
416        #endregion
417    }
418}