using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Topten.JsonKit { /// /// Helper extensions for navigating dictionaries of string/object /// public static class IDictionaryExtensions { /// /// Navigates a string/object dictionary following a path /// /// The root dictionary /// The path to follow /// Whether to create nodes as walking the path /// A callback invoked for each lead node. Return false to stop walk /// Result of last leafCallback, or false if key not found and create parameter is false public static bool WalkPath( this IDictionary This, string Path, bool create, Func,string, bool> leafCallback ) { // Walk the path var parts = Path.Split('.'); for (int i = 0; i < parts.Length-1; i++) { object val; if (!This.TryGetValue(parts[i], out val)) { if (!create) return false; val = new Dictionary(); This[parts[i]] = val; } This = (IDictionary)val; } // Process the leaf return leafCallback(This, parts[parts.Length-1]); } /// /// Check if a path exists in an string/object dictionary heirarchy /// /// The root dictionary /// The path to follow /// True if the path exists public static bool PathExists(this IDictionary This, string Path) { return This.WalkPath(Path, false, (dict, key) => dict.ContainsKey(key)); } /// /// Gets the object at the specified path in an string/object dictionary heirarchy /// /// The root dictionary /// The expected returned object type /// The path to follow /// The default value if the value isn't found /// public static object GetPath(this IDictionary This, Type type, string Path, object def) { This.WalkPath(Path, false, (dict, key) => { object val; if (dict.TryGetValue(key, out val)) { if (val == null) def = val; else if (type.IsAssignableFrom(val.GetType())) def = val; else def = Json.Reparse(type, val); } return true; }); return def; } /// /// Gets an object of specified type at a path location in a string/object dictionaryt /// /// The returned object type /// The root dictionary /// The path of the object to return /// The object instance public static T GetObjectAtPath(this IDictionary This, string Path) where T:class,new() { T retVal = null; This.WalkPath(Path, true, (dict, key) => { object val; dict.TryGetValue(key, out val); retVal = val as T; if (retVal == null) { retVal = val == null ? new T() : Json.Reparse(val); dict[key] = retVal; } return true; }); return retVal; } /// /// Get a value at a path in a string/object dictionary heirarchy /// /// The type of object to be returned /// The root dictionary /// The path of the entry to find /// The default value to return if not found /// The located value, or the default value if not found public static T GetPath(this IDictionary This, string Path, T def = default(T)) { return (T)This.GetPath(typeof(T), Path, def); } /// /// Set a value in a string/object dictionary heirarchy /// /// The root dictionary /// The path of the value to set /// The value to set public static void SetPath(this IDictionary This, string Path, object value) { This.WalkPath(Path, true, (dict, key) => { dict[key] = value; return true; }); } } }