|
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
-
- namespace MiniJSONV
- {
- public static class Json
- {
- public static object Deserialize(string json)
- {
- if (json == null)
- {
- return null;
- }
- return Json.Parser.Parse(json);
- }
-
- public static string Serialize(object obj)
- {
- return Json.Serializer.Serialize(obj);
- }
-
- private sealed class Parser : IDisposable
- {
- private Parser(string jsonString)
- {
- this.json = new StringReader(jsonString);
- }
-
- public static bool IsWordBreak(char c)
- {
- return char.IsWhiteSpace(c) || "{}[],:\"".IndexOf(c) != -1;
- }
-
- public static object Parse(string jsonString)
- {
- object result;
- using (Json.Parser parser = new Json.Parser(jsonString))
- {
- result = parser.ParseValue();
- }
- return result;
- }
-
- public void Dispose()
- {
- this.json.Dispose();
- this.json = null;
- }
-
- private Dictionary<string, object> ParseObject()
- {
- Dictionary<string, object> dictionary = new Dictionary<string, object>();
- this.json.Read();
- for (;;)
- {
- Json.Parser.TOKEN nextToken = this.NextToken;
- switch (nextToken)
- {
- case Json.Parser.TOKEN.NONE:
- goto IL_37;
- default:
- if (nextToken != Json.Parser.TOKEN.COMMA)
- {
- string text = this.ParseString();
- if (text == null)
- {
- goto Block_2;
- }
- if (this.NextToken != Json.Parser.TOKEN.COLON)
- {
- goto Block_3;
- }
- this.json.Read();
- dictionary[text] = this.ParseValue();
- }
- break;
- case Json.Parser.TOKEN.CURLY_CLOSE:
- return dictionary;
- }
- }
- IL_37:
- return null;
- Block_2:
- return null;
- Block_3:
- return null;
- }
-
- private List<object> ParseArray()
- {
- List<object> list = new List<object>();
- this.json.Read();
- bool flag = true;
- while (flag)
- {
- Json.Parser.TOKEN nextToken = this.NextToken;
- switch (nextToken)
- {
- case Json.Parser.TOKEN.SQUARED_CLOSE:
- flag = false;
- break;
- default:
- {
- if (nextToken == Json.Parser.TOKEN.NONE)
- {
- return null;
- }
- object item = this.ParseByToken(nextToken);
- list.Add(item);
- break;
- }
- case Json.Parser.TOKEN.COMMA:
- break;
- }
- }
- return list;
- }
-
- private object ParseValue()
- {
- Json.Parser.TOKEN nextToken = this.NextToken;
- return this.ParseByToken(nextToken);
- }
-
- private object ParseByToken(Json.Parser.TOKEN token)
- {
- switch (token)
- {
- case Json.Parser.TOKEN.STRING:
- return this.ParseString();
- case Json.Parser.TOKEN.NUMBER:
- return this.ParseNumber();
- case Json.Parser.TOKEN.TRUE:
- return true;
- case Json.Parser.TOKEN.FALSE:
- return false;
- case Json.Parser.TOKEN.NULL:
- return null;
- default:
- switch (token)
- {
- case Json.Parser.TOKEN.CURLY_OPEN:
- return this.ParseObject();
- case Json.Parser.TOKEN.SQUARED_OPEN:
- return this.ParseArray();
- }
- return null;
- }
- }
-
- private string ParseString()
- {
- StringBuilder stringBuilder = new StringBuilder();
- this.json.Read();
- bool flag = true;
- while (flag)
- {
- if (this.json.Peek() == -1)
- {
- break;
- }
- char nextChar = this.NextChar;
- if (nextChar != '"')
- {
- if (nextChar != '\\')
- {
- stringBuilder.Append(nextChar);
- }
- else if (this.json.Peek() == -1)
- {
- flag = false;
- }
- else
- {
- nextChar = this.NextChar;
- switch (nextChar)
- {
- case 'r':
- stringBuilder.Append('\r');
- break;
- default:
- if (nextChar != '"' && nextChar != '/' && nextChar != '\\')
- {
- if (nextChar != 'b')
- {
- if (nextChar != 'f')
- {
- if (nextChar == 'n')
- {
- stringBuilder.Append('\n');
- }
- }
- else
- {
- stringBuilder.Append('\f');
- }
- }
- else
- {
- stringBuilder.Append('\b');
- }
- }
- else
- {
- stringBuilder.Append(nextChar);
- }
- break;
- case 't':
- stringBuilder.Append('\t');
- break;
- case 'u':
- {
- char[] array = new char[4];
- for (int i = 0; i < 4; i++)
- {
- array[i] = this.NextChar;
- }
- stringBuilder.Append((char)Convert.ToInt32(new string(array), 16));
- break;
- }
- }
- }
- }
- else
- {
- flag = false;
- }
- }
- return stringBuilder.ToString();
- }
-
- private object ParseNumber()
- {
- string nextWord = this.NextWord;
- if (nextWord.IndexOf('.') == -1)
- {
- long num;
- long.TryParse(nextWord, out num);
- return num;
- }
- double num2;
- double.TryParse(nextWord, out num2);
- return num2;
- }
-
- private void EatWhitespace()
- {
- while (char.IsWhiteSpace(this.PeekChar))
- {
- this.json.Read();
- if (this.json.Peek() == -1)
- {
- break;
- }
- }
- }
-
- private char PeekChar
- {
- get
- {
- return Convert.ToChar(this.json.Peek());
- }
- }
-
- private char NextChar
- {
- get
- {
- return Convert.ToChar(this.json.Read());
- }
- }
-
- private string NextWord
- {
- get
- {
- StringBuilder stringBuilder = new StringBuilder();
- while (!Json.Parser.IsWordBreak(this.PeekChar))
- {
- stringBuilder.Append(this.NextChar);
- if (this.json.Peek() == -1)
- {
- break;
- }
- }
- return stringBuilder.ToString();
- }
- }
-
- private Json.Parser.TOKEN NextToken
- {
- get
- {
- this.EatWhitespace();
- if (this.json.Peek() == -1)
- {
- return Json.Parser.TOKEN.NONE;
- }
- char peekChar = this.PeekChar;
- switch (peekChar)
- {
- case ',':
- this.json.Read();
- return Json.Parser.TOKEN.COMMA;
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- return Json.Parser.TOKEN.NUMBER;
- default:
- switch (peekChar)
- {
- case '[':
- return Json.Parser.TOKEN.SQUARED_OPEN;
- default:
- switch (peekChar)
- {
- case '{':
- return Json.Parser.TOKEN.CURLY_OPEN;
- default:
- if (peekChar != '"')
- {
- string nextWord = this.NextWord;
- if (nextWord != null)
- {
- if (nextWord == "false")
- {
- return Json.Parser.TOKEN.FALSE;
- }
- if (nextWord == "true")
- {
- return Json.Parser.TOKEN.TRUE;
- }
- if (nextWord == "null")
- {
- return Json.Parser.TOKEN.NULL;
- }
- }
- return Json.Parser.TOKEN.NONE;
- }
- return Json.Parser.TOKEN.STRING;
- case '}':
- this.json.Read();
- return Json.Parser.TOKEN.CURLY_CLOSE;
- }
- break;
- case ']':
- this.json.Read();
- return Json.Parser.TOKEN.SQUARED_CLOSE;
- }
- break;
- case ':':
- return Json.Parser.TOKEN.COLON;
- }
- }
- }
-
- private const string WORD_BREAK = "{}[],:\"";
-
- private StringReader json;
-
- private enum TOKEN
- {
- NONE,
- CURLY_OPEN,
- CURLY_CLOSE,
- SQUARED_OPEN,
- SQUARED_CLOSE,
- COLON,
- COMMA,
- STRING,
- NUMBER,
- TRUE,
- FALSE,
- NULL
- }
- }
-
- private sealed class Serializer
- {
- private Serializer()
- {
- this.builder = new StringBuilder();
- }
-
- public static string Serialize(object obj)
- {
- Json.Serializer serializer = new Json.Serializer();
- serializer.SerializeValue(obj);
- return serializer.builder.ToString();
- }
-
- private void SerializeValue(object value)
- {
- string str;
- IList anArray;
- IDictionary obj;
- if (value == null)
- {
- this.builder.Append("null");
- }
- else if ((str = (value as string)) != null)
- {
- this.SerializeString(str);
- }
- else if (value is bool)
- {
- this.builder.Append((!(bool)value) ? "false" : "true");
- }
- else if ((anArray = (value as IList)) != null)
- {
- this.SerializeArray(anArray);
- }
- else if ((obj = (value as IDictionary)) != null)
- {
- this.SerializeObject(obj);
- }
- else if (value is char)
- {
- this.SerializeString(new string((char)value, 1));
- }
- else
- {
- this.SerializeOther(value);
- }
- }
-
- private void SerializeObject(IDictionary obj)
- {
- bool flag = true;
- this.builder.Append('{');
- IEnumerator enumerator = obj.Keys.GetEnumerator();
- try
- {
- while (enumerator.MoveNext())
- {
- object obj2 = enumerator.Current;
- if (!flag)
- {
- this.builder.Append(',');
- }
- this.SerializeString(obj2.ToString());
- this.builder.Append(':');
- this.SerializeValue(obj[obj2]);
- flag = false;
- }
- }
- finally
- {
- IDisposable disposable;
- if ((disposable = (enumerator as IDisposable)) != null)
- {
- disposable.Dispose();
- }
- }
- this.builder.Append('}');
- }
-
- private void SerializeArray(IList anArray)
- {
- this.builder.Append('[');
- bool flag = true;
- IEnumerator enumerator = anArray.GetEnumerator();
- try
- {
- while (enumerator.MoveNext())
- {
- object value = enumerator.Current;
- if (!flag)
- {
- this.builder.Append(',');
- }
- this.SerializeValue(value);
- flag = false;
- }
- }
- finally
- {
- IDisposable disposable;
- if ((disposable = (enumerator as IDisposable)) != null)
- {
- disposable.Dispose();
- }
- }
- this.builder.Append(']');
- }
-
- private void SerializeString(string str)
- {
- this.builder.Append('"');
- char[] array = str.ToCharArray();
- foreach (char c in array)
- {
- switch (c)
- {
- case '\b':
- this.builder.Append("\\b");
- break;
- case '\t':
- this.builder.Append("\\t");
- break;
- case '\n':
- this.builder.Append("\\n");
- break;
- default:
- if (c != '"')
- {
- if (c != '\\')
- {
- int num = Convert.ToInt32(c);
- if (num >= 32 && num <= 126)
- {
- this.builder.Append(c);
- }
- else
- {
- this.builder.Append("\\u");
- this.builder.Append(num.ToString("x4"));
- }
- }
- else
- {
- this.builder.Append("\\\\");
- }
- }
- else
- {
- this.builder.Append("\\\"");
- }
- break;
- case '\f':
- this.builder.Append("\\f");
- break;
- case '\r':
- this.builder.Append("\\r");
- break;
- }
- }
- this.builder.Append('"');
- }
-
- private void SerializeOther(object value)
- {
- if (value is float)
- {
- this.builder.Append(((float)value).ToString("R"));
- }
- else if (value is int || value is uint || value is long || value is sbyte || value is byte || value is short || value is ushort || value is ulong)
- {
- this.builder.Append(value);
- }
- else if (value is double || value is decimal)
- {
- this.builder.Append(Convert.ToDouble(value).ToString("R"));
- }
- else
- {
- this.SerializeString(value.ToString());
- }
- }
-
- private StringBuilder builder;
- }
- }
- }
|