├── README.md
├── UnitTest
├── UnitTest.sln
├── ParserUnitTests.cs
└── UnitTests.csproj
├── LICENSE
├── TinyJSONExt.cs
└── TinyJSON.cs
/README.md:
--------------------------------------------------------------------------------
1 | # TinyJSON
2 | C#实现的JSON解析器,核心目标是效率和使用简单,并附带有严格的语法检查。
3 | 该解析器扩展了一个注释相关的语法,/**/包围的内容被视为注释,此外完全遵循JSON的语法规范(注释是否合法可以通过选项设置,默认不支持注释)。
4 | 此外解析器还支持Object的键不需要引号,允许Object/Array的最后一个元素保留逗号
5 |
6 |
7 | 接下来需要添加的特性:
8 |
9 | + 增加对象序列化成JSON字符串的自动反射支持
10 | + JSON解析支持严格模式和禁止注释的选项(此时只支持解析完全符合标准的JSON字符串)
11 | + JSON解析时出错,提供详细错误信息
12 |
13 | >-------------2018-5-10-------------
14 | >
15 | >修改API版本(破坏向下兼容,如果要使用原来的版本,请使用v1.0分支),并提供JSON字符串映射到对象的自动反射支持
16 |
17 | >-------------2016-10-31-------------
18 | >
19 | >序列化新增支持匿名函数的接口
20 |
21 | >-------------2016-06-27-------------
22 | >
23 | >修改底层实现,增加新的SAX事件类型解析支持(便于集成到自定义数据类型解析),原DOM解析接口基于SAX解析接口实现,Printer增加Format格式化接口(同样基于SAX接口实现)
--------------------------------------------------------------------------------
/UnitTest/UnitTest.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests.csproj", "{36E24A29-D440-4D6B-8333-E974E753383D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {36E24A29-D440-4D6B-8333-E974E753383D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {36E24A29-D440-4D6B-8333-E974E753383D}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {36E24A29-D440-4D6B-8333-E974E753383D}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {36E24A29-D440-4D6B-8333-E974E753383D}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 libla
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/UnitTest/ParserUnitTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 |
3 | namespace TinyJSON.UnitTests
4 | {
5 | [TestClass()]
6 | public class ParserUnitTests
7 | {
8 | [TestMethod]
9 | public void LoadUnitTest()
10 | {
11 | string right = @"{
12 | ""array"": [1.44, 2, 3],
13 | ""object"": {""key1"":""value1"", ""key2"":256},
14 | ""string"": ""The quick brown fox \""jumps\"" over the lazy dog "",
15 | ""unicode"": ""\u3041 Men\u54c8 sesiu00f3n"",
16 | ""int"": 65536,
17 | ""float"": -3.1415926e-1,
18 | ""bool"": true,
19 | ""null"": null
20 | }";
21 | string wrong = @"[,]";
22 | JSON json = new JSON();
23 | Assert.IsNotNull(json.Parse(right));
24 | Assert.IsNull(json.Parse(wrong));
25 | Assert.IsNotNull(json.Dump(json.Parse(right)));
26 | Assert.IsNotNull(json.Parse(json.Dump(json.Parse(right))));
27 | }
28 |
29 | [TestMethod]
30 | public void ReflectUnitTest()
31 | {
32 | string right = @"{
33 | ""array"": [1.44, 2, 3],
34 | ""object"": {""key1"":""value1"", ""key2"":256},
35 | ""string"": ""The quick brown fox \""jumps\"" over the lazy dog "",
36 | ""unicode"": ""\u3041 Men\u54c8 sesiu00f3n"",
37 | ""int"": 65536,
38 | ""float"": -3.1415926e-1,
39 | ""bool"": true
40 | }";
41 |
42 | ReflectTest test = new ReflectTest();
43 | JSON json = new JSON();
44 | JSON.Value? value = json.Parse(right);
45 | Assert.IsTrue(value.HasValue);
46 | Assert.IsNotNull(value.Value.AsObject());
47 | Assert.IsTrue(test.Read(value.Value.AsObject()));
48 | Assert.AreEqual(test.array.Length, 3);
49 | Assert.AreEqual(test.obj.key1, "value1");
50 | Assert.AreEqual(test.obj.key2, 256);
51 | Assert.AreEqual(test.str, @"The quick brown fox ""jumps"" over the lazy dog ");
52 | Assert.AreEqual(test.i, 65536);
53 | Assert.AreEqual(test.f, -3.1415926e-1);
54 | Assert.AreEqual(test.b, true);
55 | }
56 |
57 | private class ReflectTest : JSON.Readable
58 | {
59 | public double[] array;
60 | [JSON.Entity(Name = "object")] public ReflectSubTest obj;
61 | [JSON.Entity(Name = "string")] public string str;
62 | public string unicode;
63 | [JSON.Entity(Name = "int")] public int i;
64 | [JSON.Entity(Name = "float")] public double f;
65 | [JSON.Entity(Name = "bool")] public bool b;
66 |
67 | public bool Read(JSON.Object o)
68 | {
69 | return o.Help(this);
70 | }
71 | }
72 |
73 | private class ReflectSubTest : JSON.Readable
74 | {
75 | public string key1;
76 | public int key2;
77 |
78 | public bool Read(JSON.Object o)
79 | {
80 | return o.Help(this);
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/UnitTest/UnitTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {36E24A29-D440-4D6B-8333-E974E753383D}
7 | Library
8 | Properties
9 | UnitTestUnitTests
10 | UnitTestUnitTests
11 | v4.5
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 10.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 |
29 |
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | False
62 |
63 |
64 | False
65 |
66 |
67 | False
68 |
69 |
70 | False
71 |
72 |
73 |
74 |
75 |
76 |
77 |
84 |
--------------------------------------------------------------------------------
/TinyJSONExt.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Collections.Generic;
4 |
5 | namespace TinyJSON
6 | {
7 | public sealed partial class JSON
8 | {
9 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
10 | public class EntityAttribute : Attribute
11 | {
12 | public string Name;
13 | public bool Required;
14 |
15 | public EntityAttribute()
16 | {
17 | Name = null;
18 | Required = false;
19 | }
20 | }
21 | }
22 |
23 | public static partial class JSONExt
24 | {
25 | public static bool Help(this JSON.Object o, ref T value) where T : struct, JSON.Readable
26 | {
27 | return ReadHelper.Read(o, ref value);
28 | }
29 |
30 | public static bool Help(this JSON.Object o, T value) where T : class, JSON.Readable
31 | {
32 | return ReadHelper.Read(o, ref value);
33 | }
34 |
35 | #region 自动映射Object和指定数据类型
36 | private static bool Get(JSON.Object o, string key, ref bool b)
37 | {
38 | return o.Get(key, ref b);
39 | }
40 |
41 | private static bool Get(JSON.Object o, string key, ref int i)
42 | {
43 | return o.Get(key, ref i);
44 | }
45 |
46 | private static bool Get(JSON.Object o, string key, ref double d)
47 | {
48 | return o.Get(key, ref d);
49 | }
50 |
51 | private static bool Get(JSON.Object o, string key, ref string s)
52 | {
53 | return o.Get(key, ref s);
54 | }
55 |
56 | private static bool Get(JSON.Object o, string key, ref JSON.Object oo)
57 | {
58 | return o.Get(key, ref oo);
59 | }
60 |
61 | private static bool Get(JSON.Object o, string key, ref JSON.Array a)
62 | {
63 | return o.Get(key, ref a);
64 | }
65 |
66 | private static bool GetEnum(JSON.Object o, Type type, string key, ref object value)
67 | {
68 | string result = default(string);
69 | if (!o.Get(key, ref result))
70 | return false;
71 | try
72 | {
73 | value = Enum.Parse(type, result);
74 | }
75 | catch (Exception)
76 | {
77 | return false;
78 | }
79 | return true;
80 | }
81 |
82 | private static bool GetEnumNullable(JSON.Object o, Type type, string key, ref object value)
83 | {
84 | string result = default(string);
85 | if (!o.Get(key, ref result))
86 | return false;
87 | if (string.IsNullOrEmpty(result))
88 | {
89 | value = Activator.CreateInstance(typeof(Nullable<>).MakeGenericType(type));
90 | return true;
91 | }
92 | object tmp;
93 | try
94 | {
95 | tmp = Enum.Parse(type, result);
96 | }
97 | catch (Exception)
98 | {
99 | return false;
100 | }
101 | value = Activator.CreateInstance(typeof(Nullable<>).MakeGenericType(type), tmp);
102 | return true;
103 | }
104 |
105 | private static bool GetEnumArray(JSON.Object o, Type type, string key, ref object value)
106 | {
107 | JSON.Array result = default(JSON.Array);
108 | if (!o.Get(key, ref result))
109 | return false;
110 | int count = result.Count;
111 | Array array = Array.CreateInstance(type, count);
112 | for (int i = 0; i < count; ++i)
113 | {
114 | string tmp1 = default(string);
115 | if (!o.Get(key, ref tmp1))
116 | return false;
117 | object tmp2;
118 | try
119 | {
120 | tmp2 = Enum.Parse(type, tmp1);
121 | }
122 | catch (Exception)
123 | {
124 | return false;
125 | }
126 | array.SetValue(tmp2, i);
127 | }
128 | value = array;
129 | return true;
130 | }
131 |
132 | private static bool GetType(JSON.Object o, Type type, string key, ref object value)
133 | {
134 | JSON.Object result = default(JSON.Object);
135 | if (!o.Get(key, ref result))
136 | return false;
137 | JSON.Readable tmp;
138 | try
139 | {
140 | tmp = (JSON.Readable)Activator.CreateInstance(type);
141 | }
142 | catch (Exception)
143 | {
144 | return false;
145 | }
146 | if (!tmp.Read(result))
147 | return false;
148 | value = tmp;
149 | return true;
150 | }
151 |
152 | private static bool GetTypeNullable(JSON.Object o, Type type, string key, ref object value)
153 | {
154 | JSON.Object result = default(JSON.Object);
155 | if (!o.Get(key, ref result))
156 | return false;
157 | if (result == null)
158 | {
159 | value = Activator.CreateInstance(typeof(Nullable<>).MakeGenericType(type));
160 | return true;
161 | }
162 | JSON.Readable tmp;
163 | try
164 | {
165 | tmp = (JSON.Readable)Activator.CreateInstance(type);
166 | }
167 | catch (Exception)
168 | {
169 | return false;
170 | }
171 | if (!tmp.Read(result))
172 | return false;
173 | value = Activator.CreateInstance(typeof(Nullable<>).MakeGenericType(type), tmp);
174 | return true;
175 | }
176 |
177 | private static bool GetTypeArray(JSON.Object o, Type type, string key, ref object value)
178 | {
179 | JSON.Array result = default(JSON.Array);
180 | if (!o.Get(key, ref result))
181 | return false;
182 | int count = result.Count;
183 | Array array = Array.CreateInstance(type, count);
184 | for (int i = 0; i < count; ++i)
185 | {
186 | JSON.Object tmp1 = default(JSON.Object);
187 | if (!o.Get(key, ref tmp1))
188 | return false;
189 | JSON.Readable tmp2;
190 | try
191 | {
192 | tmp2 = (JSON.Readable)Activator.CreateInstance(type);
193 | }
194 | catch (Exception)
195 | {
196 | return false;
197 | }
198 | if (!tmp2.Read(tmp1))
199 | return false;
200 | array.SetValue(tmp2, i);
201 | }
202 | value = array;
203 | return true;
204 | }
205 |
206 | private enum Modify
207 | {
208 | None,
209 | Array,
210 | Option,
211 | }
212 |
213 | private static MethodInfo FindReadValue(Type type, out bool needtype)
214 | {
215 | MethodInfo method = typeof(JSONExt).GetMethod("Get",
216 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null,
217 | new[] {typeof(JSON.Object), typeof(string), type.MakeByRefType()}, null);
218 | if (method != null)
219 | {
220 | needtype = false;
221 | return method;
222 | }
223 | needtype = true;
224 | Modify modify = Modify.None;
225 | if (type.IsArray)
226 | {
227 | if (type.GetArrayRank() > 1)
228 | return null;
229 | modify = Modify.Array;
230 | type = type.GetElementType();
231 | }
232 | else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
233 | {
234 | modify = Modify.Option;
235 | type = type.GetGenericArguments()[0];
236 | }
237 | if (type.IsEnum)
238 | {
239 | return typeof(JSONExt).GetMethod(
240 | modify == Modify.Array ? "GetEnumArray" : (modify == Modify.Option ? "GetEnumNullable" : "GetEnum"),
241 | BindingFlags.Static | BindingFlags.NonPublic, null,
242 | new[] {typeof(JSON.Object), typeof(Type), typeof(string), typeof(object).MakeByRefType()}, null);
243 | }
244 | if (typeof(JSON.Readable).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null)
245 | {
246 | return typeof(JSONExt).GetMethod(
247 | modify == Modify.Array ? "GetTypeArray" : (modify == Modify.Option ? "GetTypeNullable" : "GetType"),
248 | BindingFlags.Static | BindingFlags.NonPublic, null,
249 | new[] {typeof(JSON.Object), typeof(Type), typeof(string), typeof(object).MakeByRefType()}, null);
250 | }
251 | return null;
252 | }
253 |
254 | private static string GetName(MemberInfo member)
255 | {
256 | var attrs = member.GetCustomAttributes(typeof(JSON.EntityAttribute), true);
257 | if (attrs.Length != 0)
258 | {
259 | string s = ((JSON.EntityAttribute)attrs[0]).Name;
260 | if (!string.IsNullOrEmpty(s))
261 | return s;
262 | }
263 | return member.Name;
264 | }
265 |
266 | private static bool IsRequired(MemberInfo member)
267 | {
268 | var attrs = member.GetCustomAttributes(typeof(JSON.EntityAttribute), true);
269 | return attrs.Length != 0 && ((JSON.EntityAttribute)attrs[0]).Required;
270 | }
271 |
272 | private static class ReadHelper
273 | {
274 | private delegate bool Reader(JSON.Object o, ref T value);
275 | private static readonly List readers;
276 |
277 | static ReadHelper()
278 | {
279 | readers = new List();
280 | foreach (MemberInfo member in typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance))
281 | {
282 | Type type;
283 | if (member.MemberType == MemberTypes.Field)
284 | {
285 | type = ((FieldInfo)member).FieldType;
286 | }
287 | else
288 | {
289 | if (member.MemberType != MemberTypes.Property)
290 | continue;
291 | PropertyInfo property = (PropertyInfo)member;
292 | if (property.GetSetMethod() == null || property.GetGetMethod() == null)
293 | continue;
294 | type = property.PropertyType;
295 | }
296 | bool needtype;
297 | MethodInfo method = FindReadValue(type, out needtype);
298 | if (method == null)
299 | {
300 | string name = member.Name;
301 | readers.Add((JSON.Object o, ref T value) => { throw new MissingFieldException(typeof(T).FullName, name); });
302 | }
303 | else
304 | {
305 | string name = GetName(member);
306 | bool require = IsRequired(member);
307 | if (needtype)
308 | {
309 | if (member.MemberType == MemberTypes.Field)
310 | {
311 | FieldInfo field = (FieldInfo)member;
312 | readers.Add((JSON.Object o, ref T value) =>
313 | {
314 | object[] args = new object[4];
315 | args[0] = o;
316 | args[1] = type;
317 | args[2] = name;
318 | args[3] = field.GetValue(value);
319 | bool result = (bool)method.Invoke(null, args);
320 | if (!result)
321 | return !require;
322 | field.SetValue(value, args[3]);
323 | return true;
324 | });
325 | }
326 | else
327 | {
328 | PropertyInfo property = (PropertyInfo)member;
329 | MethodInfo setter = property.GetSetMethod();
330 | MethodInfo getter = property.GetGetMethod();
331 | readers.Add((JSON.Object o, ref T value) =>
332 | {
333 | object[] args = new object[4];
334 | args[0] = o;
335 | args[1] = type;
336 | args[2] = name;
337 | args[3] = getter.Invoke(value, null);
338 | bool result = (bool)method.Invoke(null, args);
339 | if (!result)
340 | return !require;
341 | setter.Invoke(value, new[] {args[3]});
342 | return true;
343 | });
344 | }
345 | }
346 | else
347 | {
348 | if (member.MemberType == MemberTypes.Field)
349 | {
350 | FieldInfo field = (FieldInfo)member;
351 | readers.Add((JSON.Object o, ref T value) =>
352 | {
353 | object[] args = new object[3];
354 | args[0] = o;
355 | args[1] = name;
356 | args[2] = field.GetValue(value);
357 | bool result = (bool)method.Invoke(null, args);
358 | if (!result)
359 | return !require;
360 | field.SetValue(value, args[2]);
361 | return true;
362 | });
363 | }
364 | else
365 | {
366 | PropertyInfo property = (PropertyInfo)member;
367 | MethodInfo setter = property.GetSetMethod();
368 | MethodInfo getter = property.GetGetMethod();
369 | readers.Add((JSON.Object o, ref T value) =>
370 | {
371 | object[] args = new object[4];
372 | args[0] = o;
373 | args[1] = name;
374 | args[2] = getter.Invoke(value, null);
375 | bool result = (bool)method.Invoke(null, args);
376 | if (!result)
377 | return !require;
378 | setter.Invoke(value, new[] {args[2]});
379 | return true;
380 | });
381 | }
382 | }
383 | }
384 | }
385 | }
386 |
387 | public static bool Read(JSON.Object o, ref T value)
388 | {
389 | for (int i = 0, j = readers.Count; i < j; ++i)
390 | {
391 | if (!readers[i](o, ref value))
392 | return false;
393 | }
394 | return true;
395 | }
396 | }
397 | #endregion
398 | }
399 | }
--------------------------------------------------------------------------------
/TinyJSON.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 | using System.Globalization;
5 | using System.Collections;
6 | using System.Collections.Generic;
7 |
8 | namespace TinyJSON
9 | {
10 | public sealed partial class JSON
11 | {
12 | public abstract class Object : IEnumerable
13 | {
14 | protected abstract IEnumerator Keys();
15 | public abstract Type Type(string key);
16 |
17 | public abstract bool Get(string key, ref bool b);
18 | public abstract bool Get(string key, ref int i);
19 | public abstract bool Get(string key, ref double d);
20 | public abstract bool Get(string key, ref string s);
21 | public abstract bool Get(string key, ref Object o);
22 | public abstract bool Get(string key, ref Array a);
23 |
24 | public Value this[string key]
25 | {
26 | get
27 | {
28 | switch (Type(key))
29 | {
30 | case JSON.Type.Bool:
31 | {
32 | bool b = false;
33 | if (Get(key, ref b))
34 | return b;
35 | }
36 | break;
37 | case JSON.Type.Int:
38 | {
39 | int i = 0;
40 | if (Get(key, ref i))
41 | return i;
42 | }
43 | break;
44 | case JSON.Type.Double:
45 | {
46 | double d = 0;
47 | if (Get(key, ref d))
48 | return d;
49 | }
50 | break;
51 | case JSON.Type.String:
52 | {
53 | string s = null;
54 | if (Get(key, ref s))
55 | return s;
56 | }
57 | break;
58 | case JSON.Type.Object:
59 | {
60 | Object o = null;
61 | if (Get(key, ref o))
62 | return o;
63 | }
64 | break;
65 | case JSON.Type.Array:
66 | {
67 | Array a = null;
68 | if (Get(key, ref a))
69 | return a;
70 | }
71 | break;
72 | }
73 | return Value.Null;
74 | }
75 | }
76 |
77 | public IEnumerator GetEnumerator()
78 | {
79 | return Keys();
80 | }
81 |
82 | IEnumerator IEnumerable.GetEnumerator()
83 | {
84 | return GetEnumerator();
85 | }
86 | }
87 |
88 | public abstract class Array : IEnumerable
89 | {
90 | public abstract int Count { get; }
91 | public abstract Type Type(int index);
92 |
93 | public abstract bool Get(int index, ref bool b);
94 | public abstract bool Get(int index, ref int i);
95 | public abstract bool Get(int index, ref double d);
96 | public abstract bool Get(int index, ref string s);
97 | public abstract bool Get(int index, ref Object o);
98 | public abstract bool Get(int index, ref Array a);
99 |
100 | public Value this[int index]
101 | {
102 | get
103 | {
104 | switch (Type(index))
105 | {
106 | case JSON.Type.Bool:
107 | {
108 | bool b = false;
109 | if (Get(index, ref b))
110 | return b;
111 | }
112 | break;
113 | case JSON.Type.Int:
114 | {
115 | int i = 0;
116 | if (Get(index, ref i))
117 | return i;
118 | }
119 | break;
120 | case JSON.Type.Double:
121 | {
122 | double d = 0;
123 | if (Get(index, ref d))
124 | return d;
125 | }
126 | break;
127 | case JSON.Type.String:
128 | {
129 | string s = null;
130 | if (Get(index, ref s))
131 | return s;
132 | }
133 | break;
134 | case JSON.Type.Object:
135 | {
136 | Object o = null;
137 | if (Get(index, ref o))
138 | return o;
139 | }
140 | break;
141 | case JSON.Type.Array:
142 | {
143 | Array a = null;
144 | if (Get(index, ref a))
145 | return a;
146 | }
147 | break;
148 | }
149 | return Value.Null;
150 | }
151 | }
152 |
153 | public Enumerator GetEnumerator()
154 | {
155 | return new Enumerator(this);
156 | }
157 |
158 | IEnumerator IEnumerable.GetEnumerator()
159 | {
160 | return GetEnumerator();
161 | }
162 |
163 | IEnumerator IEnumerable.GetEnumerator()
164 | {
165 | return GetEnumerator();
166 | }
167 |
168 | public struct Enumerator : IEnumerator
169 | {
170 | private readonly Array array;
171 | private int index;
172 |
173 | internal Enumerator(Array array)
174 | {
175 | this.array = array;
176 | this.index = -1;
177 | }
178 |
179 | public void Dispose() {}
180 |
181 | public bool MoveNext()
182 | {
183 | if (array == null)
184 | return false;
185 | if (++index >= array.Count)
186 | return false;
187 | return true;
188 | }
189 |
190 | public void Reset()
191 | {
192 | index = -1;
193 | }
194 |
195 | public Value Current
196 | {
197 | get { return array[index]; }
198 | }
199 |
200 | object IEnumerator.Current
201 | {
202 | get { return Current; }
203 | }
204 | }
205 | }
206 |
207 | public struct Value
208 | {
209 | public Type Type { get; private set; }
210 | private bool b;
211 | private int i;
212 | private double d;
213 | private string s;
214 | private Object o;
215 | private Array a;
216 |
217 | public static readonly Value Null = new Value {Type = Type.Null};
218 |
219 | public static implicit operator Value(bool b)
220 | {
221 | return new Value {Type = Type.Bool, b = b};
222 | }
223 |
224 | public static implicit operator Value(bool? b)
225 | {
226 | return b.HasValue ? new Value {Type = Type.Bool, b = b.Value} : Null;
227 | }
228 |
229 | public static implicit operator Value(int i)
230 | {
231 | return new Value {Type = Type.Int, i = i};
232 | }
233 |
234 | public static implicit operator Value(int? i)
235 | {
236 | return i.HasValue ? new Value {Type = Type.Int, i = i.Value} : Null;
237 | }
238 |
239 | public static implicit operator Value(double d)
240 | {
241 | return new Value {Type = Type.Double, d = d};
242 | }
243 |
244 | public static implicit operator Value(double? d)
245 | {
246 | return d.HasValue ? new Value {Type = Type.Double, d = d.Value} : Null;
247 | }
248 |
249 | public static implicit operator Value(string s)
250 | {
251 | return s != null ? new Value {Type = Type.String, s = s} : Null;
252 | }
253 |
254 | public static implicit operator Value(Object o)
255 | {
256 | return o != null ? new Value {Type = Type.Object, o = o} : Null;
257 | }
258 |
259 | public static implicit operator Value(Array a)
260 | {
261 | return a != null ? new Value {Type = Type.Array, a = a} : Null;
262 | }
263 |
264 | public static explicit operator bool(Value v)
265 | {
266 | bool? result = v.AsBool();
267 | if (result.HasValue)
268 | return result.Value;
269 | throw new InvalidCastException();
270 | }
271 |
272 | public static explicit operator int(Value v)
273 | {
274 | int? result = v.AsInt();
275 | if (result.HasValue)
276 | return result.Value;
277 | throw new InvalidCastException();
278 | }
279 |
280 | public static explicit operator double(Value v)
281 | {
282 | double? result = v.AsDouble();
283 | if (result.HasValue)
284 | return result.Value;
285 | throw new InvalidCastException();
286 | }
287 |
288 | public static explicit operator string(Value v)
289 | {
290 | if (v.Type == Type.Null)
291 | return null;
292 | string result = v.AsString();
293 | if (result != null)
294 | return result;
295 | throw new InvalidCastException();
296 | }
297 |
298 | public static explicit operator Object(Value v)
299 | {
300 | if (v.Type == Type.Null)
301 | return null;
302 | Object result = v.AsObject();
303 | if (result != null)
304 | return result;
305 | throw new InvalidCastException();
306 | }
307 |
308 | public static explicit operator Array(Value v)
309 | {
310 | if (v.Type == Type.Null)
311 | return null;
312 | Array result = v.AsArray();
313 | if (result != null)
314 | return result;
315 | throw new InvalidCastException();
316 | }
317 |
318 | public bool? AsBool()
319 | {
320 | if (Type == Type.Bool)
321 | return b;
322 | return null;
323 | }
324 |
325 | public int? AsInt()
326 | {
327 | if (Type == Type.Int)
328 | return i;
329 | double r = Math.Round(d);
330 | if (Type == Type.Double && Math.Abs(d - r) < double.Epsilon && r >= int.MinValue && r <= int.MaxValue)
331 | return (int)r;
332 | return null;
333 | }
334 |
335 | public double? AsDouble()
336 | {
337 | if (Type == Type.Int)
338 | return i;
339 | if (Type == Type.Double)
340 | return d;
341 | return null;
342 | }
343 |
344 | public string AsString()
345 | {
346 | return Type == Type.String ? s : null;
347 | }
348 |
349 | public Object AsObject()
350 | {
351 | return Type == Type.Object ? o : null;
352 | }
353 |
354 | public Array AsArray()
355 | {
356 | return Type == Type.Array ? a : null;
357 | }
358 | }
359 |
360 | public enum Type
361 | {
362 | Null,
363 | Bool,
364 | Int,
365 | Double,
366 | String,
367 | Object,
368 | Array,
369 | }
370 |
371 | #region 自定义事件接口
372 | public interface Handler
373 | {
374 | bool StartArray();
375 | bool StartTable();
376 | bool EndArray();
377 | bool EndTable();
378 | bool Key(string key);
379 | bool Null();
380 | bool Bool(bool b);
381 | bool String(string s);
382 | bool Double(double d);
383 | bool Int(int i);
384 | bool Flush();
385 | }
386 |
387 | public interface Writer
388 | {
389 | bool Write(Handler handler);
390 | }
391 |
392 | public delegate void ValueAction(Value value);
393 | public delegate bool WriteAction(Handler handler);
394 | #endregion
395 |
396 | #region 选项
397 | public struct ParseOptions
398 | {
399 | public bool strict;
400 | public bool comment;
401 | public bool eof;
402 | }
403 |
404 | public struct DumpOptions
405 | {
406 | public bool pretty;
407 | public bool escape;
408 | }
409 | #endregion
410 |
411 | #region 默认接口
412 | public static Handler DefaultHandler(ValueAction action)
413 | {
414 | return new NodeHandler {result = action};
415 | }
416 |
417 | public static Writer DefaultWriter(Value value)
418 | {
419 | return new NodeWriter(value);
420 | }
421 |
422 | public static Object From(Dictionary dict)
423 | {
424 | return new NodeObject(dict);
425 | }
426 |
427 | public static Array From(List list)
428 | {
429 | return new NodeArray(list);
430 | }
431 | #endregion
432 |
433 | #region 对外解析接口
434 | public bool Parse(TextReader reader, Handler handler, ParseOptions options)
435 | {
436 | input = reader;
437 | token = input.Read();
438 | if (!Skip())
439 | return false;
440 | if (!ReadValue(handler))
441 | return false;
442 | if (!handler.Flush())
443 | return false;
444 | return !options.eof || Flush();
445 | }
446 |
447 | public bool Parse(TextReader reader, Handler handler)
448 | {
449 | return Parse(reader, handler, new ParseOptions {strict = false, comment = true, eof = false});
450 | }
451 |
452 | public bool Parse(string text, Handler handler, ParseOptions options)
453 | {
454 | return Parse(new StringReader(text), handler, options);
455 | }
456 |
457 | public bool Parse(string text, Handler handler)
458 | {
459 | return Parse(new StringReader(text), handler, new ParseOptions {strict = false, comment = true, eof = true});
460 | }
461 |
462 | public Value? Parse(TextReader reader, ParseOptions options)
463 | {
464 | NodeHandler handler = new NodeHandler();
465 | return Parse(reader, handler, options) ? handler.root : null;
466 | }
467 |
468 | public Value? Parse(TextReader reader)
469 | {
470 | NodeHandler handler = new NodeHandler();
471 | return Parse(reader, handler) ? handler.root : null;
472 | }
473 |
474 | public Value? Parse(string text, ParseOptions options)
475 | {
476 | return Parse(new StringReader(text), options);
477 | }
478 |
479 | public Value? Parse(string text)
480 | {
481 | return Parse(new StringReader(text));
482 | }
483 | #endregion
484 |
485 | #region 对外序列化接口
486 | private Buffer normalbuffer;
487 | private Buffer prettybuffer;
488 |
489 | public bool Dump(Writer writer, Handler handler)
490 | {
491 | return writer.Write(handler);
492 | }
493 |
494 | public bool Dump(TextWriter output, Writer writer, DumpOptions options)
495 | {
496 | Buffer buffer;
497 | if (options.pretty)
498 | {
499 | if (prettybuffer == null)
500 | prettybuffer = new PrettyBuffer();
501 | buffer = prettybuffer;
502 | }
503 | else
504 | {
505 | if (normalbuffer == null)
506 | normalbuffer = new Buffer();
507 | buffer = normalbuffer;
508 | }
509 | buffer.escape = options.escape;
510 | buffer.writer = output;
511 | buffer.Reset();
512 | bool result = Dump(writer, buffer);
513 | buffer.writer = null;
514 | return result;
515 | }
516 |
517 | public bool Dump(TextWriter output, Writer writer)
518 | {
519 | return Dump(output, writer, new DumpOptions {pretty = false, escape = false});
520 | }
521 |
522 | public string Dump(Writer writer, DumpOptions options)
523 | {
524 | StringWriter output = new StringWriter();
525 | return Dump(output, writer, options) ? output.ToString() : null;
526 | }
527 |
528 | public string Dump(Writer writer)
529 | {
530 | StringWriter output = new StringWriter();
531 | return Dump(output, writer) ? output.ToString() : null;
532 | }
533 |
534 | public bool Dump(WriteAction writer, Handler handler)
535 | {
536 | return new ActionWriter(writer).Write(handler);
537 | }
538 |
539 | public bool Dump(TextWriter output, WriteAction writer, DumpOptions options)
540 | {
541 | return Dump(output, new ActionWriter(writer), options);
542 | }
543 |
544 | public bool Dump(TextWriter output, WriteAction writer)
545 | {
546 | return Dump(output, new ActionWriter(writer));
547 | }
548 |
549 | public string Dump(WriteAction writer, DumpOptions options)
550 | {
551 | return Dump(new ActionWriter(writer), options);
552 | }
553 |
554 | public string Dump(WriteAction writer)
555 | {
556 | return Dump(new ActionWriter(writer));
557 | }
558 |
559 | public bool Dump(Value value, Handler handler)
560 | {
561 | return new NodeWriter(value).Write(handler);
562 | }
563 |
564 | public bool Dump(Value? value, Handler handler)
565 | {
566 | return value.HasValue && new NodeWriter(value.Value).Write(handler);
567 | }
568 |
569 | public bool Dump(TextWriter output, Value value, DumpOptions options)
570 | {
571 | return Dump(output, new NodeWriter(value), options);
572 | }
573 |
574 | public bool Dump(TextWriter output, Value? value, DumpOptions options)
575 | {
576 | return value.HasValue && Dump(output, new NodeWriter(value.Value), options);
577 | }
578 |
579 | public bool Dump(TextWriter output, Value value)
580 | {
581 | return Dump(output, new NodeWriter(value));
582 | }
583 |
584 | public bool Dump(TextWriter output, Value? value)
585 | {
586 | return value.HasValue && Dump(output, new NodeWriter(value.Value));
587 | }
588 |
589 | public string Dump(Value value, DumpOptions options)
590 | {
591 | return Dump(new NodeWriter(value), options);
592 | }
593 |
594 | public string Dump(Value? value, DumpOptions options)
595 | {
596 | return value.HasValue ? Dump(new NodeWriter(value.Value), options) : null;
597 | }
598 |
599 | public string Dump(Value value)
600 | {
601 | return Dump(new NodeWriter(value));
602 | }
603 |
604 | public string Dump(Value? value)
605 | {
606 | return value.HasValue ? Dump(new NodeWriter(value.Value)) : null;
607 | }
608 | #endregion
609 |
610 | #region 解析实现
611 | private int token;
612 | private TextReader input;
613 | private StringBuilder builder;
614 |
615 | private bool ReadValue(Handler handler)
616 | {
617 | switch (token)
618 | {
619 | case '{':
620 | return ReadTable(handler);
621 | case '[':
622 | return ReadArray(handler);
623 | case 't':
624 | case 'f':
625 | return ReadBool(handler);
626 | case 'n':
627 | return ReadNull(handler);
628 | case '"':
629 | case '\'':
630 | return ReadString(handler);
631 | case '-':
632 | case '0':
633 | case '1':
634 | case '2':
635 | case '3':
636 | case '4':
637 | case '5':
638 | case '6':
639 | case '7':
640 | case '8':
641 | case '9':
642 | return ReadNumber(handler);
643 | case '/':
644 | Next();
645 | switch (token)
646 | {
647 | case '/':
648 | return ReadCommentLine();
649 | case '*':
650 | return ReadComments();
651 | }
652 | return false;
653 | }
654 | return false;
655 | }
656 |
657 | private bool ReadTable(Handler handler)
658 | {
659 | if (!handler.StartTable())
660 | return false;
661 | while (true)
662 | {
663 | Next();
664 | if (!Skip())
665 | return false;
666 | if (token == '}')
667 | {
668 | Next();
669 | if (!handler.EndTable())
670 | return false;
671 | break;
672 | }
673 | if (!ReadKey(handler))
674 | return false;
675 | if (!Skip())
676 | return false;
677 | if (token != ':')
678 | return false;
679 | Next();
680 | if (!Skip())
681 | return false;
682 | if (!ReadValue(handler))
683 | return false;
684 | if (!Skip())
685 | return false;
686 | if (token == '}')
687 | {
688 | Next();
689 | if (!handler.EndTable())
690 | return false;
691 | break;
692 | }
693 | if (token != ',')
694 | return false;
695 | }
696 | return true;
697 | }
698 |
699 | private bool ReadArray(Handler handler)
700 | {
701 | if (!handler.StartArray())
702 | return false;
703 | while (true)
704 | {
705 | Next();
706 | if (!Skip())
707 | return false;
708 | if (token == ']')
709 | {
710 | Next();
711 | if (!handler.EndArray())
712 | return false;
713 | break;
714 | }
715 | if (!ReadValue(handler))
716 | return false;
717 | if (!Skip())
718 | return false;
719 | if (token == ']')
720 | {
721 | Next();
722 | if (!handler.EndArray())
723 | return false;
724 | break;
725 | }
726 | if (token != ',')
727 | return false;
728 | }
729 | return true;
730 | }
731 |
732 | private bool ReadBool(Handler handler)
733 | {
734 | if (token == 't')
735 | {
736 | if (Next() == 'r' && Next() == 'u' && Next() == 'e')
737 | {
738 | Next();
739 | return handler.Bool(true);
740 | }
741 | }
742 | else
743 | {
744 | if (Next() == 'a' && Next() == 'l' && Next() == 's' && Next() == 'e')
745 | {
746 | Next();
747 | return handler.Bool(false);
748 | }
749 | }
750 | return false;
751 | }
752 |
753 | private bool ReadNull(Handler handler)
754 | {
755 | if (Next() == 'u' && Next() == 'l' && Next() == 'l')
756 | {
757 | Next();
758 | return handler.Null();
759 | }
760 | return false;
761 | }
762 |
763 | private bool ReadNumber(Handler handler)
764 | {
765 | bool minus = false;
766 | if (token == '-')
767 | {
768 | minus = true;
769 | Next();
770 | }
771 | if (token < '0' || token > '9')
772 | return false;
773 | uint u = 0;
774 | double d = 0;
775 | bool isfloat = false;
776 | while (token >= '0' && token <= '9')
777 | {
778 | if (isfloat)
779 | {
780 | d = d * 10 + (token - '0');
781 | }
782 | else
783 | {
784 | uint uu = (uint)(token - '0');
785 | if (u > int.MaxValue / 10 || (u == int.MaxValue / 10 && uu > int.MaxValue % 10))
786 | {
787 | isfloat = true;
788 | d = u;
789 | continue;
790 | }
791 | u = u * 10 + uu;
792 | }
793 | Next();
794 | }
795 | int dot = 0;
796 | if (token == '.')
797 | {
798 | if (!isfloat)
799 | {
800 | isfloat = true;
801 | d = u;
802 | }
803 | Next();
804 | while (token >= '0' && token <= '9')
805 | {
806 | d = d * 10 + (token - '0');
807 | --dot;
808 | Next();
809 | }
810 | if (dot == 0)
811 | return false;
812 | }
813 | int exp = 0;
814 | if (token == 'E' || token == 'e')
815 | {
816 | if (!isfloat)
817 | {
818 | isfloat = true;
819 | d = u;
820 | }
821 | bool expMinus = false;
822 | Next();
823 | if (token == '+')
824 | {
825 | Next();
826 | }
827 | else if (token == '-')
828 | {
829 | expMinus = true;
830 | Next();
831 | }
832 | if (token < '0' || token > '9')
833 | return false;
834 | while (token >= '0' && token <= '9')
835 | {
836 | exp = exp * 10 + (token - '0');
837 | Next();
838 | }
839 | if (expMinus)
840 | exp = -exp;
841 | }
842 | return isfloat ? handler.Double((minus ? -d : d) * Pow10(dot + exp)) : handler.Int(minus ? (int)-u : (int)u);
843 | }
844 |
845 | private string ReadString()
846 | {
847 | char symbol = (char)token;
848 | if (builder == null)
849 | builder = new StringBuilder();
850 | else
851 | builder.Length = 0;
852 | while (true)
853 | {
854 | Next();
855 | if (token == symbol)
856 | break;
857 | if (token == -1)
858 | return null;
859 | if (token == '\\')
860 | {
861 | Next();
862 | switch (token)
863 | {
864 | case 'b':
865 | builder.Append('\b');
866 | break;
867 | case 'f':
868 | builder.Append('\f');
869 | break;
870 | case 'n':
871 | builder.Append('\n');
872 | break;
873 | case 'r':
874 | builder.Append('\r');
875 | break;
876 | case 't':
877 | builder.Append('\t');
878 | break;
879 | case '"':
880 | builder.Append('"');
881 | break;
882 | case '\'':
883 | builder.Append('\'');
884 | break;
885 | case '\\':
886 | builder.Append('\\');
887 | break;
888 | case '/':
889 | builder.Append('/');
890 | break;
891 | case 'u':
892 | {
893 | int unicode = 0;
894 | for (int i = 0; i < 4; ++i)
895 | {
896 | int c = Next();
897 | if (c >= 'a')
898 | c -= 'a' - 10;
899 | else if (c >= 'A')
900 | c -= 'A' - 10;
901 | else if (c >= '0' && c <= '9')
902 | c -= '0';
903 | else
904 | return null;
905 | unicode <<= 4;
906 | unicode |= c;
907 | }
908 | builder.Append((char)unicode);
909 | }
910 | break;
911 | default:
912 | return null;
913 | }
914 | }
915 | else
916 | {
917 | builder.Append((char)token);
918 | }
919 | }
920 | Next();
921 | return builder.ToString();
922 | }
923 |
924 | private bool ReadString(Handler handler)
925 | {
926 | string str = ReadString();
927 | return str != null && handler.String(str);
928 | }
929 |
930 | private bool ReadKey(Handler handler)
931 | {
932 | if (token == '"' || token == '\'')
933 | {
934 | string str = ReadString();
935 | return str != null && handler.Key(str);
936 | }
937 | if (token == '_' || (token >= 'a' && token <= 'z') || (token >= 'A' && token <= 'Z'))
938 | {
939 | if (builder == null)
940 | builder = new StringBuilder();
941 | else
942 | builder.Length = 0;
943 | while (true)
944 | {
945 | builder.Append((char)token);
946 | Next();
947 | if (token == '_' || (token >= 'a' && token <= 'z') || (token >= 'A' && token <= 'Z') || (token >= '0' && token <= '9'))
948 | continue;
949 | break;
950 | }
951 | return handler.Key(builder.ToString());
952 | }
953 | return false;
954 | }
955 |
956 | private bool ReadCommentLine()
957 | {
958 | while (true)
959 | {
960 | Next();
961 | if (token == '\n')
962 | {
963 | Next();
964 | return true;
965 | }
966 | if (token == -1)
967 | return true;
968 | }
969 | }
970 |
971 | private bool ReadComments()
972 | {
973 | while (true)
974 | {
975 | Next();
976 | if (token == '*')
977 | {
978 | Next();
979 | if (token == '/')
980 | {
981 | Next();
982 | return true;
983 | }
984 | }
985 | if (token == -1)
986 | return false;
987 | }
988 | }
989 |
990 | private bool Flush()
991 | {
992 | if (!Skip())
993 | return false;
994 | input = null;
995 | return token == -1 || token == '\0';
996 | }
997 |
998 | private bool Skip()
999 | {
1000 | while (token == ' ' || token == '\n' || token == '\r' || token == '\t')
1001 | {
1002 | token = input.Read();
1003 | }
1004 | if (token == '/')
1005 | {
1006 | switch (input.Peek())
1007 | {
1008 | case '*':
1009 | input.Read();
1010 | while (true)
1011 | {
1012 | token = input.Read();
1013 | if (token == -1)
1014 | return false;
1015 | if (token == '*')
1016 | {
1017 | if (input.Peek() == '/')
1018 | {
1019 | input.Read();
1020 | token = input.Read();
1021 | break;
1022 | }
1023 | }
1024 | }
1025 | return Skip();
1026 | case '/':
1027 | input.Read();
1028 | while (true)
1029 | {
1030 | token = input.Read();
1031 | if (token == '\r' || token == '\n' || token == -1)
1032 | break;
1033 | }
1034 | return Skip();
1035 | }
1036 | }
1037 | return true;
1038 | }
1039 |
1040 | private int Next()
1041 | {
1042 | token = input.Read();
1043 | return token;
1044 | }
1045 | #endregion
1046 |
1047 | #region 加速Pow运算
1048 | private static readonly double[] e =
1049 | {
1050 | // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
1051 | 1e+0,
1052 | 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28,
1053 | 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56,
1054 | 1e+57, 1e+58, 1e+59, 1e+60, 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 1e+81, 1e+82, 1e+83, 1e+84,
1055 | 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,
1056 | 1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
1057 | 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,
1058 | 1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,
1059 | 1e+197,1e+198,1e+199,1e+200,1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,1e+221,1e+222,1e+223,1e+224,
1060 | 1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,
1061 | 1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
1062 | 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308,
1063 | };
1064 |
1065 | private static double Pow10(int x)
1066 | {
1067 | if (x < -308)
1068 | return 0;
1069 | if (x > 308)
1070 | return double.PositiveInfinity;
1071 | return x >= 0 ? e[x] : 1.0 / e[-x];
1072 | }
1073 | #endregion
1074 |
1075 | #region 默认解析生成Node
1076 | private class NodeObject : Object
1077 | {
1078 | public readonly Dictionary dict;
1079 |
1080 | public NodeObject()
1081 | {
1082 | dict = new Dictionary();
1083 | }
1084 |
1085 | public NodeObject(Dictionary dict)
1086 | {
1087 | this.dict = dict;
1088 | }
1089 |
1090 | protected override IEnumerator Keys()
1091 | {
1092 | return new Enumerator(dict);
1093 | }
1094 |
1095 | public override Type Type(string key)
1096 | {
1097 | Value value;
1098 | return dict.TryGetValue(key, out value) ? value.Type : JSON.Type.Null;
1099 | }
1100 |
1101 | public override bool Get(string key, ref bool b)
1102 | {
1103 | Value value;
1104 | if (dict.TryGetValue(key, out value))
1105 | {
1106 | bool? result = value.AsBool();
1107 | if (result.HasValue)
1108 | {
1109 | b = result.Value;
1110 | return true;
1111 | }
1112 | }
1113 | return false;
1114 | }
1115 |
1116 | public override bool Get(string key, ref int i)
1117 | {
1118 | Value value;
1119 | if (dict.TryGetValue(key, out value))
1120 | {
1121 | int? result = value.AsInt();
1122 | if (result.HasValue)
1123 | {
1124 | i = result.Value;
1125 | return true;
1126 | }
1127 | }
1128 | return false;
1129 | }
1130 |
1131 | public override bool Get(string key, ref double d)
1132 | {
1133 | Value value;
1134 | if (dict.TryGetValue(key, out value))
1135 | {
1136 | double? result = value.AsDouble();
1137 | if (result.HasValue)
1138 | {
1139 | d = result.Value;
1140 | return true;
1141 | }
1142 | }
1143 | return false;
1144 | }
1145 |
1146 | public override bool Get(string key, ref string s)
1147 | {
1148 | Value value;
1149 | if (dict.TryGetValue(key, out value))
1150 | {
1151 | string result = value.AsString();
1152 | if (result != null)
1153 | {
1154 | s = result;
1155 | return true;
1156 | }
1157 | }
1158 | return false;
1159 | }
1160 |
1161 | public override bool Get(string key, ref Object o)
1162 | {
1163 | Value value;
1164 | if (dict.TryGetValue(key, out value))
1165 | {
1166 | Object result = value.AsObject();
1167 | if (result != null)
1168 | {
1169 | o = result;
1170 | return true;
1171 | }
1172 | }
1173 | return false;
1174 | }
1175 |
1176 | public override bool Get(string key, ref Array a)
1177 | {
1178 | Value value;
1179 | if (dict.TryGetValue(key, out value))
1180 | {
1181 | Array result = value.AsArray();
1182 | if (result != null)
1183 | {
1184 | a = result;
1185 | return true;
1186 | }
1187 | }
1188 | return false;
1189 | }
1190 |
1191 | private class Enumerator : IEnumerator
1192 | {
1193 | private readonly Dictionary dict;
1194 | private Dictionary.Enumerator enumerator;
1195 |
1196 | public Enumerator(Dictionary dict)
1197 | {
1198 | this.dict = dict;
1199 | enumerator = dict.GetEnumerator();
1200 | }
1201 |
1202 | public void Dispose()
1203 | {
1204 | enumerator.Dispose();
1205 | }
1206 |
1207 | public bool MoveNext()
1208 | {
1209 | return enumerator.MoveNext();
1210 | }
1211 |
1212 | public void Reset()
1213 | {
1214 | enumerator.Dispose();
1215 | enumerator = dict.GetEnumerator();
1216 | }
1217 |
1218 | public string Current
1219 | {
1220 | get { return enumerator.Current.Key; }
1221 | }
1222 |
1223 | object IEnumerator.Current
1224 | {
1225 | get { return Current; }
1226 | }
1227 | }
1228 | }
1229 |
1230 | private class NodeArray : Array
1231 | {
1232 | public readonly List list;
1233 |
1234 | public NodeArray()
1235 | {
1236 | list = new List();
1237 | }
1238 |
1239 | public NodeArray(List list)
1240 | {
1241 | this.list = list;
1242 | }
1243 |
1244 | public override int Count
1245 | {
1246 | get { return list.Count; }
1247 | }
1248 |
1249 | public override Type Type(int index)
1250 | {
1251 | return list[index].Type;
1252 | }
1253 |
1254 | public override bool Get(int index, ref bool b)
1255 | {
1256 | bool? result = list[index].AsBool();
1257 | if (result.HasValue)
1258 | {
1259 | b = result.Value;
1260 | return true;
1261 | }
1262 | return false;
1263 | }
1264 |
1265 | public override bool Get(int index, ref int i)
1266 | {
1267 | int? result = list[index].AsInt();
1268 | if (result.HasValue)
1269 | {
1270 | i = result.Value;
1271 | return true;
1272 | }
1273 | return false;
1274 | }
1275 |
1276 | public override bool Get(int index, ref double d)
1277 | {
1278 | double? result = list[index].AsDouble();
1279 | if (result.HasValue)
1280 | {
1281 | d = result.Value;
1282 | return true;
1283 | }
1284 | return false;
1285 | }
1286 |
1287 | public override bool Get(int index, ref string s)
1288 | {
1289 | string result = list[index].AsString();
1290 | if (result != null)
1291 | {
1292 | s = result;
1293 | return true;
1294 | }
1295 | return false;
1296 | }
1297 |
1298 | public override bool Get(int index, ref Object o)
1299 | {
1300 | Object result = list[index].AsObject();
1301 | if (result != null)
1302 | {
1303 | o = result;
1304 | return true;
1305 | }
1306 | return false;
1307 | }
1308 |
1309 | public override bool Get(int index, ref Array a)
1310 | {
1311 | Array result = list[index].AsArray();
1312 | if (result != null)
1313 | {
1314 | a = result;
1315 | return true;
1316 | }
1317 | return false;
1318 | }
1319 | }
1320 |
1321 | private class NodeHandler : Stack, Handler
1322 | {
1323 | private string key;
1324 | public Value? root;
1325 | public ValueAction result;
1326 |
1327 | private bool Value(Value value)
1328 | {
1329 | if (root == null)
1330 | {
1331 | root = value;
1332 | }
1333 | else if (Count > 0)
1334 | {
1335 | Value last = Peek();
1336 | switch (last.Type)
1337 | {
1338 | case Type.Object:
1339 | {
1340 | NodeObject node = last.AsObject() as NodeObject;
1341 | if (node != null)
1342 | node.dict[key] = value;
1343 | }
1344 | break;
1345 | case Type.Array:
1346 | {
1347 | NodeArray node = last.AsArray() as NodeArray;
1348 | if (node != null)
1349 | node.list.Add(value);
1350 | }
1351 | break;
1352 | default:
1353 | return false;
1354 | }
1355 | }
1356 | return true;
1357 | }
1358 |
1359 | public bool StartArray()
1360 | {
1361 | NodeArray node = new NodeArray();
1362 | if (!Value(node))
1363 | return false;
1364 | Push(node);
1365 | return true;
1366 | }
1367 |
1368 | public bool StartTable()
1369 | {
1370 | NodeObject node = new NodeObject();
1371 | if (!Value(node))
1372 | return false;
1373 | Push(node);
1374 | return true;
1375 | }
1376 |
1377 | public bool EndArray()
1378 | {
1379 | try
1380 | {
1381 | Pop();
1382 | return true;
1383 | }
1384 | catch (Exception)
1385 | {
1386 | return false;
1387 | }
1388 | }
1389 |
1390 | public bool EndTable()
1391 | {
1392 | try
1393 | {
1394 | Pop();
1395 | return true;
1396 | }
1397 | catch (Exception)
1398 | {
1399 | return false;
1400 | }
1401 | }
1402 |
1403 | public bool Null()
1404 | {
1405 | return Value(JSON.Value.Null);
1406 | }
1407 |
1408 | public bool Key(string key)
1409 | {
1410 | this.key = key;
1411 | return true;
1412 | }
1413 |
1414 | public bool Bool(bool b)
1415 | {
1416 | return Value(b);
1417 | }
1418 |
1419 | public bool String(string s)
1420 | {
1421 | return Value(s);
1422 | }
1423 |
1424 | public bool Double(double d)
1425 | {
1426 | return Value(d);
1427 | }
1428 |
1429 | public bool Int(int i)
1430 | {
1431 | return Value(i);
1432 | }
1433 |
1434 | public bool Flush()
1435 | {
1436 | if (Count != 0)
1437 | return false;
1438 | if (result != null && root.HasValue)
1439 | result(root.Value);
1440 | return true;
1441 | }
1442 | }
1443 | #endregion
1444 |
1445 | #region 序列化实现
1446 | private class Buffer : Handler
1447 | {
1448 | public bool escape;
1449 | public TextWriter writer;
1450 | protected bool empty;
1451 | protected int depth;
1452 | protected bool table;
1453 |
1454 | public Buffer()
1455 | {
1456 | escape = false;
1457 | empty = true;
1458 | depth = 0;
1459 | }
1460 |
1461 | private void WriteString(string s)
1462 | {
1463 | writer.Write('"');
1464 | for (int i = 0, j = s.Length; i < j; ++i)
1465 | {
1466 | char c = s[i];
1467 | if (c < 128)
1468 | {
1469 | char esc = escapes[c];
1470 | if (esc == '#')
1471 | {
1472 | writer.Write(c);
1473 | }
1474 | else if (esc == 'u')
1475 | {
1476 | writer.Write("\\u00");
1477 | writer.Write(((uint)c).ToString("X2", CultureInfo.InvariantCulture));
1478 | }
1479 | else
1480 | {
1481 | writer.Write('\\');
1482 | writer.Write(esc);
1483 | }
1484 | }
1485 | else if (escape)
1486 | {
1487 | writer.Write("\\u");
1488 | writer.Write(((uint)c).ToString("X4", CultureInfo.InvariantCulture));
1489 | }
1490 | else
1491 | {
1492 | writer.Write(c);
1493 | }
1494 | }
1495 | writer.Write('"');
1496 | }
1497 |
1498 | protected virtual void Prefix()
1499 | {
1500 | if (depth > 0)
1501 | {
1502 | if (!table)
1503 | {
1504 | if (!empty)
1505 | WriteComma();
1506 | WriteIndent();
1507 | }
1508 | }
1509 | }
1510 |
1511 | public override string ToString()
1512 | {
1513 | return writer.ToString();
1514 | }
1515 |
1516 | public virtual void Reset()
1517 | {
1518 | empty = true;
1519 | depth = 0;
1520 | }
1521 |
1522 | public virtual bool StartArray()
1523 | {
1524 | Prefix();
1525 | ++depth;
1526 | empty = true;
1527 | table = false;
1528 | writer.Write('[');
1529 | return true;
1530 | }
1531 |
1532 | public virtual bool EndArray()
1533 | {
1534 | --depth;
1535 | if (!empty)
1536 | WriteIndent();
1537 | empty = false;
1538 | writer.Write(']');
1539 | return true;
1540 | }
1541 |
1542 | public virtual bool StartTable()
1543 | {
1544 | Prefix();
1545 | ++depth;
1546 | empty = true;
1547 | table = false;
1548 | writer.Write('{');
1549 | return true;
1550 | }
1551 |
1552 | public virtual bool EndTable()
1553 | {
1554 | --depth;
1555 | if (!empty)
1556 | WriteIndent();
1557 | empty = false;
1558 | writer.Write('}');
1559 | return true;
1560 | }
1561 |
1562 | public virtual bool Key(string s)
1563 | {
1564 | table = true;
1565 | if (!empty)
1566 | WriteComma();
1567 | WriteIndent();
1568 | WriteString(s);
1569 | WriteColon();
1570 | return true;
1571 | }
1572 |
1573 | public bool Null()
1574 | {
1575 | Prefix();
1576 | empty = false;
1577 | table = false;
1578 | writer.Write("null");
1579 | return true;
1580 | }
1581 |
1582 | public bool Bool(bool b)
1583 | {
1584 | Prefix();
1585 | empty = false;
1586 | table = false;
1587 | writer.Write(b ? "true" : "false");
1588 | return true;
1589 | }
1590 |
1591 | public bool String(string s)
1592 | {
1593 | Prefix();
1594 | empty = false;
1595 | table = false;
1596 | WriteString(s);
1597 | return true;
1598 | }
1599 |
1600 | public bool Double(double d)
1601 | {
1602 | Prefix();
1603 | empty = false;
1604 | table = false;
1605 | writer.Write(d.ToString(CultureInfo.InvariantCulture));
1606 | return true;
1607 | }
1608 |
1609 | public bool Int(int i)
1610 | {
1611 | Prefix();
1612 | empty = false;
1613 | table = false;
1614 | writer.Write(i.ToString(CultureInfo.InvariantCulture));
1615 | return true;
1616 | }
1617 |
1618 | public bool Flush()
1619 | {
1620 | return depth == 0;
1621 | }
1622 |
1623 | protected virtual void WriteIndent()
1624 | {
1625 | }
1626 |
1627 | protected virtual void WriteComma()
1628 | {
1629 | writer.Write(',');
1630 | }
1631 |
1632 | protected virtual void WriteColon()
1633 | {
1634 | writer.Write(':');
1635 | }
1636 | }
1637 |
1638 | private class PrettyBuffer : Buffer
1639 | {
1640 | protected override void WriteColon()
1641 | {
1642 | writer.Write(" : ");
1643 | }
1644 |
1645 | protected override void WriteIndent()
1646 | {
1647 | writer.Write('\n');
1648 | for (int i = 0, j = depth; i < j; ++i)
1649 | {
1650 | writer.Write('\t');
1651 | }
1652 | }
1653 | }
1654 | #endregion
1655 |
1656 | #region 转义字符表
1657 | private static readonly char[] escapes =
1658 | {
1659 | /*
1660 | This array maps the 128 ASCII characters into character escape.
1661 | 'u' indicate must transform to \u00xx.
1662 | */
1663 | 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u',
1664 | 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
1665 | '#', '#', '"', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
1666 | '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
1667 | '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
1668 | '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '\\', '#', '#', '#',
1669 | '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
1670 | '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
1671 | };
1672 |
1673 | #endregion
1674 |
1675 | #region 默认序列化行为
1676 | private class NodeWriter : Writer
1677 | {
1678 | private readonly Value root;
1679 | private readonly Dictionary