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