c#的几个Json库
MiniJSON
SimpleJson
litjson
NewtonJson
其中MiniJSON最简单,所以这边也是学习这个库的Json解析部分(注意:只涉及解析,没有生成json)。
整体代码也没有用到特别的算法什么的,就是一个一个字符的读取,然后根据读到的边界标识符来进行后续的读取,边界标识符的话就是:{}、[]、""、:、,等。
单引号、注释这些的话没有支持,加上各种兼容性估计代码就会复杂很多。
/* * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html * * Simplified it so that it doesn't throw exceptions * and can be used in Unity iPhone with maximum code stripping. * */ using System; using System.Collections.Generic; using System.IO; using System.Text; using UnityEngine; public static class Json { /// <summary> /// Parses the string json into a value /// </summary> /// <param name="json">A JSON string.</param> /// <returns>An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false</returns> public static object Deserialize(string json) { if (json == null) return null; return Parser.Parse(json); } private sealed class Parser : IDisposable { private const string WORD_BREAK = "{}[],:\""; private StringReader json; private Parser(string jsonString) { json = new StringReader(jsonString); } /// <summary> /// 探查下一个字符(读指针不变) /// </summary> private char PeekChar { get { return Convert.ToChar(json.Peek()); } } /// <summary> /// 读下一个字符(读指针往后+1) /// </summary> private char NextChar { get { return Convert.ToChar(json.Read()); } } private string NextWord { get { var word = new StringBuilder(); while (!IsWordBreak(PeekChar)) { word.Append(NextChar); if (json.Peek() == -1) break; } return word.ToString(); } } /// <summary> /// 通过1个字符, 确定标识符, 然后以此确定接下来怎么做 /// </summary> private TOKEN NextToken { get { EatWhitespace(); if (json.Peek() == -1) return TOKEN.NONE; switch (PeekChar) { case '{': return TOKEN.CURLY_OPEN; case '}': json.Read(); return TOKEN.CURLY_CLOSE; case '[': return TOKEN.SQUARED_OPEN; case ']': json.Read(); return TOKEN.SQUARED_CLOSE; case ',': json.Read(); return TOKEN.COMMA; case '"': return TOKEN.STRING; case ':': return TOKEN.COLON; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': return TOKEN.NUMBER; } switch (NextWord) { case "false": return TOKEN.FALSE; case "true": return TOKEN.TRUE; case "null": return TOKEN.NULL; } //jsonStr="abc", 就是none的 return TOKEN.NONE; } } public void Dispose() { json.Dispose(); json = null; } /// <summary> /// 断词字符: abc: abc ,abc{, abc}, abc[, abc]等 /// </summary> public static bool IsWordBreak(char c) { return char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1; } public static object Parse(string jsonString) { using (var instance = new Parser(jsonString)) { return instance.ParseValue(); } } private Dictionary<string, object> ParseObject() { var table = new Dictionary<string, object>(); // ditch opening brace json.Read(); // { while (true) { switch (NextToken) { case TOKEN.NONE: // {abc} //不合法object, 得到null return null; case TOKEN.COMMA: // {,, "key":1}也不会报错 continue; case TOKEN.CURLY_CLOSE: return table; default: // {false} //ParseString()拿到空, 然后EatWhiteSpace报错 // {012} // ParseString()拿到012}, 然后EatWhiteSpace报错 // {{}} //报错 // {[]} //报错 // name var keyName = ParseString(); if (keyName == null) { return null; } Debug.Log($"'{keyName}'"); // : if (NextToken != TOKEN.COLON) // {"abc"123}这样的情况, 无效的对象 return null; // ditch the colon json.Read(); // value table[keyName] = ParseValue(); break; } } } private List<object> ParseArray() { var array = new List<object>(); // ditch opening bracket json.Read(); // [ var parsing = true; while (parsing) { var nextToken = NextToken; switch (nextToken) { case TOKEN.NONE: // [abc] //不合法array, 得到null return null; case TOKEN.COMMA: // {,, 123}不会报错, 最终能得到正确的array continue; case TOKEN.SQUARED_CLOSE: parsing = false; break; default: var value = ParseByToken(nextToken); array.Add(value); break; } } return array; } //解析json的下一个值(number, bool, string, unicode, null, object, array) private object ParseValue() { var nextToken = NextToken; return ParseByToken(nextToken); } //根据开始token读后面的值 private object ParseByToken(TOKEN token) { switch (token) { case TOKEN.STRING: return ParseString(); case TOKEN.NUMBER: return ParseNumber(); case TOKEN.CURLY_OPEN: return ParseObject(); case TOKEN.SQUARED_OPEN: return ParseArray(); case TOKEN.TRUE: return true; case TOKEN.FALSE: return false; case TOKEN.NULL: return null; default: return null; } } /// <summary> /// Token为STRING时, 调用该函数才正常 /// </summary> private string ParseString() { var s = new StringBuilder(); char c; // ditch opening quote json.Read(); var parsing = true; while (parsing) { if (json.Peek() == -1) { parsing = false; break; } c = NextChar; switch (c) { case '"': //结束双引号 parsing = false; break; case '\\': // 这样? { "key":"abc\ if (json.Peek() == -1) { parsing = false; break; } c = NextChar; switch (c) { case '"': // \"就是Append(") case '\\': // \\就是Append(\) case '/': // \/就是Append(/) s.Append(c); break; case 'b': s.Append('\b'); break; case 'f': s.Append('\f'); break; case 'n': s.Append('\n'); //linux换行 break; case 'r': s.Append('\r'); //mac换行 break; case 't': s.Append('\t'); //tab break; case 'u': // "\u012"会报错 var hex = new char[4]; for (var i = 0; i < 4; i++) hex[i] = NextChar; s.Append((char)Convert.ToInt32(new string(hex), 16)); break; } break; default: s.Append(c); break; } } Debug.Log($"ParseString: {s.ToString()}"); return s.ToString(); } private object ParseNumber() { var number = NextWord; // {"abc": 1-23}, 不会报错, 会得到abc的值为0 if (number.IndexOf('.') == -1) { long parsedInt; long.TryParse(number, out parsedInt); Debug.Log($"ParseNumber: str:{number}, val:{parsedInt}"); return parsedInt; } double parsedDouble; double.TryParse(number, out parsedDouble); Debug.Log($"ParseNumber: str:{number}, val:{parsedDouble}"); return parsedDouble; } private void EatWhitespace() { while (char.IsWhiteSpace(PeekChar)) { json.Read(); if (json.Peek() == -1) break; } } private enum TOKEN { NONE, CURLY_OPEN, // { CURLY_CLOSE, // } SQUARED_OPEN, // [ SQUARED_CLOSE, // ] COLON, // : COMMA, // , STRING, // " NUMBER, // 负号或数字 TRUE, // true FALSE, // false NULL, // null }; } }
参考
用C#实现一个迷你json库,无需引入dll(可直接放到Unity中使用)_林新发的博客-CSDN博客
【Unity游戏开发】跟着马三一起魔改LitJson - 马三小伙儿 - 博客园 (cnblogs.com)
标签:case,return,TOKEN,private,break,json,源码,解析 From: https://www.cnblogs.com/sailJs/p/17597570.html