2010-03-12 Jb Evain <jbevain@novell.com>
[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 JavaScriptObjectDeserializer.BufferedStreamReader (stream));
21                 }
22
23                 public static JsonValue Load (TextReader textReader)
24                 {
25                         if (textReader == null)
26                                 throw new ArgumentNullException ("textReader");
27
28                         var ret = new JavaScriptObjectDeserializer (textReader.ReadToEnd (), true).BasicDeserialize ();
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                                         pair.Value.SaveInternal (w);
152                                         following = true;
153                                 }
154                                 w.Write ('}');
155                                 break;
156                         case JsonType.Array:
157                                 w.Write ('[');
158                                 following = false;
159                                 foreach (JsonValue v in ((JsonArray) this)) {
160                                         if (following)
161                                                 w.Write (", ");
162                                         v.SaveInternal (w);
163                                         following = true;
164                                 }
165                                 w.Write (']');
166                                 break;
167                         case JsonType.Boolean:
168                                 w.Write ((bool) this ? "true" : "false");
169                                 break;
170                         case JsonType.String:
171                                 w.Write ('"');
172                                 w.Write (EscapeString (((JsonPrimitive) this).GetFormattedString ()));
173                                 w.Write ('"');
174                                 break;
175                         default:
176                                 w.Write (((JsonPrimitive) this).GetFormattedString ());
177                                 break;
178                         }
179                 }
180
181                 public override string ToString ()
182                 {
183                         StringWriter sw = new StringWriter ();
184                         Save (sw);
185                         return sw.ToString ();
186                 }
187
188                 IEnumerator IEnumerable.GetEnumerator ()
189                 {
190                         throw new InvalidOperationException ();
191                 }
192
193                 internal string EscapeString (string src)
194                 {
195                         if (src == null)
196                                 return null;
197
198                         for (int i = 0; i < src.Length; i++)
199                                 if (src [i] == '"' || src [i] == '\\') {
200                                         var sb = new StringBuilder ();
201                                         if (i > 0)
202                                                 sb.Append (src, 0, i);
203                                         return DoEscapeString (sb, src, i);
204                                 }
205                         return src;
206                 }
207
208                 string DoEscapeString (StringBuilder sb, string src, int cur)
209                 {
210                         int start = cur;
211                         for (int i = cur; i < src.Length; i++)
212                                 if (src [i] == '"' || src [i] == '\\') {
213                                         sb.Append (src, start, i - start);
214                                         sb.Append ('\\');
215                                         sb.Append (src [i++]);
216                                         start = i;
217                                 }
218                         sb.Append (src, start, src.Length - start);
219                         return sb.ToString ();
220                 }
221
222                 // CLI -> JsonValue
223
224                 public static implicit operator JsonValue (bool value)
225                 {
226                         return new JsonPrimitive (value);
227                 }
228
229                 public static implicit operator JsonValue (byte value)
230                 {
231                         return new JsonPrimitive (value);
232                 }
233
234                 public static implicit operator JsonValue (char value)
235                 {
236                         return new JsonPrimitive (value);
237                 }
238
239                 public static implicit operator JsonValue (decimal value)
240                 {
241                         return new JsonPrimitive (value);
242                 }
243
244                 public static implicit operator JsonValue (double value)
245                 {
246                         return new JsonPrimitive (value);
247                 }
248
249                 public static implicit operator JsonValue (float value)
250                 {
251                         return new JsonPrimitive (value);
252                 }
253
254                 public static implicit operator JsonValue (int value)
255                 {
256                         return new JsonPrimitive (value);
257                 }
258
259                 public static implicit operator JsonValue (long value)
260                 {
261                         return new JsonPrimitive (value);
262                 }
263
264                 public static implicit operator JsonValue (sbyte value)
265                 {
266                         return new JsonPrimitive (value);
267                 }
268
269                 public static implicit operator JsonValue (short value)
270                 {
271                         return new JsonPrimitive (value);
272                 }
273
274                 public static implicit operator JsonValue (string value)
275                 {
276                         return new JsonPrimitive (value);
277                 }
278
279                 public static implicit operator JsonValue (uint value)
280                 {
281                         return new JsonPrimitive (value);
282                 }
283
284                 public static implicit operator JsonValue (ulong value)
285                 {
286                         return new JsonPrimitive (value);
287                 }
288
289                 public static implicit operator JsonValue (ushort value)
290                 {
291                         return new JsonPrimitive (value);
292                 }
293
294                 public static implicit operator JsonValue (DateTime value)
295                 {
296                         return new JsonPrimitive (value);
297                 }
298
299                 public static implicit operator JsonValue (DateTimeOffset value)
300                 {
301                         return new JsonPrimitive (value);
302                 }
303
304                 public static implicit operator JsonValue (Guid value)
305                 {
306                         return new JsonPrimitive (value);
307                 }
308
309                 public static implicit operator JsonValue (TimeSpan value)
310                 {
311                         return new JsonPrimitive (value);
312                 }
313
314                 public static implicit operator JsonValue (Uri value)
315                 {
316                         return new JsonPrimitive (value);
317                 }
318
319                 // JsonValue -> CLI
320
321                 public static implicit operator bool (JsonValue value)
322                 {
323                         if (value == null)
324                                 throw new ArgumentNullException ("value");
325                         return (bool) ((JsonPrimitive) value).Value;
326                 }
327
328                 public static implicit operator byte (JsonValue value)
329                 {
330                         if (value == null)
331                                 throw new ArgumentNullException ("value");
332                         return (byte) ((JsonPrimitive) value).Value;
333                 }
334
335                 public static implicit operator char (JsonValue value)
336                 {
337                         if (value == null)
338                                 throw new ArgumentNullException ("value");
339                         return (char) ((JsonPrimitive) value).Value;
340                 }
341
342                 public static implicit operator decimal (JsonValue value)
343                 {
344                         if (value == null)
345                                 throw new ArgumentNullException ("value");
346                         return (decimal) ((JsonPrimitive) value).Value;
347                 }
348
349                 public static implicit operator double (JsonValue value)
350                 {
351                         if (value == null)
352                                 throw new ArgumentNullException ("value");
353                         return (double) ((JsonPrimitive) value).Value;
354                 }
355
356                 public static implicit operator float (JsonValue value)
357                 {
358                         if (value == null)
359                                 throw new ArgumentNullException ("value");
360                         return (float) ((JsonPrimitive) value).Value;
361                 }
362
363                 public static implicit operator int (JsonValue value)
364                 {
365                         if (value == null)
366                                 throw new ArgumentNullException ("value");
367                         return (int) ((JsonPrimitive) value).Value;
368                 }
369
370                 public static implicit operator long (JsonValue value)
371                 {
372                         if (value == null)
373                                 throw new ArgumentNullException ("value");
374                         return (long) ((JsonPrimitive) value).Value;
375                 }
376
377                 public static implicit operator sbyte (JsonValue value)
378                 {
379                         if (value == null)
380                                 throw new ArgumentNullException ("value");
381                         return (sbyte) ((JsonPrimitive) value).Value;
382                 }
383
384                 public static implicit operator short (JsonValue value)
385                 {
386                         if (value == null)
387                                 throw new ArgumentNullException ("value");
388                         return (short) ((JsonPrimitive) value).Value;
389                 }
390
391                 public static implicit operator string (JsonValue value)
392                 {
393                         if (value == null)
394                                 return null;
395                         return (string) ((JsonPrimitive) value).Value;
396                 }
397
398                 public static implicit operator uint (JsonValue value)
399                 {
400                         if (value == null)
401                                 throw new ArgumentNullException ("value");
402                         return (uint) ((JsonPrimitive) value).Value;
403                 }
404
405                 public static implicit operator ulong (JsonValue value)
406                 {
407                         if (value == null)
408                                 throw new ArgumentNullException ("value");
409                         return (ulong) ((JsonPrimitive) value).Value;
410                 }
411
412                 public static implicit operator ushort (JsonValue value)
413                 {
414                         if (value == null)
415                                 throw new ArgumentNullException ("value");
416                         return (ushort) ((JsonPrimitive) value).Value;
417                 }
418
419                 public static implicit operator DateTime (JsonValue value)
420                 {
421                         if (value == null)
422                                 throw new ArgumentNullException ("value");
423                         return (DateTime) ((JsonPrimitive) value).Value;
424                 }
425
426                 public static implicit operator DateTimeOffset (JsonValue value)
427                 {
428                         if (value == null)
429                                 throw new ArgumentNullException ("value");
430                         return (DateTimeOffset) ((JsonPrimitive) value).Value;
431                 }
432
433                 public static implicit operator TimeSpan (JsonValue value)
434                 {
435                         if (value == null)
436                                 throw new ArgumentNullException ("value");
437                         return (TimeSpan) ((JsonPrimitive) value).Value;
438                 }
439
440                 public static implicit operator Guid (JsonValue value)
441                 {
442                         if (value == null)
443                                 throw new ArgumentNullException ("value");
444                         return (Guid) ((JsonPrimitive) value).Value;
445                 }
446
447                 public static implicit operator Uri (JsonValue value)
448                 {
449                         if (value == null)
450                                 throw new ArgumentNullException ("value");
451                         return (Uri) ((JsonPrimitive) value).Value;
452                 }
453         }
454 }