private void CloneStep(KeyValueEx kve, KeyValueEx des) { if (kve == null || des == null) { return; } foreach (var item in kve) { if (item.Value is KeyValueEx) { des[item.Key] = new KeyValueEx(); CloneStep(item.Value as KeyValueEx, des[item.Key] as KeyValueEx); } else if (item.Value is KeyValueExList) { KeyValueExList vle = item.Value as KeyValueExList; KeyValueExList vle1 = new KeyValueExList(); des[item.Key] = vle1; foreach (var item1 in vle) { KeyValueEx des1 = new KeyValueEx(); CloneStep(item1, des1); vle1.Add(des1); } } else if (item.Value is StringExList) { StringExList vl = item.Value as StringExList; StringExList vl1 = new StringExList(); des[item.Key] = vl1; foreach (var item2 in vl) { vl1.Add(item2); } } else { des[item.Key] = item.Value.ToString(); } } }
/// <summary> /// 递归转换json字符串为字典对象的单步运算 /// 单步处理单元是一个json,以大括号开始 /// </summary> /// <param name="kve">用于保存的字典对象</param> /// <param name="s">json字符串</param> /// <param name="now_index">待转换的字符串处理到何处的索引</param> private static void JsonStringToKeyValueExStep(KeyValueEx kve, string s, ref int now_index) { Stack <char> sc = new Stack <char>(); string key = null; string value = null; // 键是否结束 bool b_key = false; bool space_fliter = true; int i = now_index; for ( ; i < s.Length; i++) { // 如果栈上没有元素,一直忽略到第一个做大括号为止 if (sc.Count > 0) { char stack_char = sc.Peek(); if (stack_char == '{') { // if (s[i] == ' ') { continue; } // 说明键开始了 if (s[i] == '"') { sc.Push(s[i]); b_key = false; continue; } // 键值对区分的冒号 if (s[i] == ':') { sc.Push(s[i]); continue; } // 本次json未完成的情况下,又有左大括号 if (s[i] == '{') { sc.Pop(); // 新的递归 kve[key] = new KeyValueEx(); JsonStringToKeyValueExStep(kve[key] as KeyValueEx, s, ref i); key = null; continue; } // 本次json未完成的情况下,又有左中括号 if (s[i] == '[') { // 新的递归 int j = i; // 试探这个数组 for ( ; j < s.Length; j++) { // 这个数组的元素是json if (s[j] == '{') { i = j; KeyValueExList vle_temp = new KeyValueExList(); kve[key] = vle_temp; for ( ; i < s.Length; i++) { // 达到右中括号,表示数组结束 if (s[i] == ']') { break; } // List中的json元素解析开始 if (s[i] == '{') { KeyValueEx kve_temp = new KeyValueEx(); JsonStringToKeyValueExStep(kve_temp, s, ref i); vle_temp.Add(kve_temp); } } break; } // 这个数组的元素是字符串 if (s[j] == '"') { StringExList vl_temp = new StringExList(); StringToStringExList(s, vl_temp, ref i); kve[key] = vl_temp; break; } } // 解析完毕,清空 key = null; b_key = false; sc.Pop(); continue; } // 本次json结束,大循环退出 if (s[i] == '}') { break; } } else if (stack_char == '"') { // 是否有转义字符? if (s[i] == '\\') { sc.Push(s[i]); continue; } // 如果栈上和当前字符都是引号,说明键或值,完成了 if (s[i] == '"') { sc.Pop(); if (b_key) { // 如果值是空字符串,value就为null,所以要加个空字符串 kve[key] = value + ""; key = value = null; } else { b_key = true; } continue; } // 引号中其他字符都是键或值得字符串 if (b_key) { value += s[i]; } else { key += s[i]; } } else if (stack_char == '\\') { // 转义字符,未完美解决 if (b_key) { //value += Convert.ToChar( "\\" + s[i] ); //value += char.Parse( "\\" + s[i] ); value += s[i]; } else { //key += char.Parse( "\\" + s[i] ); value += s[i]; } sc.Pop(); } else if (stack_char == ':') { // 栈上是冒号,且当前字符是数字,说明值域开始了 if (s[i] >= '0' && s[i] <= '9') { sc.Pop(); // 以\a来表示数字 sc.Push('\a'); i--; continue; } // 栈上是冒号,且当前字符是'n',有可能是指null if (s[i] == 'n') { sc.Pop(); // 以\v来表示数字 sc.Push('\v'); i--; continue; } // 栈上是冒号,且当前字符是引号,说明值域开始了 if (s[i] == '"') { sc.Pop(); sc.Push(s[i]); continue; } // 栈上是冒号,且当前字符是左大括号,新的子json开始了 if (s[i] == '{') { sc.Pop(); // 新的递归 kve[key] = new KeyValueEx(); JsonStringToKeyValueExStep(kve[key] as KeyValueEx, s, ref i); key = null; continue; } // 栈上是冒号,且当前字符是左大括号,新的子数组开始了 if (s[i] == '[') { // 新的递归 int j = i; // 试探这个数组 for ( ; j < s.Length; j++) { // 这个数组的元素是json if (s[j] == '{') { i = j; KeyValueExList vle_temp = new KeyValueExList(); kve[key] = vle_temp; for ( ; i < s.Length; i++) { // 到了数组尾部 if (s[i] == ']') { break; } if (s[i] == '{') { KeyValueEx kve_temp = new KeyValueEx(); JsonStringToKeyValueExStep(kve_temp, s, ref i); vle_temp.Add(kve_temp); } } break; } // 这个数组的元素是字符串 if (s[j] == '"') { StringExList vl_temp = new StringExList(); StringToStringExList(s, vl_temp, ref i); kve[key] = vl_temp; break; } } // 清空 key = null; b_key = false; sc.Pop(); continue; } } // 纯数字的值域 else if (stack_char == '\a') { if (s[i] == ' ') { continue; } // 如果栈上和当前字符都是\a,说明键或值,完成了 if (s[i] == ',' || s[i] == ']' || s[i] == '}') { double d_temp = 0; try { d_temp = double.Parse(value); } catch (Exception e) { throw e; } sc.Pop(); if (b_key) { kve[key] = value; key = value = null; } else { b_key = true; } if (s[i] == ',') { continue; } if (s[i] == ']' || s[i] == '}') { break; } } // 引号中其他字符都是键或值得字符串 if (b_key) { value += s[i]; } else { key += s[i]; } }// null else if (stack_char == '\v') { if (s[i] == ' ') { continue; } // 如果栈上和当前字符都是\v,说明键或值,完成了 if (s[i] == ',' || s[i] == ']' || s[i] == '}') { if (value != "null") { throw new Exception("构造null时出错"); } sc.Pop(); if (b_key) { kve[key] = null; key = value = null; } else { b_key = true; } if (s[i] == ',') { continue; } if (s[i] == ']' || s[i] == '}') { break; } } // 引号中其他字符都是键或值得字符串 if (b_key) { value += s[i]; } else { key += s[i]; } } } else if (s[i] == '{') { sc.Push(s[i]); } } now_index = i; }
/// <summary> /// 转换当前节点为字典或list /// Item节点还是字典不变,但是Item节点作为value所对应的key是不存在的 /// 它对应的key作为上一级List的成员保存了起来 /// 例: /// 原来,大括号表示字典类型 /// List:{Item:{id:1},Item:{id:1}} /// 现在,中括号实际上是ListEx类型 /// List(Item):[{id:1},{id:1}] /// </summary> /// <param name="xn"></param> /// <param name="dso"></param> private static void XmlNodeToKeyValueEx(XmlNode xn, object dso, string list_name) { if (xn == null) { return; } XmlNodeList xnl = xn.ChildNodes; KeyValueExList kv_list = null; KeyValueEx kv = null; StringExList sel = null; if (dso is KeyValueEx) { kv = dso as KeyValueEx; } if (dso is KeyValueExList) { kv_list = dso as KeyValueExList; } if (dso is StringExList) { sel = dso as StringExList; } IAttr iattr = null; object temp = null; // 如果没有子节点了,退出递归的条件 // 后一个条件是为了忽略xml的强制数据条件<![CDATA[...]]>,不把它当作子节点处理 if (xnl.Count == 0 || xn.InnerText == xn.InnerXml || (xnl.Count == 1 && (xnl[0].NodeType == XmlNodeType.Text || xnl[0].NodeType == XmlNodeType.CDATA))) { XmlElement xe = xn as XmlElement; StringEx se = null; if (string.IsNullOrEmpty(xe.InnerText)) { if (xn.FirstChild == null && xe != null && xe.IsEmpty) { se = new StringEx(null); } else { se = new StringEx(""); } } else { se = new StringEx(xe.InnerText); } //如果本节点是字典类型 if (kv != null) { // 添加键值对 kv.Add(xn.Name, se); } //// 如果本节点是list类型,直接添加值,忽略键,在这个版本下不可能出现的键值列表又是stringex //else if( kv_list != null ) //{ // kv_list.Add( se ); //} else if (sel != null) { sel.Add(se); } else { throw new Exception("转换失败"); } iattr = se as IAttr; if (iattr != null && xn.Attributes != null) { foreach (XmlAttribute item in xn.Attributes) { iattr.Attr[item.Name] = item.Value; } } return; } else { // 保存子节点(item)的 string son_name = null; // 如果节点名在强制节点名中,那么把这个节点强制看作List,以当前节点的第一个子节点作为子节点名 // 防止把一个list一个item当作字典处理的这种情况 // 或者如果有重复的子节点 if (IsXmlNodeList(xn, list_name, ref son_name) || HasXmlNodeDuplicateChild(xn, ref son_name)) { //提前处理了字符数组的情况 if (xn.FirstChild.FirstChild == null || xn.FirstChild.InnerText == xn.FirstChild.InnerXml || (xn.FirstChild.NodeType == XmlNodeType.Text || xn.FirstChild.NodeType == XmlNodeType.CDATA)) { temp = new StringExList() { SonName = son_name }; } else { // 装子节点的对象为list // 实际保存为DictionaryEx<"List", List<object>> temp = new KeyValueExList(son_name); } } else { temp = new KeyValueEx(); } if (kv != null) { // 以空字典添加节点 kv.Add(xn.Name, temp); } else if (kv_list != null) { kv_list.Add((KeyValueEx)temp); } else { throw new Exception("转换失败"); } } iattr = temp as IAttr; if (iattr != null) { foreach (XmlAttribute item in xn.Attributes) { iattr.Attr[item.Name] = item.Value; } } // 子节点递归 for (int i = 0; i < xnl.Count; i++) { XmlNodeToKeyValueEx(xnl[i], temp, list_name); } }