C# JSON 解析

C# JSON 解析

原创文章,转载请注明出处:C# JSON 解析

源码在最后面

接口

  • xx.XXJSON.ToJSON(string data):object

解析为 数组 类型为 List<object>
解析为 字典 类型为 Dictionary<string,object>

测试

Console.WriteLine(xx.XXJSON.ToJSON("10"));
Console.WriteLine(xx.XXJSON.ToJSON("true"));
Console.WriteLine(xx.XXJSON.ToJSON("\"abc\""));
Console.WriteLine(null == xx.XXJSON.ToJSON("null") ? "null" : "xx");
Console.WriteLine(String.Join(",", xx.XXJSON.ToJSON("[1,2,3]") as List<object>));
var dict = xx.XXJSON.ToJSON("{\"xx\":771720}") as Dictionary<string,object>;
Console.WriteLine(dict["xx"]);
//打印结果
//10
//True
//abc
//null
//1,2,3
//771720

源码

using System;
using System.Collections.Generic;
using System.Text;

namespace xx
{
    /// <summary>
    /// JSON 解析
    /// <para>author wx771720@outlook.com 2022-12-09 10:56:12</para>
    /// </summary>
    public class XXJSON
    {
		private const char jsonString = '"';
		private const char jsonEscape = '\\';
		private const char jsonComma = ',';
		private const char jsonColon = ':';
		private const char jsonListBegin = '[';
		private const char jsonListEnd = ']';
		private const char jsonDictionaryBegin = '{';
		private const char jsonDictionaryEnd = '}';
		public static object ToJSON(string data)
		{
			int end;
			object result;
			try { if (TryJSONMeta(data, 0, out end, out result)) return result; } catch (Exception) { result = null; }
			return result;
		}

		private static bool isJSONEmpty(char letter) { return ' ' == letter || '\r' == letter || '\n' == letter; }
		private static bool TryJSONMeta(string data, int begin, out int end, out object result)
		{
			if (TryJSONString(data, begin, out end, out result)) return true;
			if (TryJSONNumber(data, begin, out end, out result)) return true;
			if (TryJSONBool(data, begin, out end, out result)) return true;
			if (TryJSONNull(data, begin, out end)) { result = null; return true; }
			if (TryJSONArray(data, begin, out end, out result)) return true;
			if (TryJSONDictionary(data, begin, out end, out result)) return true;
			return false;
		}
		private static Dictionary<char, char> jsonStrEscape = new Dictionary<char, char>() { { '\\', '\\' }, { '/', '/' }, { '"', '"' }, { 'f', '\f' }, { 't', '\t' }, { 'n', '\n' }, { 'r', '\r' } };
		private static StringBuilder jsonStrBuilder = new StringBuilder();
		private static bool TryJSONString(string data, int begin, out int end, out object result)
		{
			end = begin;
			result = null;

			char letter;
			bool hasEscape = false;
			int? stringBegin = null;
			while (begin < data.Length)
			{
				letter = data[begin++];
				if (stringBegin.HasValue)//已找到部分字符
				{
					if (letter == jsonEscape)//转义字符
					{
						if (begin >= data.Length) return false;
						hasEscape = true;
						letter = data[begin++];
						if ('u' == letter || 'U' == letter) begin += 4;
					}
					else if (letter == jsonString)//已找到完整字符串
					{
						end = begin;
						if (hasEscape)
						{
							jsonStrBuilder.Clear();
							for (begin = stringBegin.Value; begin + 1 < end; begin++)
							{
								letter = data[begin];
								if (jsonEscape == letter)
								{
									letter = data[++begin];
									if ('u' == letter || 'U' == letter)
									{
										string str = new string(new char[] { data[++begin], data[++begin], data[++begin], data[++begin] });
										jsonStrBuilder.Append(Convert.ToChar(Convert.ToInt32(str, 16)));
									}
									else if (jsonStrEscape.ContainsKey(letter)) jsonStrBuilder.Append(jsonStrEscape[letter]);
								}
								else jsonStrBuilder.Append(data[begin]);
							}
							result = jsonStrBuilder.ToString();
						}
						else result = data.Substring(stringBegin.Value, end - stringBegin.Value - 1);
						return true;
					}
				}
				else if (!isJSONEmpty(letter))//第一个可用字符
				{
					if (letter == jsonString) stringBegin = begin;
					else return false;//不符合
				}
			}
			return false;
		}
		private static char[] jsonInt32 = new char[] { '2', '1', '4', '7', '4', '8', '3', '6', '4' };
		private static bool isJSONInt32(string data, int begin, int count, bool negative)
		{
			if (count < 10) return true;
			if (count > 10) return false;
			for (int index = 0; index < jsonInt32.Length; index++) { if (data[begin + index] > jsonInt32[index]) return false; }
			begin += jsonInt32.Length;
			if ((negative && data[begin] > '8') || (!negative && data[begin] > '7')) return false;
			return true;
		}
		private static bool TryJSONNumber(string data, int begin, out int end, out object result)
		{
			end = begin;
			result = null;

			char letter;
			int? dotIndex = null;
			int? numberBegin = null;
			while (begin < data.Length)
			{
				letter = data[begin++];
				if (numberBegin.HasValue)//已找到部分字符
				{
					if ('.' == letter && !dotIndex.HasValue) dotIndex = begin - 1;//小数
					else if (letter < '0' || letter > '9') { --begin; break; }//结束
				}
				else if (!isJSONEmpty(letter))//第一个可用字符
				{
					if ('-' == letter || ('0' <= letter && '9' >= letter)) numberBegin = begin - 1;
					else return false;//不符合
				}
			}
			if (numberBegin.HasValue)
			{
				bool isNegative = '-' == data[numberBegin.Value];
				if (isNegative) numberBegin++;
				end = begin;
				if (dotIndex.HasValue)//小数
				{
					//小数点左右至少包含一位数字 && 整数部分至少两位时最左边不能为 0
					if (dotIndex.Value > numberBegin && dotIndex.Value + 1 < end && ('0' != data[numberBegin.Value] || dotIndex.Value == numberBegin.Value + 1))
					{
						if (isNegative) --numberBegin;
						result = Convert.ToDouble(data.Substring(numberBegin.Value, end - numberBegin.Value));
						return true;
					}
				}
				else if ('0' != data[numberBegin.Value] || 1 == end - numberBegin.Value)//整数(至少两位时最左边不能为 0)
				{
					if (isJSONInt32(data, numberBegin.Value, end - numberBegin.Value, isNegative))
					{
						if (isNegative) --numberBegin;
						result = Convert.ToInt32(data.Substring(numberBegin.Value, end - numberBegin.Value));
						return true;
					}
					else
					{
						if (isNegative) --numberBegin;
						result = Convert.ToInt64(data.Substring(numberBegin.Value, end - numberBegin.Value));
						return true;
					}
				}
			}
			return false;
		}
		private static char[] jsonTrue = new char[] { 't', 'r', 'u', 'e' };
		private static char[] jsonFalse = new char[] { 'f', 'a', 'l', 's', 'e' };
		private static bool TryJSONBool(string data, int begin, out int end, out object result)
		{
			end = begin;
			result = false;

			char letter;
			int? trueIndex = null;
			int? falseIndex = null;
			while (begin < data.Length)
			{
				letter = data[begin++];
				if (trueIndex.HasValue)//已找到 true 部分字符
				{
					if (letter != jsonTrue[trueIndex.Value]) return false;//不符合
					trueIndex++;
					if (trueIndex.Value == jsonTrue.Length) { end = begin; result = true; return true; }//已找到完整 true 字符串
				}
				else if (falseIndex.HasValue)//已找到 false 部分字符
				{
					if (letter != jsonFalse[falseIndex.Value]) return false;//不符合
					falseIndex++;
					if (falseIndex.Value == jsonFalse.Length) { end = begin; result = false; return true; }//已找到完整 false 字符串
				}
				else if (!isJSONEmpty(letter))//第一个可用字符
				{
					if (letter == jsonTrue[0]) trueIndex = 1;
					else if (letter == jsonFalse[0]) falseIndex = 1;
					else return false;//不符合
				}
			}
			return false;
		}
		private static char[] jsonNull = new char[] { 'n', 'u', 'l', 'l' };
		private static bool TryJSONNull(string data, int begin, out int end)
		{
			end = begin;

			char letter;
			int? nullIndex = null;
			while (begin < data.Length)
			{
				letter = data[begin++];
				if (nullIndex.HasValue)//已找到部分字符
				{
					if (letter != jsonNull[nullIndex.Value]) return false;//不符合
					nullIndex++;
					if (nullIndex.Value == jsonNull.Length) { end = begin; return true; }//已找到完整字符串
				}
				else if (!isJSONEmpty(letter))//第一个可用字符
				{
					if (letter == jsonNull[0]) nullIndex = 0;
					else return false;//不符合
				}
			}
			return false;
		}
		private static bool TryJSONArray(string data, int begin, out int end, out object result)
		{
			end = begin;
			result = null;

			char letter;
			List<object> array = new List<object>();
			bool arrayStart = false;
			while (begin < data.Length)
			{
				letter = data[begin++];
				if (arrayStart)//已找到部分字符
				{
					if (letter == jsonListEnd)//结束
					{
						end = begin;
						result = array;
						return true;
					}
					else if (!isJSONEmpty(letter) && jsonComma != letter)//可用字符
					{
						if (TryJSONMeta(data, begin - 1, out end, out result)) { begin = end; array.Add(result); }
						else return false;
					}
				}
				else if (!isJSONEmpty(letter))//第一个可用字符
				{
					if (letter == jsonListBegin) arrayStart = true;
					else return false;//不符合
				}
			}
			return false;
		}
		private static bool TryJSONDictionary(string data, int begin, out int end, out object result)
		{
			end = begin;
			result = null;

			char letter;
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			bool dictionaryStart = false;
			bool keyTurn = true;
			object key = null;
			object value = null;
			while (begin < data.Length)
			{
				letter = data[begin++];
				if (dictionaryStart)//已找到部分字符
				{
					if (letter == jsonDictionaryEnd)//结束
					{
						end = begin;
						result = dictionary;
						return true;
					}
					else if (!isJSONEmpty(letter) && jsonComma != letter)//可用字符
					{
						if (jsonColon == letter)//键值对分隔字符
						{
							if (null == key) return false;
							keyTurn = false;
						}
						else if (keyTurn)//键
						{
							if (TryJSONString(data, begin - 1, out end, out key)) { begin = end; }
							else return false;
						}
						else//值
						{
							if (TryJSONMeta(data, begin - 1, out end, out value))
							{
								keyTurn = true;
								begin = end;
								dictionary[(string)key] = value;
							}
							else return false;
						}
					}
				}
				else if (!isJSONEmpty(letter))//第一个可用字符
				{
					if (letter == jsonDictionaryBegin) dictionaryStart = true;
					else return false;//不符合
				}
			}
			return false;
		}
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wx771720

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值