原创的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,
}
}