原创的C#版Json读写类 郝伟 2021/02/14 [TOC]

1. 简介

本代码主要是用于C#中对JSon文件的解析,所有代码均为原创。

2. 源代码

2.1. 核心类

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();
        }
    }
}

2.2. 枚举类型 JsonValueType

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,
  }
}

results matching ""

    No results matching ""