原创的C#版Json读写类
郝伟 2021/02/14
本代码主要是用于C#中对JSon文件的解析,所有代码均为原创。
using System; using System.Collections.Generic; using System.IO; using System.Text; namespace huaun.hao.Json { /// <summary> /// Json的节点类,用于表示Json树型中的一个节点。 /// </summary> public class JsonNode { /// <summary> /// 节点的名称 /// </summary> public string key; /// <summary> /// 当前节点的子节点。 /// </summary> public List<JsonNode> childNodes; /// <summary> /// 当前节点的父节点。 /// </summary> public JsonNode parent; /// <summary> /// 节点的值。 /// </summary> public object value; /// <summary> /// 节点值的类型。 /// </summary> public JsonValueType valueType; private bool closeList; public int level = 0; public JsonNode() { this.closeList = false; this.valueType = JsonValueType.Node; this.childNodes = new List<JsonNode>(); } public JsonNode(string key) { this.closeList = false; this.valueType = JsonValueType.Node; this.childNodes = new List<JsonNode>(); this.key = key; } /// <summary> /// 将输入节点添加为当前节点的子节点。 /// </summary> /// <param name="node"></param> public void addChild(JsonNode node) { if (childNodes == null) childNodes = new List<JsonNode>(); this.childNodes.Add(node); node.parent = this; } /// <summary> /// 将节点添加到当前节点值的列表中,如果当前节点的值不存在或不是列表,则重新创建。 /// </summary> /// <param name="node"></param> public void addNodetoValueList(JsonNode node) { if (value == null || !(value is List<JsonNode>)) { value = new List<JsonNode>(); valueType = JsonValueType.List; } (value as List<JsonNode>).Add(node); } /// <summary> /// 将当前节点添加至 /// </summary> /// <param name="str"></param> public void addStringToList(string str) { (this.value as List<JsonNode>).Add(new JsonNode { value = str }); } /// <summary> /// 返回第0个元素,如果不存在则返回null。 /// </summary> /// <returns></returns> public JsonNode first() { return (this.childNodes?.Count > 0) ? this.childNodes[0] : null; } /// <summary> /// 返回第最后一个元素,如果不存在则返回null。 /// </summary> /// <returns></returns> private JsonNode last() { return (this.childNodes.Count > 0) ? this.childNodes[this.childNodes.Count - 1] : null; } /// <summary> /// 返回当前值作为列表的长度,如果不是列表返回-1. /// </summary> /// <returns></returns> public int getListCount() { return (this.value is List<JsonNode>) ? (this.value as List<JsonNode>).Count : -1; } /// <summary> /// 使用键值搜索子节点,找到名称为 key 的节点。 /// </summary> /// <param name="key"></param> /// <returns></returns> public JsonNode this[string key] { get { JsonNode node = null; foreach (var child in this.childNodes) { if (child.key == key) { node = child; break; } } return node; } } public JsonNode getListNode(int p) { return (((p >= 0) && (p < this.getListCount())) ? (this.value as List<JsonNode>)[p] : null); } public JsonNode getListNode(string key) { List<JsonNode> list = this.value as List<JsonNode>; if (list != null) { foreach (JsonNode node2 in list) { if (node2.key == key) { return node2; } } } return null; } /// <summary> /// 判断当前字符是否为白空格。 /// </summary> /// <param name="c"></param> /// <returns></returns> public static bool isWhiteSpace(char c) { return ((((c == ' ') || (c == '\r')) || (c == '\n')) || (c == '\t')); } public static JsonNode parse(string data) { JsonNode item = new JsonNode("root"); Stack<JsonNode> stack = new Stack<JsonNode>(); int pos; for (int i = 0; i < data.Length; i = pos + 1) { int startPos; char c = data[i]; if (!isWhiteSpace(c)) { startPos = i; if (char.IsDigit(c) || (c == '-')) { startPos = i; if (c == '-') { pos = i; i = pos + 1; } while (char.IsDigit(data[i]) || (data[i] == '.')) { pos = i; i = pos + 1; } item.setDouble(double.Parse(data.Substring(startPos, i - startPos))); pos = i; i = pos - 1; } else { switch (c) { case '"': goto Label_01B9; case ',': if (((item.valueType != JsonValueType.List) || item.closeList) && (item.parent != null)) { item.parent.addChild(new JsonNode()); item = item.parent.last(); } break; case '[': goto Label_0305; case ']': goto Label_030E; case '{': if (item.valueType == JsonValueType.List) { if (!item.closeList) { JsonNode node = new JsonNode { valueType = JsonValueType.Node }; node.addChild(new JsonNode()); item.addNodetoValueList(node); stack.Push(item); item = node.first(); } } else if (item.key != null) { JsonNode node3 = new JsonNode { valueType = JsonValueType.Node }; node3.addChild(new JsonNode()); item.value = node3; stack.Push(item); item = node3.first(); } break; case '}': goto Label_028B; } } } goto Label_0338; Label_01B9: startPos = i + 1; do { pos = i + 1; i = pos; } while (data[pos] != '"'); string str = data.Substring(startPos, i - startPos); if (item.valueType == JsonValueType.List) { item.addStringToList(str); } else if (item.key == null) { item.key = str; } else { item.setString(str); } goto Label_0338; Label_028B: if (stack.Count == 0) { item = item.parent; } else { JsonNode node4 = stack.Pop(); if (item.parent != null) { item = node4; } else if (node4.valueType == JsonValueType.List) { node4.addNodetoValueList(item); } else if (node4.valueType == JsonValueType.Node) { node4.value = item; } else { item = node4; } } goto Label_0338; Label_0305: item.setNewList(); goto Label_0338; Label_030E: if ((item.valueType == JsonValueType.List) && !item.closeList) { item.closeList = true; } Label_0338: pos = i; } return (item.value as JsonNode); } public static JsonNode read(string path) { return parse(File.ReadAllText(path)); } private void setDouble(double v) { if (this.valueType == JsonValueType.List) { JsonNode item = new JsonNode { value = v, valueType = JsonValueType.Numerial }; (this.value as List<JsonNode>).Add(item); } else { this.value = v; this.valueType = JsonValueType.Numerial; } } private void setNewList() { this.value = new List<JsonNode>(); this.valueType = JsonValueType.List; } private void setString(string v) { this.value = v; this.valueType = JsonValueType.String; } public static void showAll(JsonNode node) { int num2; Console.WriteLine(node.ToString()); for (int i = 0; i < node.childNodes.Count; i = num2 + 1) { showAll(node.childNodes[i]); num2 = i; } } public override string ToString() { StringBuilder builder = new StringBuilder(); Stack<JsonNode> stack = new Stack<JsonNode>(); string indent = new string(' ', 8); string[] indents = new string[100]; for (int i = 1; i < indents.Length; i++) indents[i] = indents[i - 1] + indent; stack.Push(this); while (stack.Count > 0) { JsonNode jn = stack.Pop(); builder.Append(indents[jn.level] + jn.key + " : "); switch (jn.valueType) { case JsonValueType.Numerial: case JsonValueType.String: builder.Append(jn.value?.ToString() + "\n"); break; case JsonValueType.Node: builder.AppendLine(); var nodelist = jn.value == null ? jn.childNodes : (jn.value as JsonNode).childNodes; if (nodelist.Count > 0) { // builder.Append(indents[jn.level] + "{\n"); for (int i = nodelist.Count - 1; i >= 0; i--) { nodelist[i].level = jn.level + 1; stack.Push(nodelist[i]); } // builder.Append(indents[jn.level] + "}\n"); } break; case JsonValueType.List: List<JsonNode> list = (List<JsonNode>)jn.value; builder.Append("[\n"); for (int i = list.Count - 1; i >= 0; i--) { list[i].level = jn.level + 1; stack.Push(list[i]); } builder.Append(indents[jn.level] + "]\n"); break; } } return builder.ToString(); } } }
namespace huaun.hao.Json { public enum JsonValueType : int { /// <summary> /// 数值型 /// </summary> Numerial = 0, /// <summary> /// 字符串型 /// </summary> String = 1, /// 列表型,即[Node1, Node2, Node3, ...]。 /// </summary> List = 2, /// <summary> /// 表示此节点的值为子树(即有子节点) /// </summary> /// <summary> Node = 10, } }