Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mcs / class / System.Json.Microsoft / System.Json / JsonValue.cs
1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
2
3 using System.Collections;
4 using System.Collections.Generic;
5 using System.ComponentModel;
6 using System.Diagnostics.CodeAnalysis;
7 #if FEATURE_DYNAMIC
8 using System.Dynamic;
9 #endif
10 using System.Globalization;
11 using System.IO;
12 using System.Linq.Expressions;
13 using System.Runtime.Serialization;
14 using System.Runtime.Serialization.Json;
15 using System.Text;
16 using System.Xml;
17
18 namespace System.Json
19 {
20     /// <summary>
21     /// This is the base class for JavaScript Object Notation (JSON) common language runtime (CLR) types. 
22     /// </summary>
23     [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix",
24         Justification = "JsonValue is by definition either a collection or a single object.")]
25     [DataContract]
26 #if FEATURE_DYNAMIC
27     public class JsonValue : IEnumerable<KeyValuePair<string, JsonValue>>, IDynamicMetaObjectProvider
28 #else
29     public class JsonValue : IEnumerable<KeyValuePair<string, JsonValue>>
30 #endif
31     {
32         private static JsonValue defaultInstance = new JsonValue();
33         private int changingListenersCount;
34         private int changedListenersCount;
35
36         internal JsonValue()
37         {
38         }
39
40         /// <summary>
41         /// Raised when this <see cref="System.Json.JsonValue"/> or any of its members have changed.
42         /// </summary>
43         /// <remarks><p>Events are raised when elements are added or removed to <see cref="System.Json.JsonValue"/>
44         /// instances. It applies to both complex descendants of <see cref="System.Json.JsonValue"/>: <see cref="System.Json.JsonArray"/>
45         /// and <see cref="System.Json.JsonObject"/>.</p>
46         /// <p>You should be careful when modifying a <see cref="System.Json.JsonValue"/> tree within one of these events,
47         /// because doing this might lead to unexpected results. For example, if you receive a Changing event, and while
48         /// the event is being processed you remove the node from the tree, you might not receive the Changed event. When
49         /// an event is being processed, it is valid to modify a tree other than the one that contains the node that is
50         /// receiving the event; it is even valid to modify the same tree provided the modifications do not affect the
51         /// specific nodes on which the event was raised. However, if you modify the area of the tree that contains the
52         /// node receiving the event, the events that you receive and the impact to the tree are undefined.</p></remarks>
53         public event EventHandler<JsonValueChangeEventArgs> Changed
54         {
55             add
56             {
57                 changedListenersCount++;
58                 OnChanged += value;
59             }
60
61             remove
62             {
63                 changedListenersCount--;
64                 OnChanged -= value;
65             }
66         }
67
68         /// <summary>
69         /// Raised when this <see cref="System.Json.JsonValue"/> or any of its members are about to be changed.
70         /// </summary>
71         /// <remarks><p>Events are raised when elements are added or removed to <see cref="System.Json.JsonValue"/>
72         /// instances. It applies to both complex descendants of <see cref="System.Json.JsonValue"/>: <see cref="System.Json.JsonArray"/>
73         /// and <see cref="System.Json.JsonObject"/>.</p>
74         /// <p>You should be careful when modifying a <see cref="System.Json.JsonValue"/> tree within one of these events,
75         /// because doing this might lead to unexpected results. For example, if you receive a Changing event, and while
76         /// the event is being processed you remove the node from the tree, you might not receive the Changed event. When
77         /// an event is being processed, it is valid to modify a tree other than the one that contains the node that is
78         /// receiving the event; it is even valid to modify the same tree provided the modifications do not affect the
79         /// specific nodes on which the event was raised. However, if you modify the area of the tree that contains the
80         /// node receiving the event, the events that you receive and the impact to the tree are undefined.</p></remarks>
81         public event EventHandler<JsonValueChangeEventArgs> Changing
82         {
83             add
84             {
85                 changingListenersCount++;
86                 OnChanging += value;
87             }
88
89             remove
90             {
91                 changingListenersCount--;
92                 OnChanging -= value;
93             }
94         }
95
96         private event EventHandler<JsonValueChangeEventArgs> OnChanged;
97         private event EventHandler<JsonValueChangeEventArgs> OnChanging;
98
99         /// <summary>
100         /// Gets the JSON CLR type represented by this instance.
101         /// </summary>
102         public virtual JsonType JsonType
103         {
104             get { return JsonType.Default; }
105         }
106
107         /// <summary>
108         /// Gets the number of items in this object.
109         /// </summary>
110         public virtual int Count
111         {
112             get { return 0; }
113         }
114
115         /// <summary>
116         /// Gets the number of listeners to the <see cref="Changing"/> event for this instance.
117         /// </summary>
118         protected int ChangingListenersCount
119         {
120             get { return changingListenersCount; }
121         }
122
123         /// <summary>
124         /// Gets the number of listeners to the <see cref="Changed"/> event for this instance.
125         /// </summary>
126         protected int ChangedListenersCount
127         {
128             get { return changedListenersCount; }
129         }
130
131         /// <summary>
132         /// Gets the default JsonValue instance.  
133         /// This instance enables safe-chaining of JsonValue operations and resolves to 'null'
134         /// when this instance is used as dynamic, mapping to the JavaScript 'null' value.
135         /// </summary>
136         private static JsonValue DefaultInstance
137         {
138             get { return defaultInstance; }
139         }
140
141         /// <summary>
142         /// This indexer is not supported for this base class and throws an exception.
143         /// </summary>
144         /// <param name="key">The key of the element to get or set.</param>
145         /// <returns><see cref="System.Json.JsonValue"/>.</returns>
146         /// <remarks>The exception thrown is the <see cref="System.InvalidOperationException"/>.
147         /// This method is overloaded in the implementation of the <see cref="System.Json.JsonObject"/>
148         /// class, which inherits from this class.</remarks>
149         public virtual JsonValue this[string key]
150         {
151             get { throw new InvalidOperationException(RS.Format(Properties.Resources.IndexerNotSupportedOnJsonType, typeof(string), JsonType)); }
152
153             set { throw new InvalidOperationException(RS.Format(Properties.Resources.IndexerNotSupportedOnJsonType, typeof(string), JsonType)); }
154         }
155
156         /// <summary>
157         /// This indexer is not supported for this base class and throws an exception.
158         /// </summary>
159         /// <param name="index">The zero-based index of the element to get or set.</param>
160         /// <returns><see cref="System.Json.JsonValue"/>.</returns>
161         /// <remarks>The exception thrown is the <see cref="System.InvalidOperationException"/>.
162         /// This method is overloaded in the implementation of the <see cref="System.Json.JsonArray"/>
163         /// class, which inherits from this class.</remarks>
164         public virtual JsonValue this[int index]
165         {
166             get { throw new InvalidOperationException(RS.Format(Properties.Resources.IndexerNotSupportedOnJsonType, typeof(int), JsonType)); }
167
168             set { throw new InvalidOperationException(RS.Format(Properties.Resources.IndexerNotSupportedOnJsonType, typeof(int), JsonType)); }
169         }
170
171         /// <summary>
172         /// Deserializes text-based JSON into a JSON CLR type.
173         /// </summary>
174         /// <param name="json">The text-based JSON to be parsed into a JSON CLR type.</param>
175         /// <returns>The <see cref="System.Json.JsonValue"/> object that represents the parsed
176         /// text-based JSON as a CLR type.</returns>
177         /// <exception cref="System.ArgumentException">The length of jsonString is zero.</exception>
178         /// <exception cref="System.ArgumentNullException">jsonString is null.</exception>
179         /// <remarks>The result will be an instance of either <see cref="System.Json.JsonArray"/>,
180         /// <see cref="System.Json.JsonObject"/> or <see cref="System.Json.JsonPrimitive"/>,
181         /// depending on the text-based JSON supplied to the method.</remarks>
182         public static JsonValue Parse(string json)
183         {
184             return JXmlToJsonValueConverter.JXMLToJsonValue(json);
185         }
186
187         /// <summary>
188         /// Deserializes text-based JSON from a text reader into a JSON CLR type.
189         /// </summary>
190         /// <param name="textReader">A <see cref="System.IO.TextReader"/> over text-based JSON content.</param>
191         /// <returns>The <see cref="System.Json.JsonValue"/> object that represents the parsed
192         /// text-based JSON as a CLR type.</returns>
193         /// <exception cref="System.ArgumentNullException">textReader is null.</exception>
194         /// <remarks>The result will be an instance of either <see cref="System.Json.JsonArray"/>,
195         /// <see cref="System.Json.JsonObject"/> or <see cref="System.Json.JsonPrimitive"/>,
196         /// depending on the text-based JSON supplied to the method.</remarks>
197         public static JsonValue Load(TextReader textReader)
198         {
199             if (textReader == null)
200             {
201                 throw new ArgumentNullException("textReader");
202             }
203
204             return JsonValue.Parse(textReader.ReadToEnd());
205         }
206
207         /// <summary>
208         /// Deserializes text-based JSON from a stream into a JSON CLR type.
209         /// </summary>
210         /// <param name="stream">A <see cref="System.IO.Stream"/> that contains text-based JSON content.</param>
211         /// <returns>The <see cref="System.Json.JsonValue"/> object that represents the parsed
212         /// text-based JSON as a CLR type.</returns>
213         /// <exception cref="System.ArgumentNullException">stream is null.</exception>
214         /// <remarks>The result will be an instance of either <see cref="System.Json.JsonArray"/>,
215         /// <see cref="System.Json.JsonObject"/> or <see cref="System.Json.JsonPrimitive"/>,
216         /// depending on the text-based JSON supplied to the method.</remarks>
217         public static JsonValue Load(Stream stream)
218         {
219             return JXmlToJsonValueConverter.JXMLToJsonValue(stream);
220         }
221
222         /// <summary>
223         /// Performs a cast operation from a <see cref="JsonValue"/> instance into the specified type parameter./>
224         /// </summary>
225         /// <typeparam name="T">The type to cast the instance to.</typeparam>
226         /// <param name="value">The <see cref="System.Json.JsonValue"/> instance.</param>
227         /// <returns>An object of type T initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
228         /// <remarks>This method is to support the framework and is not intended to be used externally, use explicit type cast instead.</remarks>
229         [EditorBrowsable(EditorBrowsableState.Never)]
230         [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter",
231             Justification = "The generic parameter is used to specify the output type")]
232         public static T CastValue<T>(JsonValue value)
233         {
234             Type typeofT = typeof(T);
235
236             if ((value != null && typeofT.IsAssignableFrom(value.GetType())) || typeofT == typeof(object))
237             {
238                 return (T)(object)value;
239             }
240
241             if (value == null || value.JsonType == JsonType.Default)
242             {
243                 if (typeofT.IsValueType)
244                 {
245                     throw new InvalidCastException(RS.Format(Properties.Resources.InvalidCastNonNullable, typeofT.FullName));
246                 }
247                 else
248                 {
249                     return default(T);
250                 }
251             }
252
253             try
254             {
255                 return value.ReadAs<T>();
256             }
257             catch (Exception ex)
258             {
259                 if (ex is FormatException || ex is NotSupportedException || ex is InvalidCastException)
260                 {
261                     throw new InvalidCastException(RS.Format(Properties.Resources.CannotCastJsonValue, value.GetType().FullName, typeofT.FullName), ex);
262                 }
263
264                 throw;
265             }
266         }
267
268         /// <summary>
269         /// Returns an enumerator which iterates through the values in this object.
270         /// </summary>
271         /// <returns>An enumerator which which iterates through the values in this object.</returns>
272         /// <remarks>The enumerator returned by this class is empty; subclasses will override this method to return appropriate enumerators for themselves.</remarks>
273         public IEnumerator<KeyValuePair<string, JsonValue>> GetEnumerator()
274         {
275             return GetKeyValuePairEnumerator();
276         }
277
278         /// <summary>
279         /// Returns an enumerator which iterates through the values in this object.
280         /// </summary>
281         /// <returns>An <see cref="System.Collections.IEnumerator"/> which iterates through the values in this object.</returns>
282         /// <remarks>The enumerator returned by this class is empty; subclasses will override this method to return appropriate enumerators for themselves.</remarks>
283         IEnumerator IEnumerable.GetEnumerator()
284         {
285             return GetKeyValuePairEnumerator();
286         }
287
288 #if FEATURE_DYNAMIC
289         /// <summary>
290         /// Gets this instance as a <code>dynamic</code> object.
291         /// </summary>
292         /// <returns>This instance as <code>dynamic</code>.</returns>
293         public dynamic AsDynamic()
294         {
295             return this;
296         }
297 #endif
298
299         /// <summary>
300         /// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into the type T.
301         /// </summary>
302         /// <typeparam name="T">The type to which the conversion is being performed.</typeparam>
303         /// <param name="valueOfT">An instance of T initialized with this instance, or the default value of T if the conversion cannot be performed.</param>
304         /// <returns>true if this <see cref="System.Json.JsonValue"/> instance can be read as type T; otherwise, false.</returns>
305         public bool TryReadAs<T>(out T valueOfT)
306         {
307             object value;
308             if (TryReadAs(typeof(T), out value))
309             {
310                 valueOfT = (T)value;
311                 return true;
312             }
313
314             valueOfT = default(T);
315             return false;
316         }
317
318         /// <summary>
319         /// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into the type T.
320         /// </summary>
321         /// <typeparam name="T">The type to which the conversion is being performed.</typeparam>
322         /// <returns>An instance of T initialized with the value from the conversion of this instance.</returns>
323         /// <exception cref="System.NotSupportedException">If this <see cref="System.Json.JsonValue"/> value cannot be converted into the type T.</exception>
324         [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter",
325             Justification = "The generic parameter is used to specify the output type")]
326         public T ReadAs<T>()
327         {
328             return (T)ReadAs(typeof(T));
329         }
330
331         /// <summary>
332         /// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into the type T.
333         /// </summary>
334         /// <typeparam name="T">The type to which the conversion is being performed.</typeparam>
335         /// <param name="fallback">The fallback value to be returned if the conversion cannot be made.</param>
336         /// <returns>An instance of T initialized with the value from the conversion of this instance, or the specified fallback value if the conversion cannot be made.</returns>
337         public T ReadAs<T>(T fallback)
338         {
339             return (T)ReadAs(typeof(T), fallback);
340         }
341
342         /// <summary>
343         /// Attempts to convert this <see cref="System.Json.JsonValue"/> instance to an instance of the specified type.
344         /// </summary>
345         /// <param name="type">The type to which the conversion is being performed.</param>
346         /// <param name="fallback">The fallback value to be returned if the conversion cannot be made.</param>
347         /// <returns>An instance of the specified type initialized with the value from the conversion of this instance, or the specified fallback value if the conversion cannot be made.</returns>
348         public object ReadAs(Type type, object fallback)
349         {
350             if (type == null)
351             {
352                 throw new ArgumentNullException("type");
353             }
354
355             object result;
356             if (JsonType != JsonType.Default && TryReadAs(type, out result))
357             {
358                 return result;
359             }
360             else
361             {
362                 return fallback;
363             }
364         }
365
366         /// <summary>
367         /// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into an instance of the specified type.
368         /// </summary>
369         /// <param name="type">The type to which the conversion is being performed.</param>
370         /// <returns>An instance of the specified type initialized with the value from the conversion of this instance.</returns>
371         /// <exception cref="System.NotSupportedException">If this <see cref="System.Json.JsonValue"/> value cannot be converted into the type T.</exception>
372         public virtual object ReadAs(Type type)
373         {
374             if (type == null)
375             {
376                 throw new ArgumentNullException("type");
377             }
378
379             object result;
380             if (TryReadAs(type, out result))
381             {
382                 return result;
383             }
384
385             throw new NotSupportedException(RS.Format(Properties.Resources.CannotReadAsType, GetType().FullName, type.FullName));
386         }
387
388         /// <summary>
389         /// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into an instance of the specified type.
390         /// </summary>
391         /// <param name="type">The type to which the conversion is being performed.</param>
392         /// <param name="value">An object to be initialized with this instance or null if the conversion cannot be performed.</param>
393         /// <returns>true if this <see cref="System.Json.JsonValue"/> instance can be read as the specified type; otherwise, false.</returns>
394         [SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate",
395             Justification = "This is the non-generic version of the method.")]
396         public virtual bool TryReadAs(Type type, out object value)
397         {
398             if (type == null)
399             {
400                 throw new ArgumentNullException("type");
401             }
402
403             if (type.IsAssignableFrom(GetType()) || type == typeof(object))
404             {
405                 value = this;
406                 return true;
407             }
408
409             value = null;
410             return false;
411         }
412
413         /// <summary>
414         /// Writes this <see cref="System.Json.JsonValue"/> instance to a <see cref="System.IO.Stream"/>.
415         /// </summary>
416         /// <param name="stream">Stream to which to write text-based JSON.</param>
417         public void Save(Stream stream)
418         {
419             if (JsonType == JsonType.Default)
420             {
421                 throw new InvalidOperationException(Properties.Resources.UseOfDefaultNotAllowed);
422             }
423
424             if (stream == null)
425             {
426                 throw new ArgumentNullException("stream");
427             }
428
429             using (XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8, false))
430             {
431                 jsonWriter.WriteStartElement(JXmlToJsonValueConverter.RootElementName);
432                 Save(jsonWriter);
433                 jsonWriter.WriteEndElement();
434             }
435         }
436
437         /// <summary>
438         /// Writes <see cref="System.Json.JsonValue"/> instance to a <see cref="TextWriter"/>.
439         /// </summary>
440         /// <param name="textWriter">The <see cref="System.IO.TextWriter"/> used to write text-based JSON.</param>
441         public void Save(TextWriter textWriter)
442         {
443             if (JsonType == JsonType.Default)
444             {
445                 throw new InvalidOperationException(Properties.Resources.UseOfDefaultNotAllowed);
446             }
447
448             if (textWriter == null)
449             {
450                 throw new ArgumentNullException("textWriter");
451             }
452
453             using (MemoryStream ms = new MemoryStream())
454             {
455                 Save(ms);
456                 ms.Position = 0;
457                 textWriter.Write(new StreamReader(ms).ReadToEnd());
458             }
459         }
460
461         /// <summary>
462         /// Provides a textual representation of this <see cref="System.Json.JsonValue"/> instance.
463         /// </summary>
464         /// <returns>A <see cref="System.String"/> containing text-based JSON.</returns>
465         public override string ToString()
466         {
467             if (JsonType == JsonType.Default)
468             {
469                 return "Default";
470             }
471
472             using (MemoryStream ms = new MemoryStream())
473             {
474                 Save(ms);
475                 ms.Position = 0;
476                 return new StreamReader(ms).ReadToEnd();
477             }
478         }
479
480         /// <summary>
481         /// Checks whether a key/value pair with a specified key exists in the JSON CLR object type.
482         /// </summary>
483         /// <param name="key">The key to check for.</param>
484         /// <returns>false in this class; subclasses may override this method to return other values.</returns>
485         /// <remarks>This method is overloaded in the implementation of the <see cref="System.Json.JsonObject"/>
486         /// class, which inherits from this class.</remarks>
487         public virtual bool ContainsKey(string key)
488         {
489             return false;
490         }
491
492         /// <summary>
493         /// Returns the value returned by the safe string indexer for this instance.
494         /// </summary>
495         /// <param name="key">The key of the element to get.</param>
496         /// <returns>If this is an instance of <see cref="System.Json.JsonObject"/>, it contains
497         /// the given key and the value corresponding to the key is not null, then it will return that value.
498         /// Otherwise it will return a <see cref="System.Json.JsonValue"/> instance with <see cref="System.Json.JsonValue.JsonType"/>
499         /// equals to <see cref="F:System.Json.JsonType.Default"/>.</returns>
500         [EditorBrowsable(EditorBrowsableState.Never)]
501         public virtual JsonValue GetValue(string key)
502         {
503             return ValueOrDefault(key);
504         }
505
506         /// <summary>
507         /// Returns the value returned by the safe int indexer for this instance.
508         /// </summary>
509         /// <param name="index">The zero-based index of the element to get.</param>
510         /// <returns>If this is an instance of <see cref="System.Json.JsonArray"/>, the index is within the array
511         /// bounds, and the value corresponding to the index is not null, then it will return that value.
512         /// Otherwise it will return a <see cref="System.Json.JsonValue"/> instance with <see cref="System.Json.JsonValue.JsonType"/>
513         /// equals to <see cref="F:System.Json.JsonType.Default"/>.</returns>
514         [EditorBrowsable(EditorBrowsableState.Never)]
515         public virtual JsonValue GetValue(int index)
516         {
517             return ValueOrDefault(index);
518         }
519
520         /// <summary>
521         /// Sets the value and returns it.
522         /// </summary>
523         /// <param name="key">The key of the element to set.</param>
524         /// <param name="value">The value to be set.</param>
525         /// <returns>The value, converted into a JsonValue, set in this collection.</returns>
526         /// <exception cref="System.ArgumentException">If the value cannot be converted into a JsonValue.</exception>
527         [EditorBrowsable(EditorBrowsableState.Never)]
528         public virtual JsonValue SetValue(string key, object value)
529         {
530             this[key] = ResolveObject(value);
531             return this[key];
532         }
533
534         /// <summary>
535         /// Sets the value and returns it.
536         /// </summary>
537         /// <param name="index">The zero-based index of the element to set.</param>
538         /// <param name="value">The value to be set.</param>
539         /// <returns>The value, converted into a JsonValue, set in this collection.</returns>
540         /// <exception cref="System.ArgumentException">If the value cannot be converted into a JsonValue.</exception>
541         [EditorBrowsable(EditorBrowsableState.Never)]
542         public virtual JsonValue SetValue(int index, object value)
543         {
544             this[index] = ResolveObject(value);
545             return this[index];
546         }
547
548         /// <summary>
549         /// Safe string indexer for the <see cref="System.Json.JsonValue"/> type. 
550         /// </summary>
551         /// <param name="key">The key of the element to get.</param>
552         /// <returns>If this is an instance of <see cref="System.Json.JsonObject"/>, it contains
553         /// the given key and the value corresponding to the key is not null, then it will return that value.
554         /// Otherwise it will return a <see cref="System.Json.JsonValue"/> instance with <see cref="System.Json.JsonValue.JsonType"/>
555         /// equals to <see cref="F:System.Json.JsonType.Default"/>.</returns>
556         public virtual JsonValue ValueOrDefault(string key)
557         {
558             return JsonValue.DefaultInstance;
559         }
560
561         /// <summary>
562         /// Safe indexer for the <see cref="System.Json.JsonValue"/> type. 
563         /// </summary>
564         /// <param name="index">The zero-based index of the element to get.</param>
565         /// <returns>If this is an instance of <see cref="System.Json.JsonArray"/>, the index is within the array
566         /// bounds, and the value corresponding to the index is not null, then it will return that value.
567         /// Otherwise it will return a <see cref="System.Json.JsonValue"/> instance with <see cref="System.Json.JsonValue.JsonType"/>
568         /// equals to <see cref="F:System.Json.JsonType.Default"/>.</returns>
569         public virtual JsonValue ValueOrDefault(int index)
570         {
571             return JsonValue.DefaultInstance;
572         }
573
574         /// <summary>
575         /// Safe deep indexer for the <see cref="JsonValue"/> type.
576         /// </summary>
577         /// <param name="indexes">The indices to index this type. The indices can be
578         /// of type <see cref="System.Int32"/> or <see cref="System.String"/>.</param>
579         /// <returns>A <see cref="JsonValue"/> which is equivalent to calling<see cref="ValueOrDefault(int)"/> or
580         /// <see cref="ValueOrDefault(string)"/> on the first index, then calling it again on the result
581         /// for the second index and so on.</returns>
582         /// <exception cref="System.ArgumentException">If any of the indices is not of type
583         /// <see cref="System.Int32"/> or <see cref="System.String"/>.</exception>
584         public JsonValue ValueOrDefault(params object[] indexes)
585         {
586             if (indexes == null)
587             {
588                 return JsonValue.DefaultInstance;
589             }
590
591             if (indexes.Length == 0)
592             {
593                 return this;
594             }
595
596             JsonValue result = this;
597             for (int i = 0; i < indexes.Length; i++)
598             {
599                 object index = indexes[i];
600                 if (index == null)
601                 {
602                     result = JsonValue.DefaultInstance;
603                     continue;
604                 }
605
606                 Type indexType = index.GetType();
607
608                 switch (Type.GetTypeCode(indexType))
609                 {
610                     case TypeCode.Char:
611                     case TypeCode.Int16:
612                     case TypeCode.UInt16:
613                     case TypeCode.Byte:
614                     case TypeCode.SByte:
615                         index = System.Convert.ChangeType(index, typeof(int), CultureInfo.InvariantCulture);
616                         goto case TypeCode.Int32;
617
618                     case TypeCode.Int32:
619                         result = result.ValueOrDefault((int)index);
620                         break;
621
622                     case TypeCode.String:
623                         result = result.ValueOrDefault((string)index);
624                         break;
625
626                     default:
627                         throw new ArgumentException(RS.Format(Properties.Resources.InvalidIndexType, index.GetType()), "indexes");
628                 }
629             }
630
631             return result;
632         }
633
634 #if FEATURE_DYNAMIC
635         [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes",
636             Justification = "Cannot make this class sealed, it needs to have subclasses. But its subclasses are sealed themselves.")]
637         DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
638         {
639             if (parameter == null)
640             {
641                 throw new ArgumentNullException("parameter");
642             }
643
644             return new JsonValueDynamicMetaObject(parameter, this);
645         }
646 #endif
647
648         /// <summary>
649         /// Resolves the specified object to an appropriate JsonValue instance.
650         /// </summary>
651         /// <param name="value">The object to resolve.</param>
652         /// <returns>A <see cref="JsonValue"/> instance resolved from the specified object.</returns>
653         internal static JsonValue ResolveObject(object value)
654         {
655             JsonPrimitive primitive;
656
657             if (value == null)
658             {
659                 return null;
660             }
661
662             JsonValue jsonValue = value as JsonValue;
663
664             if (jsonValue != null)
665             {
666                 return jsonValue;
667             }
668
669             if (JsonPrimitive.TryCreate(value, out primitive))
670             {
671                 return primitive;
672             }
673
674             throw new ArgumentException(Properties.Resources.TypeNotSupported, "value");
675         }
676
677         /// <summary>
678         /// Determines whether an explicit cast to JsonValue is provided from the specified type.
679         /// </summary>
680         /// <param name="type">The type to check.</param>
681         /// <returns>true if an explicit cast exists for the specified type, false otherwise.</returns>
682         internal static bool IsSupportedExplicitCastType(Type type)
683         {
684             TypeCode typeCode = Type.GetTypeCode(type);
685
686             switch (typeCode)
687             {
688                 case TypeCode.Boolean:
689                 case TypeCode.Byte:
690                 case TypeCode.Char:
691                 case TypeCode.DateTime:
692                 case TypeCode.Decimal:
693                 case TypeCode.Double:
694                 case TypeCode.Int16:
695                 case TypeCode.Int32:
696                 case TypeCode.Int64:
697                 case TypeCode.SByte:
698                 case TypeCode.Single:
699                 case TypeCode.String:
700                 case TypeCode.UInt16:
701                 case TypeCode.UInt32:
702                 case TypeCode.UInt64:
703                     return true;
704
705                 default:
706                     return type == typeof(DateTimeOffset) || type == typeof(Guid) || type == typeof(Uri) ||
707                            type == typeof(List<object>) || type == typeof(Array) || type == typeof(object[]) ||
708                            type == typeof(Dictionary<string, object>);
709             }
710         }
711
712         /// <summary>
713         /// Returns the value this object wraps (if any).
714         /// </summary>
715         /// <returns>The value wrapped by this instance or null if none.</returns>
716         internal virtual object Read()
717         {
718             return null;
719         }
720
721         /// <summary>
722         /// Serializes this object into the specified <see cref="XmlDictionaryWriter"/> instance.
723         /// </summary>
724         /// <param name="jsonWriter">An <see cref="XmlDictionaryWriter"/> instance to serialize this instance into.</param>
725         internal virtual void Save(XmlDictionaryWriter jsonWriter)
726         {
727             if (jsonWriter == null)
728             {
729                 throw new ArgumentNullException("jsonWriter");
730             }
731
732             Stack<JsonValue> objectStack = new Stack<JsonValue>();
733             Stack<int> indexStack = new Stack<int>();
734             int currentIndex = 0;
735             JsonValue currentValue = this;
736
737             OnSaveStarted();
738
739             WriteAttributeString(jsonWriter);
740
741             while (currentIndex < currentValue.Count || objectStack.Count > 0)
742             {
743                 if (currentValue.Count > currentIndex)
744                 {
745                     JsonValue nextValue = currentValue.WriteStartElementAndGetNext(jsonWriter, currentIndex);
746
747                     if (JsonValue.IsJsonCollection(nextValue))
748                     {
749                         nextValue.OnSaveStarted();
750                         nextValue.WriteAttributeString(jsonWriter);
751
752                         objectStack.Push(currentValue);
753                         indexStack.Push(currentIndex);
754                         currentValue = nextValue;
755                         currentIndex = 0;
756                     }
757                     else
758                     {
759                         if (nextValue == null)
760                         {
761                             jsonWriter.WriteAttributeString(JXmlToJsonValueConverter.TypeAttributeName, JXmlToJsonValueConverter.NullAttributeValue);
762                         }
763                         else
764                         {
765                             nextValue.Save(jsonWriter);
766                         }
767
768                         currentIndex++;
769                         jsonWriter.WriteEndElement();
770                     }
771                 }
772                 else
773                 {
774                     if (objectStack.Count > 0)
775                     {
776                         currentValue.OnSaveEnded();
777                         jsonWriter.WriteEndElement();
778
779                         currentValue = objectStack.Pop();
780                         currentIndex = indexStack.Pop() + 1;
781                     }
782                 }
783             }
784
785             OnSaveEnded();
786         }
787
788         /// <summary>
789         /// Returns an enumerator which iterates through the values in this object.
790         /// </summary>
791         /// <returns>An <see cref="System.Collections.IEnumerator"/> which iterates through the values in this object.</returns>
792         /// <remarks>This method is the virtual version of the IEnumerator.GetEnumerator method and is provided to allow derived classes to implement the 
793         /// appropriate version of the generic interface (enumerator of values or key/value pairs).</remarks>
794         [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
795             Justification = "This method is a virtual version of the IEnumerable.GetEnumerator method.")]
796         [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
797             Justification = "This class is a collection that is properly represented by the nested generic type.")]
798         protected virtual IEnumerator<KeyValuePair<string, JsonValue>> GetKeyValuePairEnumerator()
799         {
800             yield break;
801         }
802
803         /// <summary>
804         /// Callback method called during Save operations to let the instance write the start element
805         /// and return the next element in the collection.
806         /// </summary>
807         /// <param name="jsonWriter">The JXML writer used to write JSON.</param>
808         /// <param name="index">The index within this collection.</param>
809         /// <returns>The next item in the collection, or null of there are no more items.</returns>
810         internal virtual JsonValue WriteStartElementAndGetNext(XmlDictionaryWriter jsonWriter, int index)
811         {
812             return null;
813         }
814
815         /// <summary>
816         /// Callback method called to let an instance write the proper JXML attribute when saving this
817         /// instance.
818         /// </summary>
819         /// <param name="jsonWriter">The JXML writer used to write JSON.</param>
820         internal virtual void WriteAttributeString(XmlDictionaryWriter jsonWriter)
821         {
822         }
823
824         /// <summary>
825         /// Callback method called when a Save operation is starting for this instance.
826         /// </summary>
827         protected virtual void OnSaveStarted()
828         {
829         }
830
831         /// <summary>
832         /// Callback method called when a Save operation is finished for this instance.
833         /// </summary>
834         protected virtual void OnSaveEnded()
835         {
836         }
837
838         /// <summary>
839         /// Called internally to raise the <see cref="Changing"/> event.
840         /// </summary>
841         /// <param name="sender">The object which caused the event to be raised.</param>
842         /// <param name="eventArgs">The arguments to the event.</param>
843         [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate",
844             Justification = "This is a helper function used to raise the event.")]
845         [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers",
846             Justification = "This is not externally visible, since the constructor for this class is internal (cannot be directly derived) and all its subclasses are sealed.")]
847         protected void RaiseChangingEvent(object sender, JsonValueChangeEventArgs eventArgs)
848         {
849             EventHandler<JsonValueChangeEventArgs> changing = OnChanging;
850             if (changing != null)
851             {
852                 changing(sender, eventArgs);
853             }
854         }
855
856         /// <summary>
857         /// Called internally to raise the <see cref="Changed"/> event.
858         /// </summary>
859         /// <param name="sender">The object which caused the event to be raised.</param>
860         /// <param name="eventArgs">The arguments to the event.</param>
861         [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate",
862             Justification = "This is a helper function used to raise the event.")]
863         [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers",
864             Justification = "This is not externally visible, since the constructor for this class is internal (cannot be directly derived) and all its subclasses are sealed.")]
865         protected void RaiseChangedEvent(object sender, JsonValueChangeEventArgs eventArgs)
866         {
867             EventHandler<JsonValueChangeEventArgs> changed = OnChanged;
868             if (changed != null)
869             {
870                 changed(sender, eventArgs);
871             }
872         }
873
874         private static bool IsJsonCollection(JsonValue value)
875         {
876             return value != null && (value.JsonType == JsonType.Array || value.JsonType == JsonType.Object);
877         }
878
879         /// <summary>
880         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.String"/> object.
881         /// </summary>
882         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.String"/> object.</param>
883         /// <returns>The <see cref="System.String"/> initialized with the <see cref="System.Json.JsonValue"/> value specified or null if value is null.</returns>
884         public static explicit operator string(JsonValue value)
885         {
886             return CastValue<string>(value);
887         }
888
889         /// <summary>
890         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Double"/> object.
891         /// </summary>
892         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Double"/> object.</param>
893         /// <returns>The <see cref="System.Double"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
894         public static explicit operator double(JsonValue value)
895         {
896             return CastValue<double>(value);
897         }
898
899         /// <summary>
900         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Single"/> object.
901         /// </summary>
902         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Single"/> object.</param>
903         /// <returns>The <see cref="System.Single"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
904         public static explicit operator float(JsonValue value)
905         {
906             return CastValue<float>(value);
907         }
908
909         /// <summary>
910         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Decimal"/> object.
911         /// </summary>
912         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Decimal"/> object.</param>
913         /// <returns>The <see cref="System.Decimal"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
914         public static explicit operator decimal(JsonValue value)
915         {
916             return CastValue<decimal>(value);
917         }
918
919         /// <summary>
920         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Int64"/> object.
921         /// </summary>
922         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Int64"/> object.</param>
923         /// <returns>The <see cref="System.Int64"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
924         public static explicit operator long(JsonValue value)
925         {
926             return CastValue<long>(value);
927         }
928
929         /// <summary>
930         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.UInt64"/> object.
931         /// </summary>
932         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.UInt64"/> object.</param>
933         /// <returns>The <see cref="System.UInt64"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
934         [CLSCompliant(false)]
935         public static explicit operator ulong(JsonValue value)
936         {
937             return CastValue<ulong>(value);
938         }
939
940         /// <summary>
941         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Int32"/> object.
942         /// </summary>
943         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Int32"/> object.</param>
944         /// <returns>The <see cref="System.Int32"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
945         public static explicit operator int(JsonValue value)
946         {
947             return CastValue<int>(value);
948         }
949
950         /// <summary>
951         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.UInt32"/> object.
952         /// </summary>
953         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.UInt32"/> object.</param>
954         /// <returns>The <see cref="System.UInt32"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
955         [CLSCompliant(false)]
956         public static explicit operator uint(JsonValue value)
957         {
958             return CastValue<uint>(value);
959         }
960
961         /// <summary>
962         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Int16"/> object.
963         /// </summary>
964         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Int16"/> object.</param>
965         /// <returns>The <see cref="System.Int16"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
966         public static explicit operator short(JsonValue value)
967         {
968             return CastValue<short>(value);
969         }
970
971         /// <summary>
972         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.UInt16"/> object.
973         /// </summary>
974         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.UInt16"/> object.</param>
975         /// <returns>The <see cref="System.UInt16"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
976         [CLSCompliant(false)]
977         public static explicit operator ushort(JsonValue value)
978         {
979             return CastValue<ushort>(value);
980         }
981
982         /// <summary>
983         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.SByte"/> object.
984         /// </summary>
985         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.SByte"/> object.</param>
986         /// <returns>The <see cref="System.SByte"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
987         [CLSCompliant(false)]
988         public static explicit operator sbyte(JsonValue value)
989         {
990             return CastValue<sbyte>(value);
991         }
992
993         /// <summary>
994         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Byte"/> object.
995         /// </summary>
996         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Byte"/> object.</param>
997         /// <returns>The <see cref="System.Byte"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
998         public static explicit operator byte(JsonValue value)
999         {
1000             return CastValue<byte>(value);
1001         }
1002
1003         /// <summary>
1004         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Uri"/> object.
1005         /// </summary>
1006         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Uri"/> object.</param>
1007         /// <returns>The <see cref="System.Uri"/> initialized with the <see cref="System.Json.JsonValue"/> value specified or null if value is null.</returns>
1008         public static explicit operator Uri(JsonValue value)
1009         {
1010             return CastValue<Uri>(value);
1011         }
1012
1013         /// <summary>
1014         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Guid"/> object.
1015         /// </summary>
1016         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Guid"/> object.</param>
1017         /// <returns>The <see cref="System.Guid"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
1018         public static explicit operator Guid(JsonValue value)
1019         {
1020             return CastValue<Guid>(value);
1021         }
1022
1023         /// <summary>
1024         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.DateTime"/> object.
1025         /// </summary>
1026         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.DateTime"/> object.</param>
1027         /// <returns>The <see cref="System.DateTime"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
1028         public static explicit operator DateTime(JsonValue value)
1029         {
1030             return CastValue<DateTime>(value);
1031         }
1032
1033         /// <summary>
1034         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Char"/> object.
1035         /// </summary>
1036         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Char"/> object.</param>
1037         /// <returns>The <see cref="System.Char"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
1038         public static explicit operator char(JsonValue value)
1039         {
1040             return CastValue<char>(value);
1041         }
1042
1043         /// <summary>
1044         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.Boolean"/> object.
1045         /// </summary>
1046         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.Boolean"/> object.</param>
1047         /// <returns>The <see cref="System.Boolean"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
1048         public static explicit operator bool(JsonValue value)
1049         {
1050             return CastValue<bool>(value);
1051         }
1052
1053         /// <summary>
1054         /// Enables explicit casts from an instance of type <see cref="System.Json.JsonValue"/> to a <see cref="System.DateTimeOffset"/> object.
1055         /// </summary>
1056         /// <param name="value">The instance of <see cref="System.Json.JsonValue"/> used to initialize the <see cref="System.DateTimeOffset"/> object.</param>
1057         /// <returns>The <see cref="System.DateTimeOffset"/> initialized with the <see cref="System.Json.JsonValue"/> value specified.</returns>
1058         public static explicit operator DateTimeOffset(JsonValue value)
1059         {
1060             return CastValue<DateTimeOffset>(value);
1061         }
1062
1063         /// <summary>
1064         /// Enables implicit casts from type <see cref="System.Boolean"/> to a <see cref="System.Json.JsonPrimitive"/>.
1065         /// </summary>
1066         /// <param name="value">The <see cref="System.Boolean"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1067         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Boolean"/> specified.</returns>
1068         public static implicit operator JsonValue(bool value)
1069         {
1070             return new JsonPrimitive(value);
1071         }
1072
1073         /// <summary>
1074         /// Enables implicit casts from type <see cref="System.Byte"/> to a <see cref="System.Json.JsonPrimitive"/>.
1075         /// </summary>
1076         /// <param name="value">The <see cref="System.Byte"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1077         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Byte"/> specified.</returns>
1078         public static implicit operator JsonValue(byte value)
1079         {
1080             return new JsonPrimitive(value);
1081         }
1082
1083         /// <summary>
1084         /// Enables implicit casts from type <see cref="System.Decimal"/> to a <see cref="System.Json.JsonPrimitive"/>.
1085         /// </summary>
1086         /// <param name="value">The <see cref="System.Decimal"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1087         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Decimal"/> specified.</returns>
1088         public static implicit operator JsonValue(decimal value)
1089         {
1090             return new JsonPrimitive(value);
1091         }
1092
1093         /// <summary>
1094         /// Enables implicit casts from type <see cref="System.Double"/> to a <see cref="System.Json.JsonPrimitive"/>.
1095         /// </summary>
1096         /// <param name="value">The <see cref="System.Double"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1097         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Double"/> specified.</returns>
1098         public static implicit operator JsonValue(double value)
1099         {
1100             return new JsonPrimitive(value);
1101         }
1102
1103         /// <summary>
1104         /// Enables implicit casts from type <see cref="System.Int16"/> to a <see cref="System.Json.JsonPrimitive"/>.
1105         /// </summary>
1106         /// <param name="value">The <see cref="System.Int16"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1107         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Int16"/> specified.</returns>
1108         public static implicit operator JsonValue(short value)
1109         {
1110             return new JsonPrimitive(value);
1111         }
1112
1113         /// <summary>
1114         /// Enables implicit casts from type <see cref="System.Int32"/> to a <see cref="System.Json.JsonPrimitive"/>.
1115         /// </summary>
1116         /// <param name="value">The <see cref="System.Int32"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1117         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Int32"/> specified.</returns>
1118         public static implicit operator JsonValue(int value)
1119         {
1120             return new JsonPrimitive(value);
1121         }
1122
1123         /// <summary>
1124         /// Enables implicit casts from type <see cref="System.Int64"/> to a <see cref="System.Json.JsonPrimitive"/>.
1125         /// </summary>
1126         /// <param name="value">The <see cref="System.Int64"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1127         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Int64"/> specified.</returns>
1128         public static implicit operator JsonValue(long value)
1129         {
1130             return new JsonPrimitive(value);
1131         }
1132
1133         /// <summary>
1134         /// Enables implicit casts from type <see cref="System.Single"/> to a <see cref="System.Json.JsonPrimitive"/>.
1135         /// </summary>
1136         /// <param name="value">The <see cref="System.Single"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1137         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Single"/> specified.</returns>
1138         public static implicit operator JsonValue(float value)
1139         {
1140             return new JsonPrimitive(value);
1141         }
1142
1143         /// <summary>
1144         /// Enables implicit casts from type <see cref="System.String"/> to a <see cref="System.Json.JsonPrimitive"/>.
1145         /// </summary>
1146         /// <param name="value">The <see cref="System.String"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1147         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.String"/> specified, or null if the value is null.</returns>
1148         [SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads",
1149             Justification = "This operator does not intend to represent a Uri overload.")]
1150         public static implicit operator JsonValue(string value)
1151         {
1152             return value == null ? null : new JsonPrimitive(value);
1153         }
1154
1155         /// <summary>
1156         /// Enables implicit casts from type <see cref="System.Char"/> to a <see cref="System.Json.JsonPrimitive"/>.
1157         /// </summary>
1158         /// <param name="value">The <see cref="System.Char"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1159         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Char"/> specified.</returns>
1160         public static implicit operator JsonValue(char value)
1161         {
1162             return new JsonPrimitive(value);
1163         }
1164
1165         /// <summary>
1166         /// Enables implicit casts from type <see cref="System.DateTime"/> to a <see cref="System.Json.JsonPrimitive"/>.
1167         /// </summary>
1168         /// <param name="value">The <see cref="System.DateTime"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1169         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.DateTime"/> specified.</returns>
1170         public static implicit operator JsonValue(DateTime value)
1171         {
1172             return new JsonPrimitive(value);
1173         }
1174
1175         /// <summary>
1176         /// Enables implicit casts from type <see cref="System.Guid"/> to a <see cref="System.Json.JsonPrimitive"/>.
1177         /// </summary>
1178         /// <param name="value">The <see cref="System.Guid"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1179         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Guid"/> specified.</returns>
1180         public static implicit operator JsonValue(Guid value)
1181         {
1182             return new JsonPrimitive(value);
1183         }
1184
1185         /// <summary>
1186         /// Enables implicit casts from type <see cref="System.Uri"/> to a <see cref="System.Json.JsonPrimitive"/>.
1187         /// </summary>
1188         /// <param name="value">The <see cref="System.Uri"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1189         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.Uri"/> specified, or null if the value is null.</returns>
1190         public static implicit operator JsonValue(Uri value)
1191         {
1192             return value == null ? null : new JsonPrimitive(value);
1193         }
1194
1195         /// <summary>
1196         /// Enables implicit casts from type <see cref="System.SByte"/> to a <see cref="System.Json.JsonPrimitive"/>.
1197         /// </summary>
1198         /// <param name="value">The <see cref="System.SByte"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1199         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.SByte"/> specified.</returns>
1200         [CLSCompliant(false)]
1201         public static implicit operator JsonValue(sbyte value)
1202         {
1203             return new JsonPrimitive(value);
1204         }
1205
1206         /// <summary>
1207         /// Enables implicit casts from type <see cref="System.UInt16"/> to a <see cref="System.Json.JsonPrimitive"/>.
1208         /// </summary>
1209         /// <param name="value">The <see cref="System.UInt16"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1210         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.UInt16"/> specified.</returns>
1211         [CLSCompliant(false)]
1212         public static implicit operator JsonValue(ushort value)
1213         {
1214             return new JsonPrimitive(value);
1215         }
1216
1217         /// <summary>
1218         /// Enables implicit casts from type <see cref="System.UInt32"/> to a <see cref="System.Json.JsonPrimitive"/>.
1219         /// </summary>
1220         /// <param name="value">The <see cref="System.UInt32"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1221         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.UInt32"/> specified.</returns>
1222         [CLSCompliant(false)]
1223         public static implicit operator JsonValue(uint value)
1224         {
1225             return new JsonPrimitive(value);
1226         }
1227
1228         /// <summary>
1229         /// Enables implicit casts from type <see cref="System.UInt64"/> to a <see cref="System.Json.JsonPrimitive"/>.
1230         /// </summary>
1231         /// <param name="value">The <see cref="System.UInt64"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1232         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.UInt64"/> specified.</returns>
1233         [CLSCompliant(false)]
1234         public static implicit operator JsonValue(ulong value)
1235         {
1236             return new JsonPrimitive(value);
1237         }
1238
1239         /// <summary>
1240         /// Enables implicit casts from type <see cref="System.DateTimeOffset"/> to a <see cref="System.Json.JsonPrimitive"/>.
1241         /// </summary>
1242         /// <param name="value">The <see cref="System.DateTimeOffset"/> instance used to initialize the <see cref="System.Json.JsonPrimitive"/>.</param>
1243         /// <returns>The <see cref="System.Json.JsonValue"/> initialized with the <see cref="System.DateTimeOffset"/> specified.</returns>
1244         public static implicit operator JsonValue(DateTimeOffset value)
1245         {
1246             return new JsonPrimitive(value);
1247         }
1248     }
1249 }