Statistics
| Branch: | Tag: | Revision:

root / Assets / Plugins / SimpleJson.cs @ 2:ae2e128a3d94

History | View | Annotate | Download (83.2 kB)

1
//-----------------------------------------------------------------------
2
// <copyright file="SimpleJson.cs" company="The Outercurve Foundation">
3
//    Copyright (c) 2011, The Outercurve Foundation.
4
//
5
//    Licensed under the MIT License (the "License");
6
//    you may not use this file except in compliance with the License.
7
//    You may obtain a copy of the License at
8
//      http://www.opensource.org/licenses/mit-license.php
9
//
10
//    Unless required by applicable law or agreed to in writing, software
11
//    distributed under the License is distributed on an "AS IS" BASIS,
12
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
//    See the License for the specific language governing permissions and
14
//    limitations under the License.
15
// </copyright>
16
// <author>Nathan Totten (ntotten.com), Jim Zimmerman (jimzimmerman.com) and Prabir Shrestha (prabir.me)</author>
17
// <website>https://github.com/facebook-csharp-sdk/simple-json</website>
18
//-----------------------------------------------------------------------
19
20
// VERSION:
21
22
// NOTE: uncomment the following line to make SimpleJson class internal.
23
//#define SIMPLE_JSON_INTERNAL
24
25
// NOTE: uncomment the following line to make JsonArray and JsonObject class internal.
26
//#define SIMPLE_JSON_OBJARRAYINTERNAL
27
28
// NOTE: uncomment the following line to enable dynamic support.
29
//#define SIMPLE_JSON_DYNAMIC
30
31
// NOTE: uncomment the following line to enable DataContract support.
32
//#define SIMPLE_JSON_DATACONTRACT
33
34
// NOTE: uncomment the following line to disable linq expressions/compiled lambda (better performance) instead of method.invoke().
35
// define if you are using .net framework <= 3.0 or < WP7.5
36
#define SIMPLE_JSON_NO_LINQ_EXPRESSION
37
38
// NOTE: uncomment the following line if you are compiling under Window Metro style application/library.
39
// usually already defined in properties
40
//#define NETFX_CORE;
41
42
// If you are targetting WinStore, WP8 and NET4.5+ PCL make sure to #define SIMPLE_JSON_TYPEINFO;
43
44
// original json parsing code from http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
45
46
#if NETFX_CORE
47
#define SIMPLE_JSON_TYPEINFO
48
#endif
49
50
using System;
51
using System.CodeDom.Compiler;
52
using System.Collections;
53
using System.Collections.Generic;
54
#if !SIMPLE_JSON_NO_LINQ_EXPRESSION
55
using System.Linq.Expressions;
56
#endif
57
using System.ComponentModel;
58
using System.Diagnostics.CodeAnalysis;
59
#if SIMPLE_JSON_DYNAMIC
60
using System.Dynamic;
61
#endif
62
using System.Globalization;
63
using System.Reflection;
64
using System.Runtime.Serialization;
65
using System.Text;
66
using SimpleJson.Reflection;
67
68
// ReSharper disable LoopCanBeConvertedToQuery
69
// ReSharper disable RedundantExplicitArrayCreation
70
// ReSharper disable SuggestUseVarKeywordEvident
71
namespace SimpleJson
72
{
73
    /// <summary>
74
    /// Represents the json array.
75
    /// </summary>
76
    [GeneratedCode("simple-json", "1.0.0")]
77
    [EditorBrowsable(EditorBrowsableState.Never)]
78
    [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
79
#if SIMPLE_JSON_OBJARRAYINTERNAL
80
    internal
81
#else
82
    public
83
#endif
84
 class JsonArray : List<object>
85
    {
86
        /// <summary>
87
        /// Initializes a new instance of the <see cref="JsonArray"/> class. 
88
        /// </summary>
89
        public JsonArray() { }
90
91
        /// <summary>
92
        /// Initializes a new instance of the <see cref="JsonArray"/> class. 
93
        /// </summary>
94
        /// <param name="capacity">The capacity of the json array.</param>
95
        public JsonArray(int capacity) : base(capacity) { }
96
97
        /// <summary>
98
        /// The json representation of the array.
99
        /// </summary>
100
        /// <returns>The json representation of the array.</returns>
101
        public override string ToString()
102
        {
103
            return SimpleJson.SerializeObject(this) ?? string.Empty;
104
        }
105
    }
106
107
    /// <summary>
108
    /// Represents the json object.
109
    /// </summary>
110
    [GeneratedCode("simple-json", "1.0.0")]
111
    [EditorBrowsable(EditorBrowsableState.Never)]
112
    [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
113
#if SIMPLE_JSON_OBJARRAYINTERNAL
114
    internal
115
#else
116
    public
117
#endif
118
 class JsonObject :
119
#if SIMPLE_JSON_DYNAMIC
120
 DynamicObject,
121
#endif
122
 IDictionary<string, object>
123
    {
124
        /// <summary>
125
        /// The internal member dictionary.
126
        /// </summary>
127
        private readonly Dictionary<string, object> _members;
128
129
        /// <summary>
130
        /// Initializes a new instance of <see cref="JsonObject"/>.
131
        /// </summary>
132
        public JsonObject()
133
        {
134
            _members = new Dictionary<string, object>();
135
        }
136
137
        /// <summary>
138
        /// Initializes a new instance of <see cref="JsonObject"/>.
139
        /// </summary>
140
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> implementation to use when comparing keys, or null to use the default <see cref="T:System.Collections.Generic.EqualityComparer`1"/> for the type of the key.</param>
141
        public JsonObject(IEqualityComparer<string> comparer)
142
        {
143
            _members = new Dictionary<string, object>(comparer);
144
        }
145
146
        /// <summary>
147
        /// Gets the <see cref="System.Object"/> at the specified index.
148
        /// </summary>
149
        /// <value></value>
150
        public object this[int index]
151
        {
152
            get { return GetAtIndex(_members, index); }
153
        }
154
155
        internal static object GetAtIndex(IDictionary<string, object> obj, int index)
156
        {
157
            if (obj == null)
158
                throw new ArgumentNullException("obj");
159
            if (index >= obj.Count)
160
                throw new ArgumentOutOfRangeException("index");
161
            int i = 0;
162
            foreach (KeyValuePair<string, object> o in obj)
163
                if (i++ == index) return o.Value;
164
            return null;
165
        }
166
167
        /// <summary>
168
        /// Adds the specified key.
169
        /// </summary>
170
        /// <param name="key">The key.</param>
171
        /// <param name="value">The value.</param>
172
        public void Add(string key, object value)
173
        {
174
            _members.Add(key, value);
175
        }
176
177
        /// <summary>
178
        /// Determines whether the specified key contains key.
179
        /// </summary>
180
        /// <param name="key">The key.</param>
181
        /// <returns>
182
        ///     <c>true</c> if the specified key contains key; otherwise, <c>false</c>.
183
        /// </returns>
184
        public bool ContainsKey(string key)
185
        {
186
            return _members.ContainsKey(key);
187
        }
188
189
        /// <summary>
190
        /// Gets the keys.
191
        /// </summary>
192
        /// <value>The keys.</value>
193
        public ICollection<string> Keys
194
        {
195
            get { return _members.Keys; }
196
        }
197
198
        /// <summary>
199
        /// Removes the specified key.
200
        /// </summary>
201
        /// <param name="key">The key.</param>
202
        /// <returns></returns>
203
        public bool Remove(string key)
204
        {
205
            return _members.Remove(key);
206
        }
207
208
        /// <summary>
209
        /// Tries the get value.
210
        /// </summary>
211
        /// <param name="key">The key.</param>
212
        /// <param name="value">The value.</param>
213
        /// <returns></returns>
214
        public bool TryGetValue(string key, out object value)
215
        {
216
            return _members.TryGetValue(key, out value);
217
        }
218
219
        /// <summary>
220
        /// Gets the values.
221
        /// </summary>
222
        /// <value>The values.</value>
223
        public ICollection<object> Values
224
        {
225
            get { return _members.Values; }
226
        }
227
228
        /// <summary>
229
        /// Gets or sets the <see cref="System.Object"/> with the specified key.
230
        /// </summary>
231
        /// <value></value>
232
        public object this[string key]
233
        {
234
            get { return _members[key]; }
235
            set { _members[key] = value; }
236
        }
237
238
        /// <summary>
239
        /// Adds the specified item.
240
        /// </summary>
241
        /// <param name="item">The item.</param>
242
        public void Add(KeyValuePair<string, object> item)
243
        {
244
            _members.Add(item.Key, item.Value);
245
        }
246
247
        /// <summary>
248
        /// Clears this instance.
249
        /// </summary>
250
        public void Clear()
251
        {
252
            _members.Clear();
253
        }
254
255
        /// <summary>
256
        /// Determines whether [contains] [the specified item].
257
        /// </summary>
258
        /// <param name="item">The item.</param>
259
        /// <returns>
260
        /// 	<c>true</c> if [contains] [the specified item]; otherwise, <c>false</c>.
261
        /// </returns>
262
        public bool Contains(KeyValuePair<string, object> item)
263
        {
264
            return _members.ContainsKey(item.Key) && _members[item.Key] == item.Value;
265
        }
266
267
        /// <summary>
268
        /// Copies to.
269
        /// </summary>
270
        /// <param name="array">The array.</param>
271
        /// <param name="arrayIndex">Index of the array.</param>
272
        public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
273
        {
274
            if (array == null) throw new ArgumentNullException("array");
275
            int num = Count;
276
            foreach (KeyValuePair<string, object> kvp in this)
277
            {
278
                array[arrayIndex++] = kvp;
279
                if (--num <= 0)
280
                    return;
281
            }
282
        }
283
284
        /// <summary>
285
        /// Gets the count.
286
        /// </summary>
287
        /// <value>The count.</value>
288
        public int Count
289
        {
290
            get { return _members.Count; }
291
        }
292
293
        /// <summary>
294
        /// Gets a value indicating whether this instance is read only.
295
        /// </summary>
296
        /// <value>
297
        /// 	<c>true</c> if this instance is read only; otherwise, <c>false</c>.
298
        /// </value>
299
        public bool IsReadOnly
300
        {
301
            get { return false; }
302
        }
303
304
        /// <summary>
305
        /// Removes the specified item.
306
        /// </summary>
307
        /// <param name="item">The item.</param>
308
        /// <returns></returns>
309
        public bool Remove(KeyValuePair<string, object> item)
310
        {
311
            return _members.Remove(item.Key);
312
        }
313
314
        /// <summary>
315
        /// Gets the enumerator.
316
        /// </summary>
317
        /// <returns></returns>
318
        public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
319
        {
320
            return _members.GetEnumerator();
321
        }
322
323
        /// <summary>
324
        /// Returns an enumerator that iterates through a collection.
325
        /// </summary>
326
        /// <returns>
327
        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
328
        /// </returns>
329
        IEnumerator IEnumerable.GetEnumerator()
330
        {
331
            return _members.GetEnumerator();
332
        }
333
334
        /// <summary>
335
        /// Returns a json <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
336
        /// </summary>
337
        /// <returns>
338
        /// A json <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
339
        /// </returns>
340
        public override string ToString()
341
        {
342
            return SimpleJson.SerializeObject(this);
343
        }
344
345
#if SIMPLE_JSON_DYNAMIC
346
        /// <summary>
347
        /// Provides implementation for type conversion operations. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for operations that convert an object from one type to another.
348
        /// </summary>
349
        /// <param name="binder">Provides information about the conversion operation. The binder.Type property provides the type to which the object must be converted. For example, for the statement (String)sampleObject in C# (CType(sampleObject, Type) in Visual Basic), where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, binder.Type returns the <see cref="T:System.String"/> type. The binder.Explicit property provides information about the kind of conversion that occurs. It returns true for explicit conversion and false for implicit conversion.</param>
350
        /// <param name="result">The result of the type conversion operation.</param>
351
        /// <returns>
352
        /// Alwasy returns true.
353
        /// </returns>
354
        public override bool TryConvert(ConvertBinder binder, out object result)
355
        {
356
            // <pex>
357
            if (binder == null)
358
                throw new ArgumentNullException("binder");
359
            // </pex>
360
            Type targetType = binder.Type;
361
362
            if ((targetType == typeof(IEnumerable)) ||
363
                (targetType == typeof(IEnumerable<KeyValuePair<string, object>>)) ||
364
                (targetType == typeof(IDictionary<string, object>)) ||
365
                (targetType == typeof(IDictionary)))
366
            {
367
                result = this;
368
                return true;
369
            }
370
371
            return base.TryConvert(binder, out result);
372
        }
373
374
        /// <summary>
375
        /// Provides the implementation for operations that delete an object member. This method is not intended for use in C# or Visual Basic.
376
        /// </summary>
377
        /// <param name="binder">Provides information about the deletion.</param>
378
        /// <returns>
379
        /// Alwasy returns true.
380
        /// </returns>
381
        public override bool TryDeleteMember(DeleteMemberBinder binder)
382
        {
383
            // <pex>
384
            if (binder == null)
385
                throw new ArgumentNullException("binder");
386
            // </pex>
387
            return _members.Remove(binder.Name);
388
        }
389
390
        /// <summary>
391
        /// Provides the implementation for operations that get a value by index. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for indexing operations.
392
        /// </summary>
393
        /// <param name="binder">Provides information about the operation.</param>
394
        /// <param name="indexes">The indexes that are used in the operation. For example, for the sampleObject[3] operation in C# (sampleObject(3) in Visual Basic), where sampleObject is derived from the DynamicObject class, <paramref name="indexes"/> is equal to 3.</param>
395
        /// <param name="result">The result of the index operation.</param>
396
        /// <returns>
397
        /// Alwasy returns true.
398
        /// </returns>
399
        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
400
        {
401
            if (indexes == null) throw new ArgumentNullException("indexes");
402
            if (indexes.Length == 1)
403
            {
404
                result = ((IDictionary<string, object>)this)[(string)indexes[0]];
405
                return true;
406
            }
407
            result = null;
408
            return true;
409
        }
410
411
        /// <summary>
412
        /// Provides the implementation for operations that get member values. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for operations such as getting a value for a property.
413
        /// </summary>
414
        /// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Name property provides the name of the member on which the dynamic operation is performed. For example, for the Console.WriteLine(sampleObject.SampleProperty) statement, where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, binder.Name returns "SampleProperty". The binder.IgnoreCase property specifies whether the member name is case-sensitive.</param>
415
        /// <param name="result">The result of the get operation. For example, if the method is called for a property, you can assign the property value to <paramref name="result"/>.</param>
416
        /// <returns>
417
        /// Alwasy returns true.
418
        /// </returns>
419
        public override bool TryGetMember(GetMemberBinder binder, out object result)
420
        {
421
            object value;
422
            if (_members.TryGetValue(binder.Name, out value))
423
            {
424
                result = value;
425
                return true;
426
            }
427
            result = null;
428
            return true;
429
        }
430
431
        /// <summary>
432
        /// Provides the implementation for operations that set a value by index. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for operations that access objects by a specified index.
433
        /// </summary>
434
        /// <param name="binder">Provides information about the operation.</param>
435
        /// <param name="indexes">The indexes that are used in the operation. For example, for the sampleObject[3] = 10 operation in C# (sampleObject(3) = 10 in Visual Basic), where sampleObject is derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, <paramref name="indexes"/> is equal to 3.</param>
436
        /// <param name="value">The value to set to the object that has the specified index. For example, for the sampleObject[3] = 10 operation in C# (sampleObject(3) = 10 in Visual Basic), where sampleObject is derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, <paramref name="value"/> is equal to 10.</param>
437
        /// <returns>
438
        /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a language-specific run-time exception is thrown.
439
        /// </returns>
440
        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
441
        {
442
            if (indexes == null) throw new ArgumentNullException("indexes");
443
            if (indexes.Length == 1)
444
            {
445
                ((IDictionary<string, object>)this)[(string)indexes[0]] = value;
446
                return true;
447
            }
448
            return base.TrySetIndex(binder, indexes, value);
449
        }
450
451
        /// <summary>
452
        /// Provides the implementation for operations that set member values. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for operations such as setting a value for a property.
453
        /// </summary>
454
        /// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Name property provides the name of the member to which the value is being assigned. For example, for the statement sampleObject.SampleProperty = "Test", where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, binder.Name returns "SampleProperty". The binder.IgnoreCase property specifies whether the member name is case-sensitive.</param>
455
        /// <param name="value">The value to set to the member. For example, for sampleObject.SampleProperty = "Test", where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, the <paramref name="value"/> is "Test".</param>
456
        /// <returns>
457
        /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a language-specific run-time exception is thrown.)
458
        /// </returns>
459
        public override bool TrySetMember(SetMemberBinder binder, object value)
460
        {
461
            // <pex>
462
            if (binder == null)
463
                throw new ArgumentNullException("binder");
464
            // </pex>
465
            _members[binder.Name] = value;
466
            return true;
467
        }
468
469
        /// <summary>
470
        /// Returns the enumeration of all dynamic member names.
471
        /// </summary>
472
        /// <returns>
473
        /// A sequence that contains dynamic member names.
474
        /// </returns>
475
        public override IEnumerable<string> GetDynamicMemberNames()
476
        {
477
            foreach (var key in Keys)
478
                yield return key;
479
        }
480
#endif
481
    }
482
}
483
484
namespace SimpleJson
485
{
486
    /// <summary>
487
    /// This class encodes and decodes JSON strings.
488
    /// Spec. details, see http://www.json.org/
489
    /// 
490
    /// JSON uses Arrays and Objects. These correspond here to the datatypes JsonArray(IList&lt;object>) and JsonObject(IDictionary&lt;string,object>).
491
    /// All numbers are parsed to doubles.
492
    /// </summary>
493
    [GeneratedCode("simple-json", "1.0.0")]
494
#if SIMPLE_JSON_INTERNAL
495
    internal
496
#else
497
    public
498
#endif
499
 static class SimpleJson
500
    {
501
        private const int TOKEN_NONE = 0;
502
        private const int TOKEN_CURLY_OPEN = 1;
503
        private const int TOKEN_CURLY_CLOSE = 2;
504
        private const int TOKEN_SQUARED_OPEN = 3;
505
        private const int TOKEN_SQUARED_CLOSE = 4;
506
        private const int TOKEN_COLON = 5;
507
        private const int TOKEN_COMMA = 6;
508
        private const int TOKEN_STRING = 7;
509
        private const int TOKEN_NUMBER = 8;
510
        private const int TOKEN_TRUE = 9;
511
        private const int TOKEN_FALSE = 10;
512
        private const int TOKEN_NULL = 11;
513
        private const int BUILDER_CAPACITY = 2000;
514
515
        /// <summary>
516
        /// Parses the string json into a value
517
        /// </summary>
518
        /// <param name="json">A JSON string.</param>
519
        /// <returns>An IList&lt;object>, a IDictionary&lt;string,object>, a double, a string, null, true, or false</returns>
520
        public static object DeserializeObject(string json)
521
        {
522
            object obj;
523
            if (TryDeserializeObject(json, out obj))
524
                return obj;
525
            throw new SerializationException("Invalid JSON string");
526
        }
527
528
        /// <summary>
529
        /// Try parsing the json string into a value.
530
        /// </summary>
531
        /// <param name="json">
532
        /// A JSON string.
533
        /// </param>
534
        /// <param name="obj">
535
        /// The object.
536
        /// </param>
537
        /// <returns>
538
        /// Returns true if successfull otherwise false.
539
        /// </returns>
540
        [SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="Need to support .NET 2")]
541
        public static bool TryDeserializeObject(string json, out object obj)
542
        {
543
            bool success = true;
544
            if (json != null)
545
            {
546
                char[] charArray = json.ToCharArray();
547
                int index = 0;
548
                obj = ParseValue(charArray, ref index, ref success);
549
            }
550
            else
551
                obj = null;
552
553
            return success;
554
        }
555
556
        public static object DeserializeObject(string json, Type type, IJsonSerializerStrategy jsonSerializerStrategy)
557
        {
558
            object jsonObject = DeserializeObject(json);
559
            return type == null || jsonObject != null && ReflectionUtils.IsAssignableFrom(jsonObject.GetType(), type)
560
                       ? jsonObject
561
                       : (jsonSerializerStrategy ?? CurrentJsonSerializerStrategy).DeserializeObject(jsonObject, type);
562
        }
563
564
        public static object DeserializeObject(string json, Type type)
565
        {
566
            return DeserializeObject(json, type, null);
567
        }
568
569
        public static T DeserializeObject<T>(string json, IJsonSerializerStrategy jsonSerializerStrategy)
570
        {
571
            return (T)DeserializeObject(json, typeof(T), jsonSerializerStrategy);
572
        }
573
574
        public static T DeserializeObject<T>(string json)
575
        {
576
            return (T)DeserializeObject(json, typeof(T), null);
577
        }
578
579
        /// <summary>
580
        /// Converts a IDictionary&lt;string,object> / IList&lt;object> object into a JSON string
581
        /// </summary>
582
        /// <param name="json">A IDictionary&lt;string,object> / IList&lt;object></param>
583
        /// <param name="jsonSerializerStrategy">Serializer strategy to use</param>
584
        /// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
585
        public static string SerializeObject(object json, IJsonSerializerStrategy jsonSerializerStrategy)
586
        {
587
            StringBuilder builder = new StringBuilder(BUILDER_CAPACITY);
588
            bool success = SerializeValue(jsonSerializerStrategy, json, builder);
589
            return (success ? builder.ToString() : null);
590
        }
591
592
        public static string SerializeObject(object json)
593
        {
594
            return SerializeObject(json, CurrentJsonSerializerStrategy);
595
        }
596
597
        public static string EscapeToJavascriptString(string jsonString)
598
        {
599
            if (string.IsNullOrEmpty(jsonString))
600
                return jsonString;
601
602
            StringBuilder sb = new StringBuilder();
603
            char c;
604
605
            for (int i = 0; i < jsonString.Length; )
606
            {
607
                c = jsonString[i++];
608
609
                if (c == '\\')
610
                {
611
                    int remainingLength = jsonString.Length - i;
612
                    if (remainingLength >= 2)
613
                    {
614
                        char lookahead = jsonString[i];
615
                        if (lookahead == '\\')
616
                        {
617
                            sb.Append('\\');
618
                            ++i;
619
                        }
620
                        else if (lookahead == '"')
621
                        {
622
                            sb.Append("\"");
623
                            ++i;
624
                        }
625
                        else if (lookahead == 't')
626
                        {
627
                            sb.Append('\t');
628
                            ++i;
629
                        }
630
                        else if (lookahead == 'b')
631
                        {
632
                            sb.Append('\b');
633
                            ++i;
634
                        }
635
                        else if (lookahead == 'n')
636
                        {
637
                            sb.Append('\n');
638
                            ++i;
639
                        }
640
                        else if (lookahead == 'r')
641
                        {
642
                            sb.Append('\r');
643
                            ++i;
644
                        }
645
                    }
646
                }
647
                else
648
                {
649
                    sb.Append(c);
650
                }
651
            }
652
            return sb.ToString();
653
        }
654
655
        static IDictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
656
        {
657
            IDictionary<string, object> table = new JsonObject();
658
            int token;
659
660
            // {
661
            NextToken(json, ref index);
662
663
            bool done = false;
664
            while (!done)
665
            {
666
                token = LookAhead(json, index);
667
                if (token == TOKEN_NONE)
668
                {
669
                    success = false;
670
                    return null;
671
                }
672
                else if (token == TOKEN_COMMA)
673
                    NextToken(json, ref index);
674
                else if (token == TOKEN_CURLY_CLOSE)
675
                {
676
                    NextToken(json, ref index);
677
                    return table;
678
                }
679
                else
680
                {
681
                    // name
682
                    string name = ParseString(json, ref index, ref success);
683
                    if (!success)
684
                    {
685
                        success = false;
686
                        return null;
687
                    }
688
                    // :
689
                    token = NextToken(json, ref index);
690
                    if (token != TOKEN_COLON)
691
                    {
692
                        success = false;
693
                        return null;
694
                    }
695
                    // value
696
                    object value = ParseValue(json, ref index, ref success);
697
                    if (!success)
698
                    {
699
                        success = false;
700
                        return null;
701
                    }
702
                    table[name] = value;
703
                }
704
            }
705
            return table;
706
        }
707
708
        static JsonArray ParseArray(char[] json, ref int index, ref bool success)
709
        {
710
            JsonArray array = new JsonArray();
711
712
            // [
713
            NextToken(json, ref index);
714
715
            bool done = false;
716
            while (!done)
717
            {
718
                int token = LookAhead(json, index);
719
                if (token == TOKEN_NONE)
720
                {
721
                    success = false;
722
                    return null;
723
                }
724
                else if (token == TOKEN_COMMA)
725
                    NextToken(json, ref index);
726
                else if (token == TOKEN_SQUARED_CLOSE)
727
                {
728
                    NextToken(json, ref index);
729
                    break;
730
                }
731
                else
732
                {
733
                    object value = ParseValue(json, ref index, ref success);
734
                    if (!success)
735
                        return null;
736
                    array.Add(value);
737
                }
738
            }
739
            return array;
740
        }
741
742
        static object ParseValue(char[] json, ref int index, ref bool success)
743
        {
744
            switch (LookAhead(json, index))
745
            {
746
                case TOKEN_STRING:
747
                    return ParseString(json, ref index, ref success);
748
                case TOKEN_NUMBER:
749
                    return ParseNumber(json, ref index, ref success);
750
                case TOKEN_CURLY_OPEN:
751
                    return ParseObject(json, ref index, ref success);
752
                case TOKEN_SQUARED_OPEN:
753
                    return ParseArray(json, ref index, ref success);
754
                case TOKEN_TRUE:
755
                    NextToken(json, ref index);
756
                    return true;
757
                case TOKEN_FALSE:
758
                    NextToken(json, ref index);
759
                    return false;
760
                case TOKEN_NULL:
761
                    NextToken(json, ref index);
762
                    return null;
763
                case TOKEN_NONE:
764
                    break;
765
            }
766
            success = false;
767
            return null;
768
        }
769
770
        static string ParseString(char[] json, ref int index, ref bool success)
771
        {
772
            StringBuilder s = new StringBuilder(BUILDER_CAPACITY);
773
            char c;
774
775
            EatWhitespace(json, ref index);
776
777
            // "
778
            c = json[index++];
779
            bool complete = false;
780
            while (!complete)
781
            {
782
                if (index == json.Length)
783
                    break;
784
785
                c = json[index++];
786
                if (c == '"')
787
                {
788
                    complete = true;
789
                    break;
790
                }
791
                else if (c == '\\')
792
                {
793
                    if (index == json.Length)
794
                        break;
795
                    c = json[index++];
796
                    if (c == '"')
797
                        s.Append('"');
798
                    else if (c == '\\')
799
                        s.Append('\\');
800
                    else if (c == '/')
801
                        s.Append('/');
802
                    else if (c == 'b')
803
                        s.Append('\b');
804
                    else if (c == 'f')
805
                        s.Append('\f');
806
                    else if (c == 'n')
807
                        s.Append('\n');
808
                    else if (c == 'r')
809
                        s.Append('\r');
810
                    else if (c == 't')
811
                        s.Append('\t');
812
                    else if (c == 'u')
813
                    {
814
                        int remainingLength = json.Length - index;
815
                        if (remainingLength >= 4)
816
                        {
817
                            // parse the 32 bit hex into an integer codepoint
818
                            uint codePoint;
819
                            if (!(success = UInt32.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint)))
820
                                return "";
821
822
                            // convert the integer codepoint to a unicode char and add to string
823
                            if (0xD800 <= codePoint && codePoint <= 0xDBFF)  // if high surrogate
824
                            {
825
                                index += 4; // skip 4 chars
826
                                remainingLength = json.Length - index;
827
                                if (remainingLength >= 6)
828
                                {
829
                                    uint lowCodePoint;
830
                                    if (new string(json, index, 2) == "\\u" && UInt32.TryParse(new string(json, index + 2, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out lowCodePoint))
831
                                    {
832
                                        if (0xDC00 <= lowCodePoint && lowCodePoint <= 0xDFFF)    // if low surrogate
833
                                        {
834
                                            s.Append((char)codePoint);
835
                                            s.Append((char)lowCodePoint);
836
                                            index += 6; // skip 6 chars
837
                                            continue;
838
                                        }
839
                                    }
840
                                }
841
                                success = false;    // invalid surrogate pair
842
                                return "";
843
                            }
844
                            s.Append(ConvertFromUtf32((int)codePoint));
845
                            // skip 4 chars
846
                            index += 4;
847
                        }
848
                        else
849
                            break;
850
                    }
851
                }
852
                else
853
                    s.Append(c);
854
            }
855
            if (!complete)
856
            {
857
                success = false;
858
                return null;
859
            }
860
            return s.ToString();
861
        }
862
863
        private static string ConvertFromUtf32(int utf32)
864
        {
865
            // http://www.java2s.com/Open-Source/CSharp/2.6.4-mono-.net-core/System/System/Char.cs.htm
866
            if (utf32 < 0 || utf32 > 0x10FFFF)
867
                throw new ArgumentOutOfRangeException("utf32", "The argument must be from 0 to 0x10FFFF.");
868
            if (0xD800 <= utf32 && utf32 <= 0xDFFF)
869
                throw new ArgumentOutOfRangeException("utf32", "The argument must not be in surrogate pair range.");
870
            if (utf32 < 0x10000)
871
                return new string((char)utf32, 1);
872
            utf32 -= 0x10000;
873
            return new string(new char[] { (char)((utf32 >> 10) + 0xD800), (char)(utf32 % 0x0400 + 0xDC00) });
874
        }
875
876
        static object ParseNumber(char[] json, ref int index, ref bool success)
877
        {
878
            EatWhitespace(json, ref index);
879
            int lastIndex = GetLastIndexOfNumber(json, index);
880
            int charLength = (lastIndex - index) + 1;
881
            object returnNumber;
882
            string str = new string(json, index, charLength);
883
            if (str.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1 || str.IndexOf("e", StringComparison.OrdinalIgnoreCase) != -1)
884
            {
885
                double number;
886
                success = double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number);
887
                returnNumber = number;
888
            }
889
            else
890
            {
891
                long number;
892
                success = long.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number);
893
                returnNumber = number;
894
            }
895
            index = lastIndex + 1;
896
            return returnNumber;
897
        }
898
899
        static int GetLastIndexOfNumber(char[] json, int index)
900
        {
901
            int lastIndex;
902
            for (lastIndex = index; lastIndex < json.Length; lastIndex++)
903
                if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) break;
904
            return lastIndex - 1;
905
        }
906
907
        static void EatWhitespace(char[] json, ref int index)
908
        {
909
            for (; index < json.Length; index++)
910
                if (" \t\n\r\b\f".IndexOf(json[index]) == -1) break;
911
        }
912
913
        static int LookAhead(char[] json, int index)
914
        {
915
            int saveIndex = index;
916
            return NextToken(json, ref saveIndex);
917
        }
918
919
        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
920
        static int NextToken(char[] json, ref int index)
921
        {
922
            EatWhitespace(json, ref index);
923
            if (index == json.Length)
924
                return TOKEN_NONE;
925
            char c = json[index];
926
            index++;
927
            switch (c)
928
            {
929
                case '{':
930
                    return TOKEN_CURLY_OPEN;
931
                case '}':
932
                    return TOKEN_CURLY_CLOSE;
933
                case '[':
934
                    return TOKEN_SQUARED_OPEN;
935
                case ']':
936
                    return TOKEN_SQUARED_CLOSE;
937
                case ',':
938
                    return TOKEN_COMMA;
939
                case '"':
940
                    return TOKEN_STRING;
941
                case '0':
942
                case '1':
943
                case '2':
944
                case '3':
945
                case '4':
946
                case '5':
947
                case '6':
948
                case '7':
949
                case '8':
950
                case '9':
951
                case '-':
952
                    return TOKEN_NUMBER;
953
                case ':':
954
                    return TOKEN_COLON;
955
            }
956
            index--;
957
            int remainingLength = json.Length - index;
958
            // false
959
            if (remainingLength >= 5)
960
            {
961
                if (json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' && json[index + 4] == 'e')
962
                {
963
                    index += 5;
964
                    return TOKEN_FALSE;
965
                }
966
            }
967
            // true
968
            if (remainingLength >= 4)
969
            {
970
                if (json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e')
971
                {
972
                    index += 4;
973
                    return TOKEN_TRUE;
974
                }
975
            }
976
            // null
977
            if (remainingLength >= 4)
978
            {
979
                if (json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l')
980
                {
981
                    index += 4;
982
                    return TOKEN_NULL;
983
                }
984
            }
985
            return TOKEN_NONE;
986
        }
987
988
        static bool SerializeValue(IJsonSerializerStrategy jsonSerializerStrategy, object value, StringBuilder builder)
989
        {
990
            bool success = true;
991
            string stringValue = value as string;
992
            if (stringValue != null)
993
                success = SerializeString(stringValue, builder);
994
            else
995
            {
996
                IDictionary<string, object> dict = value as IDictionary<string, object>;
997
                if (dict != null)
998
                {
999
                    success = SerializeObject(jsonSerializerStrategy, dict.Keys, dict.Values, builder);
1000
                }
1001
                else
1002
                {
1003
                    IDictionary<string, string> stringDictionary = value as IDictionary<string, string>;
1004
                    if (stringDictionary != null)
1005
                    {
1006
                        success = SerializeObject(jsonSerializerStrategy, stringDictionary.Keys, stringDictionary.Values, builder);
1007
                    }
1008
                    else
1009
                    {
1010
                        IEnumerable enumerableValue = value as IEnumerable;
1011
                        if (enumerableValue != null)
1012
                            success = SerializeArray(jsonSerializerStrategy, enumerableValue, builder);
1013
                        else if (IsNumeric(value))
1014
                            success = SerializeNumber(value, builder);
1015
                        else if (value is bool)
1016
                            builder.Append((bool)value ? "true" : "false");
1017
                        else if (value == null)
1018
                            builder.Append("null");
1019
                        else
1020
                        {
1021
                            object serializedObject;
1022
                            success = jsonSerializerStrategy.TrySerializeNonPrimitiveObject(value, out serializedObject);
1023
                            if (success)
1024
                                SerializeValue(jsonSerializerStrategy, serializedObject, builder);
1025
                        }
1026
                    }
1027
                }
1028
            }
1029
            return success;
1030
        }
1031
1032
        static bool SerializeObject(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable keys, IEnumerable values, StringBuilder builder)
1033
        {
1034
            builder.Append("{");
1035
            IEnumerator ke = keys.GetEnumerator();
1036
            IEnumerator ve = values.GetEnumerator();
1037
            bool first = true;
1038
            while (ke.MoveNext() && ve.MoveNext())
1039
            {
1040
                object key = ke.Current;
1041
                object value = ve.Current;
1042
                if (!first)
1043
                    builder.Append(",");
1044
                string stringKey = key as string;
1045
                if (stringKey != null)
1046
                    SerializeString(stringKey, builder);
1047
                else
1048
                    if (!SerializeValue(jsonSerializerStrategy, value, builder)) return false;
1049
                builder.Append(":");
1050
                if (!SerializeValue(jsonSerializerStrategy, value, builder))
1051
                    return false;
1052
                first = false;
1053
            }
1054
            builder.Append("}");
1055
            return true;
1056
        }
1057
1058
        static bool SerializeArray(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable anArray, StringBuilder builder)
1059
        {
1060
            builder.Append("[");
1061
            bool first = true;
1062
            foreach (object value in anArray)
1063
            {
1064
                if (!first)
1065
                    builder.Append(",");
1066
                if (!SerializeValue(jsonSerializerStrategy, value, builder))
1067
                    return false;
1068
                first = false;
1069
            }
1070
            builder.Append("]");
1071
            return true;
1072
        }
1073
1074
        static bool SerializeString(string aString, StringBuilder builder)
1075
        {
1076
            builder.Append("\"");
1077
            char[] charArray = aString.ToCharArray();
1078
            for (int i = 0; i < charArray.Length; i++)
1079
            {
1080
                char c = charArray[i];
1081
                if (c == '"')
1082
                    builder.Append("\\\"");
1083
                else if (c == '\\')
1084
                    builder.Append("\\\\");
1085
                else if (c == '\b')
1086
                    builder.Append("\\b");
1087
                else if (c == '\f')
1088
                    builder.Append("\\f");
1089
                else if (c == '\n')
1090
                    builder.Append("\\n");
1091
                else if (c == '\r')
1092
                    builder.Append("\\r");
1093
                else if (c == '\t')
1094
                    builder.Append("\\t");
1095
                else
1096
                    builder.Append(c);
1097
            }
1098
            builder.Append("\"");
1099
            return true;
1100
        }
1101
1102
        static bool SerializeNumber(object number, StringBuilder builder)
1103
        {
1104
            if (number is long)
1105
                builder.Append(((long)number).ToString(CultureInfo.InvariantCulture));
1106
            else if (number is ulong)
1107
                builder.Append(((ulong)number).ToString(CultureInfo.InvariantCulture));
1108
            else if (number is int)
1109
                builder.Append(((int)number).ToString(CultureInfo.InvariantCulture));
1110
            else if (number is uint)
1111
                builder.Append(((uint)number).ToString(CultureInfo.InvariantCulture));
1112
            else if (number is decimal)
1113
                builder.Append(((decimal)number).ToString(CultureInfo.InvariantCulture));
1114
            else if (number is float)
1115
                builder.Append(((float)number).ToString(CultureInfo.InvariantCulture));
1116
            else
1117
                builder.Append(Convert.ToDouble(number, CultureInfo.InvariantCulture).ToString("r", CultureInfo.InvariantCulture));
1118
            return true;
1119
        }
1120
1121
        /// <summary>
1122
        /// Determines if a given object is numeric in any way
1123
        /// (can be integer, double, null, etc).
1124
        /// </summary>
1125
        static bool IsNumeric(object value)
1126
        {
1127
            if (value is sbyte) return true;
1128
            if (value is byte) return true;
1129
            if (value is short) return true;
1130
            if (value is ushort) return true;
1131
            if (value is int) return true;
1132
            if (value is uint) return true;
1133
            if (value is long) return true;
1134
            if (value is ulong) return true;
1135
            if (value is float) return true;
1136
            if (value is double) return true;
1137
            if (value is decimal) return true;
1138
            return false;
1139
        }
1140
1141
        private static IJsonSerializerStrategy _currentJsonSerializerStrategy;
1142
        public static IJsonSerializerStrategy CurrentJsonSerializerStrategy
1143
        {
1144
            get
1145
            {
1146
                return _currentJsonSerializerStrategy ??
1147
                    (_currentJsonSerializerStrategy =
1148
#if SIMPLE_JSON_DATACONTRACT
1149
 DataContractJsonSerializerStrategy
1150
#else
1151
 PocoJsonSerializerStrategy
1152
#endif
1153
);
1154
            }
1155
            set
1156
            {
1157
                _currentJsonSerializerStrategy = value;
1158
            }
1159
        }
1160
1161
        private static PocoJsonSerializerStrategy _pocoJsonSerializerStrategy;
1162
        [EditorBrowsable(EditorBrowsableState.Advanced)]
1163
        public static PocoJsonSerializerStrategy PocoJsonSerializerStrategy
1164
        {
1165
            get
1166
            {
1167
                return _pocoJsonSerializerStrategy ?? (_pocoJsonSerializerStrategy = new PocoJsonSerializerStrategy());
1168
            }
1169
        }
1170
1171
#if SIMPLE_JSON_DATACONTRACT
1172
1173
        private static DataContractJsonSerializerStrategy _dataContractJsonSerializerStrategy;
1174
        [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1175
        public static DataContractJsonSerializerStrategy DataContractJsonSerializerStrategy
1176
        {
1177
            get
1178
            {
1179
                return _dataContractJsonSerializerStrategy ?? (_dataContractJsonSerializerStrategy = new DataContractJsonSerializerStrategy());
1180
            }
1181
        }
1182
1183
#endif
1184
    }
1185
    
1186
    [GeneratedCode("simple-json", "1.0.0")]
1187
#if SIMPLE_JSON_INTERNAL
1188
    internal
1189
#else
1190
    public
1191
#endif
1192
 interface IJsonSerializerStrategy
1193
    {
1194
        [SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="Need to support .NET 2")]
1195
        bool TrySerializeNonPrimitiveObject(object input, out object output);
1196
        object DeserializeObject(object value, Type type);
1197
    }
1198
1199
    [GeneratedCode("simple-json", "1.0.0")]
1200
#if SIMPLE_JSON_INTERNAL
1201
    internal
1202
#else
1203
    public
1204
#endif
1205
 class PocoJsonSerializerStrategy : IJsonSerializerStrategy
1206
    {
1207
        internal IDictionary<Type, ReflectionUtils.ConstructorDelegate> ConstructorCache;
1208
        internal IDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>> GetCache;
1209
        internal IDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>> SetCache;
1210
1211
        internal static readonly Type[] EmptyTypes = new Type[0];
1212
        internal static readonly Type[] ArrayConstructorParameterTypes = new Type[] { typeof(int) };
1213
1214
        private static readonly string[] Iso8601Format = new string[]
1215
                                                             {
1216
                                                                 @"yyyy-MM-dd\THH:mm:ss.FFFFFFF\Z",
1217
                                                                 @"yyyy-MM-dd\THH:mm:ss\Z",
1218
                                                                 @"yyyy-MM-dd\THH:mm:ssK"
1219
                                                             };
1220
1221
        public PocoJsonSerializerStrategy()
1222
        {
1223
            ConstructorCache = new ReflectionUtils.ThreadSafeDictionary<Type, ReflectionUtils.ConstructorDelegate>(ContructorDelegateFactory);
1224
            GetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>>(GetterValueFactory);
1225
            SetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>>(SetterValueFactory);
1226
        }
1227
1228
        protected virtual string MapClrMemberNameToJsonFieldName(string clrPropertyName)
1229
        {
1230
            return clrPropertyName;
1231
        }
1232
1233
        internal virtual ReflectionUtils.ConstructorDelegate ContructorDelegateFactory(Type key)
1234
        {
1235
            return ReflectionUtils.GetContructor(key, key.IsArray ? ArrayConstructorParameterTypes : EmptyTypes);
1236
        }
1237
1238
        internal virtual IDictionary<string, ReflectionUtils.GetDelegate> GetterValueFactory(Type type)
1239
        {
1240
            IDictionary<string, ReflectionUtils.GetDelegate> result = new Dictionary<string, ReflectionUtils.GetDelegate>();
1241
            foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties(type))
1242
            {
1243
                if (propertyInfo.CanRead)
1244
                {
1245
                    MethodInfo getMethod = ReflectionUtils.GetGetterMethodInfo(propertyInfo);
1246
                    if (getMethod.IsStatic || !getMethod.IsPublic)
1247
                        continue;
1248
                    result[MapClrMemberNameToJsonFieldName(propertyInfo.Name)] = ReflectionUtils.GetGetMethod(propertyInfo);
1249
                }
1250
            }
1251
            foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields(type))
1252
            {
1253
                if (fieldInfo.IsStatic || !fieldInfo.IsPublic)
1254
                    continue;
1255
                result[MapClrMemberNameToJsonFieldName(fieldInfo.Name)] = ReflectionUtils.GetGetMethod(fieldInfo);
1256
            }
1257
            return result;
1258
        }
1259
1260
        internal virtual IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> SetterValueFactory(Type type)
1261
        {
1262
            IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> result = new Dictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>();
1263
            foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties(type))
1264
            {
1265
                if (propertyInfo.CanWrite)
1266
                {
1267
                    MethodInfo setMethod = ReflectionUtils.GetSetterMethodInfo(propertyInfo);
1268
                    if (setMethod.IsStatic || !setMethod.IsPublic)
1269
                        continue;
1270
                    result[MapClrMemberNameToJsonFieldName(propertyInfo.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(propertyInfo.PropertyType, ReflectionUtils.GetSetMethod(propertyInfo));
1271
                }
1272
            }
1273
            foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields(type))
1274
            {
1275
                if (fieldInfo.IsInitOnly || fieldInfo.IsStatic || !fieldInfo.IsPublic)
1276
                    continue;
1277
                result[MapClrMemberNameToJsonFieldName(fieldInfo.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(fieldInfo.FieldType, ReflectionUtils.GetSetMethod(fieldInfo));
1278
            }
1279
            return result;
1280
        }
1281
1282
        public virtual bool TrySerializeNonPrimitiveObject(object input, out object output)
1283
        {
1284
            return TrySerializeKnownTypes(input, out output) || TrySerializeUnknownTypes(input, out output);
1285
        }
1286
1287
        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
1288
        public virtual object DeserializeObject(object value, Type type)
1289
        {
1290
            if (type == null) throw new ArgumentNullException("type");
1291
            string str = value as string;
1292
1293
            if (type == typeof (Guid) && string.IsNullOrEmpty(str))
1294
                return default(Guid);
1295
1296
            if (value == null)
1297
                return null;
1298
            
1299
            object obj = null;
1300
1301
            if (str != null)
1302
            {
1303
                if (str.Length != 0) // We know it can't be null now.
1304
                {
1305
                    if (type == typeof(DateTime) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTime)))
1306
                        return DateTime.ParseExact(str, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
1307
                    if (type == typeof(DateTimeOffset) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTimeOffset)))
1308
                        return DateTimeOffset.ParseExact(str, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
1309
                    if (type == typeof(Guid) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid)))
1310
                        return new Guid(str);
1311
                    if (type == typeof(Uri))
1312
                    {
1313
                        bool isValid =  Uri.IsWellFormedUriString(str, UriKind.RelativeOrAbsolute);
1314
1315
                        Uri result;
1316
                        if (isValid && Uri.TryCreate(str, UriKind.RelativeOrAbsolute, out result))
1317
                            return result;
1318
                    }
1319
                    return str;
1320
                }
1321
                else
1322
                {
1323
                    if (type == typeof(Guid))
1324
                        obj = default(Guid);
1325
                    else if (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid))
1326
                        obj = null;
1327
                    else
1328
                        obj = str;
1329
                }
1330
                // Empty string case
1331
                if (!ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid))
1332
                    return str;
1333
            }
1334
            else if (value is bool)
1335
                return value;
1336
            
1337
            bool valueIsLong = value is long;
1338
            bool valueIsDouble = value is double;
1339
            if ((valueIsLong && type == typeof(long)) || (valueIsDouble && type == typeof(double)))
1340
                return value;
1341
            if ((valueIsDouble && type != typeof(double)) || (valueIsLong && type != typeof(long)))
1342
            {
1343
                obj = type == typeof(int) || type == typeof(long) || type == typeof(double) || type == typeof(float) || type == typeof(bool) || type == typeof(decimal) || type == typeof(byte) || type == typeof(short)
1344
                            ? Convert.ChangeType(value, type, CultureInfo.InvariantCulture)
1345
                            : value;
1346
            }
1347
            else
1348
            {
1349
                IDictionary<string, object> objects = value as IDictionary<string, object>;
1350
                if (objects != null)
1351
                {
1352
                    IDictionary<string, object> jsonObject = objects;
1353
1354
                    if (ReflectionUtils.IsTypeDictionary(type))
1355
                    {
1356
                        // if dictionary then
1357
                        Type[] types = ReflectionUtils.GetGenericTypeArguments(type);
1358
                        Type keyType = types[0];
1359
                        Type valueType = types[1];
1360
1361
                        Type genericType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
1362
1363
                        IDictionary dict = (IDictionary)ConstructorCache[genericType]();
1364
1365
                        foreach (KeyValuePair<string, object> kvp in jsonObject)
1366
                            dict.Add(kvp.Key, DeserializeObject(kvp.Value, valueType));
1367
1368
                        obj = dict;
1369
                    }
1370
                    else
1371
                    {
1372
                        if (type == typeof(object))
1373
                            obj = value;
1374
                        else
1375
                        {
1376
                            obj = ConstructorCache[type]();
1377
                            foreach (KeyValuePair<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> setter in SetCache[type])
1378
                            {
1379
                                object jsonValue;
1380
                                if (jsonObject.TryGetValue(setter.Key, out jsonValue))
1381
                                {
1382
                                    jsonValue = DeserializeObject(jsonValue, setter.Value.Key);
1383
                                    setter.Value.Value(obj, jsonValue);
1384
                                }
1385
                            }
1386
                        }
1387
                    }
1388
                }
1389
                else
1390
                {
1391
                    IList<object> valueAsList = value as IList<object>;
1392
                    if (valueAsList != null)
1393
                    {
1394
                        IList<object> jsonObject = valueAsList;
1395
                        IList list = null;
1396
1397
                        if (type.IsArray)
1398
                        {
1399
                            list = (IList)ConstructorCache[type](jsonObject.Count);
1400
                            int i = 0;
1401
                            foreach (object o in jsonObject)
1402
                                list[i++] = DeserializeObject(o, type.GetElementType());
1403
                        }
1404
                        else if (ReflectionUtils.IsTypeGenericeCollectionInterface(type) || ReflectionUtils.IsAssignableFrom(typeof(IList), type))
1405
                        {
1406
                            Type innerType = ReflectionUtils.GetGenericListElementType(type);
1407
                            list = (IList)(ConstructorCache[type] ?? ConstructorCache[typeof(List<>).MakeGenericType(innerType)])(jsonObject.Count);
1408
                            foreach (object o in jsonObject)
1409
                                list.Add(DeserializeObject(o, innerType));
1410
                        }
1411
                        obj = list;
1412
                    }
1413
                }
1414
                return obj;
1415
            }
1416
            if (ReflectionUtils.IsNullableType(type))
1417
                return ReflectionUtils.ToNullableType(obj, type);
1418
            return obj;
1419
        }
1420
1421
        protected virtual object SerializeEnum(Enum p)
1422
        {
1423
            return Convert.ToDouble(p, CultureInfo.InvariantCulture);
1424
        }
1425
1426
        [SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="Need to support .NET 2")]
1427
        protected virtual bool TrySerializeKnownTypes(object input, out object output)
1428
        {
1429
            bool returnValue = true;
1430
            if (input is DateTime)
1431
                output = ((DateTime)input).ToUniversalTime().ToString(Iso8601Format[0], CultureInfo.InvariantCulture);
1432
            else if (input is DateTimeOffset)
1433
                output = ((DateTimeOffset)input).ToUniversalTime().ToString(Iso8601Format[0], CultureInfo.InvariantCulture);
1434
            else if (input is Guid)
1435
                output = ((Guid)input).ToString("D");
1436
            else if (input is Uri)
1437
                output = input.ToString();
1438
            else
1439
            {
1440
                Enum inputEnum = input as Enum;
1441
                if (inputEnum != null)
1442
                    output = SerializeEnum(inputEnum);
1443
                else
1444
                {
1445
                    returnValue = false;
1446
                    output = null;
1447
                }
1448
            }
1449
            return returnValue;
1450
        }
1451
        [SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="Need to support .NET 2")]
1452
        protected virtual bool TrySerializeUnknownTypes(object input, out object output)
1453
        {
1454
            if (input == null) throw new ArgumentNullException("input");
1455
            output = null;
1456
            Type type = input.GetType();
1457
            if (type.FullName == null)
1458
                return false;
1459
            IDictionary<string, object> obj = new JsonObject();
1460
            IDictionary<string, ReflectionUtils.GetDelegate> getters = GetCache[type];
1461
            foreach (KeyValuePair<string, ReflectionUtils.GetDelegate> getter in getters)
1462
            {
1463
                if (getter.Value != null)
1464
                    obj.Add(MapClrMemberNameToJsonFieldName(getter.Key), getter.Value(input));
1465
            }
1466
            output = obj;
1467
            return true;
1468
        }
1469
    }
1470
1471
#if SIMPLE_JSON_DATACONTRACT
1472
    [GeneratedCode("simple-json", "1.0.0")]
1473
#if SIMPLE_JSON_INTERNAL
1474
    internal
1475
#else
1476
    public
1477
#endif
1478
 class DataContractJsonSerializerStrategy : PocoJsonSerializerStrategy
1479
    {
1480
        public DataContractJsonSerializerStrategy()
1481
        {
1482
            GetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>>(GetterValueFactory);
1483
            SetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>>(SetterValueFactory);
1484
        }
1485
1486
        internal override IDictionary<string, ReflectionUtils.GetDelegate> GetterValueFactory(Type type)
1487
        {
1488
            bool hasDataContract = ReflectionUtils.GetAttribute(type, typeof(DataContractAttribute)) != null;
1489
            if (!hasDataContract)
1490
                return base.GetterValueFactory(type);
1491
            string jsonKey;
1492
            IDictionary<string, ReflectionUtils.GetDelegate> result = new Dictionary<string, ReflectionUtils.GetDelegate>();
1493
            foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties(type))
1494
            {
1495
                if (propertyInfo.CanRead)
1496
                {
1497
                    MethodInfo getMethod = ReflectionUtils.GetGetterMethodInfo(propertyInfo);
1498
                    if (!getMethod.IsStatic && CanAdd(propertyInfo, out jsonKey))
1499
                        result[jsonKey] = ReflectionUtils.GetGetMethod(propertyInfo);
1500
                }
1501
            }
1502
            foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields(type))
1503
            {
1504
                if (!fieldInfo.IsStatic && CanAdd(fieldInfo, out jsonKey))
1505
                    result[jsonKey] = ReflectionUtils.GetGetMethod(fieldInfo);
1506
            }
1507
            return result;
1508
        }
1509
1510
        internal override IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> SetterValueFactory(Type type)
1511
        {
1512
            bool hasDataContract = ReflectionUtils.GetAttribute(type, typeof(DataContractAttribute)) != null;
1513
            if (!hasDataContract)
1514
                return base.SetterValueFactory(type);
1515
            string jsonKey;
1516
            IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> result = new Dictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>();
1517
            foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties(type))
1518
            {
1519
                if (propertyInfo.CanWrite)
1520
                {
1521
                    MethodInfo setMethod = ReflectionUtils.GetSetterMethodInfo(propertyInfo);
1522
                    if (!setMethod.IsStatic && CanAdd(propertyInfo, out jsonKey))
1523
                        result[jsonKey] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(propertyInfo.PropertyType, ReflectionUtils.GetSetMethod(propertyInfo));
1524
                }
1525
            }
1526
            foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields(type))
1527
            {
1528
                if (!fieldInfo.IsInitOnly && !fieldInfo.IsStatic && CanAdd(fieldInfo, out jsonKey))
1529
                    result[jsonKey] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(fieldInfo.FieldType, ReflectionUtils.GetSetMethod(fieldInfo));
1530
            }
1531
            // todo implement sorting for DATACONTRACT.
1532
            return result;
1533
        }
1534
1535
        private static bool CanAdd(MemberInfo info, out string jsonKey)
1536
        {
1537
            jsonKey = null;
1538
            if (ReflectionUtils.GetAttribute(info, typeof(IgnoreDataMemberAttribute)) != null)
1539
                return false;
1540
            DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)ReflectionUtils.GetAttribute(info, typeof(DataMemberAttribute));
1541
            if (dataMemberAttribute == null)
1542
                return false;
1543
            jsonKey = string.IsNullOrEmpty(dataMemberAttribute.Name) ? info.Name : dataMemberAttribute.Name;
1544
            return true;
1545
        }
1546
    }
1547
1548
#endif
1549
1550
    namespace Reflection
1551
    {
1552
        // This class is meant to be copied into other libraries. So we want to exclude it from Code Analysis rules
1553
 	    // that might be in place in the target project.
1554
        [GeneratedCode("reflection-utils", "1.0.0")]
1555
#if SIMPLE_JSON_REFLECTION_UTILS_PUBLIC
1556
        public
1557
#else
1558
        internal
1559
#endif
1560
 class ReflectionUtils
1561
        {
1562
            private static readonly object[] EmptyObjects = new object[] { };
1563
1564
            public delegate object GetDelegate(object source);
1565
            public delegate void SetDelegate(object source, object value);
1566
            public delegate object ConstructorDelegate(params object[] args);
1567
1568
            public delegate TValue ThreadSafeDictionaryValueFactory<TKey, TValue>(TKey key);
1569
1570
#if SIMPLE_JSON_TYPEINFO
1571
            public static TypeInfo GetTypeInfo(Type type)
1572
            {
1573
                return type.GetTypeInfo();
1574
            }
1575
#else
1576
            public static Type GetTypeInfo(Type type)
1577
            {
1578
                return type;
1579
            }
1580
#endif
1581
1582
            public static Attribute GetAttribute(MemberInfo info, Type type)
1583
            {
1584
#if SIMPLE_JSON_TYPEINFO
1585
                if (info == null || type == null || !info.IsDefined(type))
1586
                    return null;
1587
                return info.GetCustomAttribute(type);
1588
#else
1589
                if (info == null || type == null || !Attribute.IsDefined(info, type))
1590
                    return null;
1591
                return Attribute.GetCustomAttribute(info, type);
1592
#endif
1593
            }
1594
1595
            public static Type GetGenericListElementType(Type type)
1596
            {
1597
                IEnumerable<Type> interfaces;
1598
#if SIMPLE_JSON_TYPEINFO
1599
                interfaces = type.GetTypeInfo().ImplementedInterfaces;
1600
#else
1601
                interfaces = type.GetInterfaces();
1602
#endif
1603
                foreach (Type implementedInterface in interfaces)
1604
                {
1605
                    if (IsTypeGeneric(implementedInterface) &&
1606
                        implementedInterface.GetGenericTypeDefinition() == typeof (IList<>))
1607
                    {
1608
                        return GetGenericTypeArguments(implementedInterface)[0];
1609
                    }
1610
                }
1611
                return GetGenericTypeArguments(type)[0];
1612
            }
1613
1614
            public static Attribute GetAttribute(Type objectType, Type attributeType)
1615
            {
1616
1617
#if SIMPLE_JSON_TYPEINFO
1618
                if (objectType == null || attributeType == null || !objectType.GetTypeInfo().IsDefined(attributeType))
1619
                    return null;
1620
                return objectType.GetTypeInfo().GetCustomAttribute(attributeType);
1621
#else
1622
                if (objectType == null || attributeType == null || !Attribute.IsDefined(objectType, attributeType))
1623
                    return null;
1624
                return Attribute.GetCustomAttribute(objectType, attributeType);
1625
#endif
1626
            }
1627
1628
            public static Type[] GetGenericTypeArguments(Type type)
1629
            {
1630
#if SIMPLE_JSON_TYPEINFO
1631
                return type.GetTypeInfo().GenericTypeArguments;
1632
#else
1633
                return type.GetGenericArguments();
1634
#endif
1635
            }
1636
1637
            public static bool IsTypeGeneric(Type type)
1638
            {
1639
                return GetTypeInfo(type).IsGenericType;
1640
            }
1641
1642
            public static bool IsTypeGenericeCollectionInterface(Type type)
1643
            {
1644
                if (!IsTypeGeneric(type))
1645
                    return false;
1646
1647
                Type genericDefinition = type.GetGenericTypeDefinition();
1648
1649
                return (genericDefinition == typeof(IList<>) || genericDefinition == typeof(ICollection<>) || genericDefinition == typeof(IEnumerable<>));
1650
            }
1651
1652
            public static bool IsAssignableFrom(Type type1, Type type2)
1653
            {
1654
                return GetTypeInfo(type1).IsAssignableFrom(GetTypeInfo(type2));
1655
            }
1656
1657
            public static bool IsTypeDictionary(Type type)
1658
            {
1659
#if SIMPLE_JSON_TYPEINFO
1660
                if (typeof(IDictionary<,>).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
1661
                    return true;
1662
#else
1663
                if (typeof(System.Collections.IDictionary).IsAssignableFrom(type))
1664
                    return true;
1665
#endif
1666
                if (!GetTypeInfo(type).IsGenericType)
1667
                    return false;
1668
1669
                Type genericDefinition = type.GetGenericTypeDefinition();
1670
                return genericDefinition == typeof(IDictionary<,>);
1671
            }
1672
1673
            public static bool IsNullableType(Type type)
1674
            {
1675
                return GetTypeInfo(type).IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
1676
            }
1677
1678
            public static object ToNullableType(object obj, Type nullableType)
1679
            {
1680
                return obj == null ? null : Convert.ChangeType(obj, Nullable.GetUnderlyingType(nullableType), CultureInfo.InvariantCulture);
1681
            }
1682
1683
            public static bool IsValueType(Type type)
1684
            {
1685
                return GetTypeInfo(type).IsValueType;
1686
            }
1687
1688
            public static IEnumerable<ConstructorInfo> GetConstructors(Type type)
1689
            {
1690
#if SIMPLE_JSON_TYPEINFO
1691
                return type.GetTypeInfo().DeclaredConstructors;
1692
#else
1693
                return type.GetConstructors();
1694
#endif
1695
            }
1696
1697
            public static ConstructorInfo GetConstructorInfo(Type type, params Type[] argsType)
1698
            {
1699
                IEnumerable<ConstructorInfo> constructorInfos = GetConstructors(type);
1700
                int i;
1701
                bool matches;
1702
                foreach (ConstructorInfo constructorInfo in constructorInfos)
1703
                {
1704
                    ParameterInfo[] parameters = constructorInfo.GetParameters();
1705
                    if (argsType.Length != parameters.Length)
1706
                        continue;
1707
1708
                    i = 0;
1709
                    matches = true;
1710
                    foreach (ParameterInfo parameterInfo in constructorInfo.GetParameters())
1711
                    {
1712
                        if (parameterInfo.ParameterType != argsType[i])
1713
                        {
1714
                            matches = false;
1715
                            break;
1716
                        }
1717
                    }
1718
1719
                    if (matches)
1720
                        return constructorInfo;
1721
                }
1722
1723
                return null;
1724
            }
1725
1726
            public static IEnumerable<PropertyInfo> GetProperties(Type type)
1727
            {
1728
#if SIMPLE_JSON_TYPEINFO
1729
                return type.GetTypeInfo().DeclaredProperties;
1730
#else
1731
                return type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
1732
#endif
1733
            }
1734
1735
            public static IEnumerable<FieldInfo> GetFields(Type type)
1736
            {
1737
#if SIMPLE_JSON_TYPEINFO
1738
                return type.GetTypeInfo().DeclaredFields;
1739
#else
1740
                return type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
1741
#endif
1742
            }
1743
1744
            public static MethodInfo GetGetterMethodInfo(PropertyInfo propertyInfo)
1745
            {
1746
#if SIMPLE_JSON_TYPEINFO
1747
                return propertyInfo.GetMethod;
1748
#else
1749
                return propertyInfo.GetGetMethod(true);
1750
#endif
1751
            }
1752
1753
            public static MethodInfo GetSetterMethodInfo(PropertyInfo propertyInfo)
1754
            {
1755
#if SIMPLE_JSON_TYPEINFO
1756
                return propertyInfo.SetMethod;
1757
#else
1758
                return propertyInfo.GetSetMethod(true);
1759
#endif
1760
            }
1761
1762
            public static ConstructorDelegate GetContructor(ConstructorInfo constructorInfo)
1763
            {
1764
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
1765
                return GetConstructorByReflection(constructorInfo);
1766
#else
1767
                return GetConstructorByExpression(constructorInfo);
1768
#endif
1769
            }
1770
1771
            public static ConstructorDelegate GetContructor(Type type, params Type[] argsType)
1772
            {
1773
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
1774
                return GetConstructorByReflection(type, argsType);
1775
#else
1776
                return GetConstructorByExpression(type, argsType);
1777
#endif
1778
            }
1779
1780
            public static ConstructorDelegate GetConstructorByReflection(ConstructorInfo constructorInfo)
1781
            {
1782
                return delegate(object[] args) { return constructorInfo.Invoke(args); };
1783
            }
1784
1785
            public static ConstructorDelegate GetConstructorByReflection(Type type, params Type[] argsType)
1786
            {
1787
                ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType);
1788
                return constructorInfo == null ? null : GetConstructorByReflection(constructorInfo);
1789
            }
1790
1791
#if !SIMPLE_JSON_NO_LINQ_EXPRESSION
1792
1793
            public static ConstructorDelegate GetConstructorByExpression(ConstructorInfo constructorInfo)
1794
            {
1795
                ParameterInfo[] paramsInfo = constructorInfo.GetParameters();
1796
                ParameterExpression param = Expression.Parameter(typeof(object[]), "args");
1797
                Expression[] argsExp = new Expression[paramsInfo.Length];
1798
                for (int i = 0; i < paramsInfo.Length; i++)
1799
                {
1800
                    Expression index = Expression.Constant(i);
1801
                    Type paramType = paramsInfo[i].ParameterType;
1802
                    Expression paramAccessorExp = Expression.ArrayIndex(param, index);
1803
                    Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
1804
                    argsExp[i] = paramCastExp;
1805
                }
1806
                NewExpression newExp = Expression.New(constructorInfo, argsExp);
1807
                Expression<Func<object[], object>> lambda = Expression.Lambda<Func<object[], object>>(newExp, param);
1808
                Func<object[], object> compiledLambda = lambda.Compile();
1809
                return delegate(object[] args) { return compiledLambda(args); };
1810
            }
1811
1812
            public static ConstructorDelegate GetConstructorByExpression(Type type, params Type[] argsType)
1813
            {
1814
                ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType);
1815
                return constructorInfo == null ? null : GetConstructorByExpression(constructorInfo);
1816
            }
1817
1818
#endif
1819
1820
            public static GetDelegate GetGetMethod(PropertyInfo propertyInfo)
1821
            {
1822
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
1823
                return GetGetMethodByReflection(propertyInfo);
1824
#else
1825
                return GetGetMethodByExpression(propertyInfo);
1826
#endif
1827
            }
1828
1829
            public static GetDelegate GetGetMethod(FieldInfo fieldInfo)
1830
            {
1831
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
1832
                return GetGetMethodByReflection(fieldInfo);
1833
#else
1834
                return GetGetMethodByExpression(fieldInfo);
1835
#endif
1836
            }
1837
1838
            public static GetDelegate GetGetMethodByReflection(PropertyInfo propertyInfo)
1839
            {
1840
                MethodInfo methodInfo = GetGetterMethodInfo(propertyInfo);
1841
                return delegate(object source) { return methodInfo.Invoke(source, EmptyObjects); };
1842
            }
1843
1844
            public static GetDelegate GetGetMethodByReflection(FieldInfo fieldInfo)
1845
            {
1846
                return delegate(object source) { return fieldInfo.GetValue(source); };
1847
            }
1848
1849
#if !SIMPLE_JSON_NO_LINQ_EXPRESSION
1850
1851
            public static GetDelegate GetGetMethodByExpression(PropertyInfo propertyInfo)
1852
            {
1853
                MethodInfo getMethodInfo = GetGetterMethodInfo(propertyInfo);
1854
                ParameterExpression instance = Expression.Parameter(typeof(object), "instance");
1855
                UnaryExpression instanceCast = (!IsValueType(propertyInfo.DeclaringType)) ? Expression.TypeAs(instance, propertyInfo.DeclaringType) : Expression.Convert(instance, propertyInfo.DeclaringType);
1856
                Func<object, object> compiled = Expression.Lambda<Func<object, object>>(Expression.TypeAs(Expression.Call(instanceCast, getMethodInfo), typeof(object)), instance).Compile();
1857
                return delegate(object source) { return compiled(source); };
1858
            }
1859
1860
            public static GetDelegate GetGetMethodByExpression(FieldInfo fieldInfo)
1861
            {
1862
                ParameterExpression instance = Expression.Parameter(typeof(object), "instance");
1863
                MemberExpression member = Expression.Field(Expression.Convert(instance, fieldInfo.DeclaringType), fieldInfo);
1864
                GetDelegate compiled = Expression.Lambda<GetDelegate>(Expression.Convert(member, typeof(object)), instance).Compile();
1865
                return delegate(object source) { return compiled(source); };
1866
            }
1867
1868
#endif
1869
1870
            public static SetDelegate GetSetMethod(PropertyInfo propertyInfo)
1871
            {
1872
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
1873
                return GetSetMethodByReflection(propertyInfo);
1874
#else
1875
                return GetSetMethodByExpression(propertyInfo);
1876
#endif
1877
            }
1878
1879
            public static SetDelegate GetSetMethod(FieldInfo fieldInfo)
1880
            {
1881
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
1882
                return GetSetMethodByReflection(fieldInfo);
1883
#else
1884
                return GetSetMethodByExpression(fieldInfo);
1885
#endif
1886
            }
1887
1888
            public static SetDelegate GetSetMethodByReflection(PropertyInfo propertyInfo)
1889
            {
1890
                MethodInfo methodInfo = GetSetterMethodInfo(propertyInfo);
1891
                return delegate(object source, object value) { methodInfo.Invoke(source, new object[] { value }); };
1892
            }
1893
1894
            public static SetDelegate GetSetMethodByReflection(FieldInfo fieldInfo)
1895
            {
1896
                return delegate(object source, object value) { fieldInfo.SetValue(source, value); };
1897
            }
1898
1899
#if !SIMPLE_JSON_NO_LINQ_EXPRESSION
1900
1901
            public static SetDelegate GetSetMethodByExpression(PropertyInfo propertyInfo)
1902
            {
1903
                MethodInfo setMethodInfo = GetSetterMethodInfo(propertyInfo);
1904
                ParameterExpression instance = Expression.Parameter(typeof(object), "instance");
1905
                ParameterExpression value = Expression.Parameter(typeof(object), "value");
1906
                UnaryExpression instanceCast = (!IsValueType(propertyInfo.DeclaringType)) ? Expression.TypeAs(instance, propertyInfo.DeclaringType) : Expression.Convert(instance, propertyInfo.DeclaringType);
1907
                UnaryExpression valueCast = (!IsValueType(propertyInfo.PropertyType)) ? Expression.TypeAs(value, propertyInfo.PropertyType) : Expression.Convert(value, propertyInfo.PropertyType);
1908
                Action<object, object> compiled = Expression.Lambda<Action<object, object>>(Expression.Call(instanceCast, setMethodInfo, valueCast), new ParameterExpression[] { instance, value }).Compile();
1909
                return delegate(object source, object val) { compiled(source, val); };
1910
            }
1911
1912
            public static SetDelegate GetSetMethodByExpression(FieldInfo fieldInfo)
1913
            {
1914
                ParameterExpression instance = Expression.Parameter(typeof(object), "instance");
1915
                ParameterExpression value = Expression.Parameter(typeof(object), "value");
1916
                Action<object, object> compiled = Expression.Lambda<Action<object, object>>(
1917
                    Assign(Expression.Field(Expression.Convert(instance, fieldInfo.DeclaringType), fieldInfo), Expression.Convert(value, fieldInfo.FieldType)), instance, value).Compile();
1918
                return delegate(object source, object val) { compiled(source, val); };
1919
            }
1920
1921
            public static BinaryExpression Assign(Expression left, Expression right)
1922
            {
1923
#if SIMPLE_JSON_TYPEINFO
1924
                return Expression.Assign(left, right);
1925
#else
1926
                MethodInfo assign = typeof(Assigner<>).MakeGenericType(left.Type).GetMethod("Assign");
1927
                BinaryExpression assignExpr = Expression.Add(left, right, assign);
1928
                return assignExpr;
1929
#endif
1930
            }
1931
1932
            private static class Assigner<T>
1933
            {
1934
                public static T Assign(ref T left, T right)
1935
                {
1936
                    return (left = right);
1937
                }
1938
            }
1939
1940
#endif
1941
1942
            public sealed class ThreadSafeDictionary<TKey, TValue> : IDictionary<TKey, TValue>
1943
            {
1944
                private readonly object _lock = new object();
1945
                private readonly ThreadSafeDictionaryValueFactory<TKey, TValue> _valueFactory;
1946
                private Dictionary<TKey, TValue> _dictionary;
1947
1948
                public ThreadSafeDictionary(ThreadSafeDictionaryValueFactory<TKey, TValue> valueFactory)
1949
                {
1950
                    _valueFactory = valueFactory;
1951
                }
1952
1953
                private TValue Get(TKey key)
1954
                {
1955
                    if (_dictionary == null)
1956
                        return AddValue(key);
1957
                    TValue value;
1958
                    if (!_dictionary.TryGetValue(key, out value))
1959
                        return AddValue(key);
1960
                    return value;
1961
                }
1962
1963
                private TValue AddValue(TKey key)
1964
                {
1965
                    TValue value = _valueFactory(key);
1966
                    lock (_lock)
1967
                    {
1968
                        if (_dictionary == null)
1969
                        {
1970
                            _dictionary = new Dictionary<TKey, TValue>();
1971
                            _dictionary[key] = value;
1972
                        }
1973
                        else
1974
                        {
1975
                            TValue val;
1976
                            if (_dictionary.TryGetValue(key, out val))
1977
                                return val;
1978
                            Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>(_dictionary);
1979
                            dict[key] = value;
1980
                            _dictionary = dict;
1981
                        }
1982
                    }
1983
                    return value;
1984
                }
1985
1986
                public void Add(TKey key, TValue value)
1987
                {
1988
                    throw new NotImplementedException();
1989
                }
1990
1991
                public bool ContainsKey(TKey key)
1992
                {
1993
                    return _dictionary.ContainsKey(key);
1994
                }
1995
1996
                public ICollection<TKey> Keys
1997
                {
1998
                    get { return _dictionary.Keys; }
1999
                }
2000
2001
                public bool Remove(TKey key)
2002
                {
2003
                    throw new NotImplementedException();
2004
                }
2005
2006
                public bool TryGetValue(TKey key, out TValue value)
2007
                {
2008
                    value = this[key];
2009
                    return true;
2010
                }
2011
2012
                public ICollection<TValue> Values
2013
                {
2014
                    get { return _dictionary.Values; }
2015
                }
2016
2017
                public TValue this[TKey key]
2018
                {
2019
                    get { return Get(key); }
2020
                    set { throw new NotImplementedException(); }
2021
                }
2022
2023
                public void Add(KeyValuePair<TKey, TValue> item)
2024
                {
2025
                    throw new NotImplementedException();
2026
                }
2027
2028
                public void Clear()
2029
                {
2030
                    throw new NotImplementedException();
2031
                }
2032
2033
                public bool Contains(KeyValuePair<TKey, TValue> item)
2034
                {
2035
                    throw new NotImplementedException();
2036
                }
2037
2038
                public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
2039
                {
2040
                    throw new NotImplementedException();
2041
                }
2042
2043
                public int Count
2044
                {
2045
                    get { return _dictionary.Count; }
2046
                }
2047
2048
                public bool IsReadOnly
2049
                {
2050
                    get { throw new NotImplementedException(); }
2051
                }
2052
2053
                public bool Remove(KeyValuePair<TKey, TValue> item)
2054
                {
2055
                    throw new NotImplementedException();
2056
                }
2057
2058
                public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
2059
                {
2060
                    return _dictionary.GetEnumerator();
2061
                }
2062
2063
                System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
2064
                {
2065
                    return _dictionary.GetEnumerator();
2066
                }
2067
            }
2068
2069
        }
2070
    }
2071
}
2072
// ReSharper restore LoopCanBeConvertedToQuery
2073
// ReSharper restore RedundantExplicitArrayCreation
2074
// ReSharper restore SuggestUseVarKeywordEvident