d703edd5512c5c6427f43f78a2975f8600f5edd5
[mono.git] / mcs / class / System.Json / System.Json / JsonValue.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.IO;
6 using System.Linq;
7 using System.Runtime.Serialization.Json;
8 using System.Text;
9
10 using JsonPair = System.Collections.Generic.KeyValuePair<string, System.Json.JsonValue>;
11
12
13 namespace System.Json
14 {
15         public abstract class JsonValue : IEnumerable
16         {
17                 public static JsonValue Load (Stream stream)
18                 {
19                         if (stream == null)
20                                 throw new ArgumentNullException ("stream");
21                         return Load (new StreamReader (stream, true));
22                 }
23
24                 public static JsonValue Load (TextReader textReader)
25                 {
26                         if (textReader == null)
27                                 throw new ArgumentNullException ("textReader");
28
29                         var ret = new JavaScriptReader (textReader, true).Read ();
30
31                         return ToJsonValue (ret);
32                 }
33
34                 static IEnumerable<KeyValuePair<string,JsonValue>> ToJsonPairEnumerable (IEnumerable<KeyValuePair<string,object>> kvpc)
35                 {
36                         foreach (var kvp in kvpc)
37                                 yield return new KeyValuePair<string,JsonValue> (kvp.Key, ToJsonValue (kvp.Value));
38                 }
39
40                 static IEnumerable<JsonValue> ToJsonValueEnumerable (IEnumerable<object> arr)
41                 {
42                         foreach (var obj in arr)
43                                 yield return ToJsonValue (obj);
44                 }
45
46                 static JsonValue ToJsonValue (object ret)
47                 {
48                         if (ret == null)
49                                 return null;
50                         var kvpc = ret as IEnumerable<KeyValuePair<string,object>>;
51                         if (kvpc != null)
52                                 return new JsonObject (ToJsonPairEnumerable (kvpc));
53                         var arr = ret as IEnumerable<object>;
54                         if (arr != null)
55                                 return new JsonArray (ToJsonValueEnumerable (arr));
56
57                         if (ret is bool)
58                                 return new JsonPrimitive ((bool) ret);
59                         if (ret is byte)
60                                 return new JsonPrimitive ((byte) ret);
61                         if (ret is char)
62                                 return new JsonPrimitive ((char) ret);
63                         if (ret is decimal)
64                                 return new JsonPrimitive ((decimal) ret);
65                         if (ret is double)
66                                 return new JsonPrimitive ((double) ret);
67                         if (ret is float)
68                                 return new JsonPrimitive ((float) ret);
69                         if (ret is int)
70                                 return new JsonPrimitive ((int) ret);
71                         if (ret is long)
72                                 return new JsonPrimitive ((long) ret);
73                         if (ret is sbyte)
74                                 return new JsonPrimitive ((sbyte) ret);
75                         if (ret is short)
76                                 return new JsonPrimitive ((short) ret);
77                         if (ret is string)
78                                 return new JsonPrimitive ((string) ret);
79                         if (ret is uint)
80                                 return new JsonPrimitive ((uint) ret);
81                         if (ret is ulong)
82                                 return new JsonPrimitive ((ulong) ret);
83                         if (ret is ushort)
84                                 return new JsonPrimitive ((ushort) ret);
85                         if (ret is DateTime)
86                                 return new JsonPrimitive ((DateTime) ret);
87                         if (ret is DateTimeOffset)
88                                 return new JsonPrimitive ((DateTimeOffset) ret);
89                         if (ret is Guid)
90                                 return new JsonPrimitive ((Guid) ret);
91                         if (ret is TimeSpan)
92                                 return new JsonPrimitive ((TimeSpan) ret);
93                         if (ret is Uri)
94                                 return new JsonPrimitive ((Uri) ret);
95                         throw new NotSupportedException (String.Format ("Unexpected parser return type: {0}", ret.GetType ()));
96                 }
97
98                 public static JsonValue Parse (string jsonString)
99                 {
100                         if (jsonString == null)
101                                 throw new ArgumentNullException ("jsonString");
102                         return Load (new StringReader (jsonString));
103                 }
104
105                 public virtual int Count {
106                         get { throw new InvalidOperationException (); }
107                 }
108
109                 public abstract JsonType JsonType { get; }
110
111                 public virtual JsonValue this [int index] {
112                         get { throw new InvalidOperationException (); }
113                         set { throw new InvalidOperationException (); }
114                 }
115
116                 public virtual JsonValue this [string key] {
117                         get { throw new InvalidOperationException (); }
118                         set { throw new InvalidOperationException (); }
119                 }
120
121                 public virtual bool ContainsKey (string key)
122                 {
123                         throw new InvalidOperationException ();
124                 }
125
126                 public virtual void Save (Stream stream)
127                 {
128                         if (stream == null)
129                                 throw new ArgumentNullException ("stream");
130                         Save (new StreamWriter (stream));
131                 }
132
133                 public virtual void Save (TextWriter textWriter)
134                 {
135                         if (textWriter == null)
136                                 throw new ArgumentNullException ("textWriter");
137                         SaveInternal (textWriter);
138                 }
139                 
140                 void SaveInternal (TextWriter w)
141                 {
142                         switch (JsonType) {
143                         case JsonType.Object:
144                                 w.Write ('{');
145                                 bool following = false;
146                                 foreach (JsonPair pair in ((JsonObject) this)) {
147                                         if (following)
148                                                 w.Write (", ");
149                                         w.Write ('\"');
150                                         w.Write (EscapeString (pair.Key));
151                                         w.Write ("\": ");
152                                         if (pair.Value == null)
153                                                 w.Write ("null");
154                                         else
155                                                 pair.Value.SaveInternal (w);
156                                         following = true;
157                                 }
158                                 w.Write ('}');
159                                 break;
160                         case JsonType.Array:
161                                 w.Write ('[');
162                                 following = false;
163                                 foreach (JsonValue v in ((JsonArray) this)) {
164                                         if (following)
165                                                 w.Write (", ");
166                                         if (v != null) 
167                                                 v.SaveInternal (w);
168                                         else
169                                                 w.Write ("null");
170                                         following = true;
171                                 }
172                                 w.Write (']');
173                                 break;
174                         case JsonType.Boolean:
175                                 w.Write ((bool) this ? "true" : "false");
176                                 break;
177                         case JsonType.String:
178                                 w.Write ('"');
179                                 w.Write (EscapeString (((JsonPrimitive) this).GetFormattedString ()));
180                                 w.Write ('"');
181                                 break;
182                         default:
183                                 w.Write (((JsonPrimitive) this).GetFormattedString ());
184                                 break;
185                         }
186                 }
187
188                 public override string ToString ()
189                 {
190                         StringWriter sw = new StringWriter ();
191                         Save (sw);
192                         return sw.ToString ();
193                 }
194
195                 IEnumerator IEnumerable.GetEnumerator ()
196                 {
197                         throw new InvalidOperationException ();
198                 }
199
200                 internal string EscapeString (string src)
201                 {
202                         if (src == null)
203                                 return null;
204
205                         for (int i = 0; i < src.Length; i++)
206                                 if (src [i] == '"' || src [i] == '\\') {
207                                         var sb = new StringBuilder ();
208                                         if (i > 0)
209                                                 sb.Append (src, 0, i);
210                                         return DoEscapeString (sb, src, i);
211                                 }
212                         return src;
213                 }
214
215                 string DoEscapeString (StringBuilder sb, string src, int cur)
216                 {
217                         int start = cur;
218                         for (int i = cur; i < src.Length; i++)
219                                 if (src [i] == '"' || src [i] == '\\') {
220                                         sb.Append (src, start, i - start);
221                                         sb.Append ('\\');
222                                         sb.Append (src [i]);
223                                         start = i + 1;
224                                 }
225                         sb.Append (src, start, src.Length - start);
226                         return sb.ToString ();
227                 }
228
229                 // CLI -> JsonValue
230
231                 public static implicit operator JsonValue (bool value)
232                 {
233                         return new JsonPrimitive (value);
234                 }
235
236                 public static implicit operator JsonValue (byte value)
237                 {
238                         return new JsonPrimitive (value);
239                 }
240
241                 public static implicit operator JsonValue (char value)
242                 {
243                         return new JsonPrimitive (value);
244                 }
245
246                 public static implicit operator JsonValue (decimal value)
247                 {
248                         return new JsonPrimitive (value);
249                 }
250
251                 public static implicit operator JsonValue (double value)
252                 {
253                         return new JsonPrimitive (value);
254                 }
255
256                 public static implicit operator JsonValue (float value)
257                 {
258                         return new JsonPrimitive (value);
259                 }
260
261                 public static implicit operator JsonValue (int value)
262                 {
263                         return new JsonPrimitive (value);
264                 }
265
266                 public static implicit operator JsonValue (long value)
267                 {
268                         return new JsonPrimitive (value);
269                 }
270
271                 public static implicit operator JsonValue (sbyte value)
272                 {
273                         return new JsonPrimitive (value);
274                 }
275
276                 public static implicit operator JsonValue (short value)
277                 {
278                         return new JsonPrimitive (value);
279                 }
280
281                 public static implicit operator JsonValue (string value)
282                 {
283                         return new JsonPrimitive (value);
284                 }
285
286                 public static implicit operator JsonValue (uint value)
287                 {
288                         return new JsonPrimitive (value);
289                 }
290
291                 public static implicit operator JsonValue (ulong value)
292                 {
293                         return new JsonPrimitive (value);
294                 }
295
296                 public static implicit operator JsonValue (ushort value)
297                 {
298                         return new JsonPrimitive (value);
299                 }
300
301                 public static implicit operator JsonValue (DateTime value)
302                 {
303                         return new JsonPrimitive (value);
304                 }
305
306                 public static implicit operator JsonValue (DateTimeOffset value)
307                 {
308                         return new JsonPrimitive (value);
309                 }
310
311                 public static implicit operator JsonValue (Guid value)
312                 {
313                         return new JsonPrimitive (value);
314                 }
315
316                 public static implicit operator JsonValue (TimeSpan value)
317                 {
318                         return new JsonPrimitive (value);
319                 }
320
321                 public static implicit operator JsonValue (Uri value)
322                 {
323                         return new JsonPrimitive (value);
324                 }
325
326                 // JsonValue -> CLI
327
328                 public static implicit operator bool (JsonValue value)
329                 {
330                         if (value == null)
331                                 throw new ArgumentNullException ("value");
332                         return Convert.ToBoolean (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
333                 }
334
335                 public static implicit operator byte (JsonValue value)
336                 {
337                         if (value == null)
338                                 throw new ArgumentNullException ("value");
339                         return Convert.ToByte (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
340                 }
341
342                 public static implicit operator char (JsonValue value)
343                 {
344                         if (value == null)
345                                 throw new ArgumentNullException ("value");
346                         return Convert.ToChar (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
347                 }
348
349                 public static implicit operator decimal (JsonValue value)
350                 {
351                         if (value == null)
352                                 throw new ArgumentNullException ("value");
353                         return Convert.ToDecimal (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
354                 }
355
356                 public static implicit operator double (JsonValue value)
357                 {
358                         if (value == null)
359                                 throw new ArgumentNullException ("value");
360                         return Convert.ToDouble (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
361                 }
362
363                 public static implicit operator float (JsonValue value)
364                 {
365                         if (value == null)
366                                 throw new ArgumentNullException ("value");
367                         return Convert.ToSingle (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
368                 }
369
370                 public static implicit operator int (JsonValue value)
371                 {
372                         if (value == null)
373                                 throw new ArgumentNullException ("value");
374                         return Convert.ToInt32 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
375                 }
376
377                 public static implicit operator long (JsonValue value)
378                 {
379                         if (value == null)
380                                 throw new ArgumentNullException ("value");
381                         return Convert.ToInt64 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
382                 }
383
384                 public static implicit operator sbyte (JsonValue value)
385                 {
386                         if (value == null)
387                                 throw new ArgumentNullException ("value");
388                         return Convert.ToSByte (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
389                 }
390
391                 public static implicit operator short (JsonValue value)
392                 {
393                         if (value == null)
394                                 throw new ArgumentNullException ("value");
395                         return Convert.ToInt16 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
396                 }
397
398                 public static implicit operator string (JsonValue value)
399                 {
400                         if (value == null)
401                                 return null;
402                         return (string) ((JsonPrimitive) value).Value;
403                 }
404
405                 public static implicit operator uint (JsonValue value)
406                 {
407                         if (value == null)
408                                 throw new ArgumentNullException ("value");
409                         return Convert.ToUInt16 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
410                 }
411
412                 public static implicit operator ulong (JsonValue value)
413                 {
414                         if (value == null)
415                                 throw new ArgumentNullException ("value");
416                         return Convert.ToUInt64(((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
417                 }
418
419                 public static implicit operator ushort (JsonValue value)
420                 {
421                         if (value == null)
422                                 throw new ArgumentNullException ("value");
423                         return Convert.ToUInt16 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
424                 }
425
426                 public static implicit operator DateTime (JsonValue value)
427                 {
428                         if (value == null)
429                                 throw new ArgumentNullException ("value");
430                         return (DateTime) ((JsonPrimitive) value).Value;
431                 }
432
433                 public static implicit operator DateTimeOffset (JsonValue value)
434                 {
435                         if (value == null)
436                                 throw new ArgumentNullException ("value");
437                         return (DateTimeOffset) ((JsonPrimitive) value).Value;
438                 }
439
440                 public static implicit operator TimeSpan (JsonValue value)
441                 {
442                         if (value == null)
443                                 throw new ArgumentNullException ("value");
444                         return (TimeSpan) ((JsonPrimitive) value).Value;
445                 }
446
447                 public static implicit operator Guid (JsonValue value)
448                 {
449                         if (value == null)
450                                 throw new ArgumentNullException ("value");
451                         return (Guid) ((JsonPrimitive) value).Value;
452                 }
453
454                 public static implicit operator Uri (JsonValue value)
455                 {
456                         if (value == null)
457                                 throw new ArgumentNullException ("value");
458                         return (Uri) ((JsonPrimitive) value).Value;
459                 }
460         }
461 }