2010-01-20 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / System.ServiceModel.Web / System.Runtime.Serialization.Json / DataContractJsonSerializer.cs
1 //
2 // DataContractJsonSerializer.cs
3 //
4 // Author:
5 //      Atsushi Enomoto  <atsushi@ximian.com>
6 //
7 // Copyright (C) 2007-2008 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.Globalization;
33 using System.IO;
34 using System.Reflection;
35 using System.Text;
36 using System.Xml;
37
38 namespace System.Runtime.Serialization.Json
39 {
40         public sealed class DataContractJsonSerializer : XmlObjectSerializer
41         {
42                 const string default_root_name = "root";
43
44                 #region lengthy constructor list
45
46                 public DataContractJsonSerializer (Type type)
47                         : this (type, Type.EmptyTypes)
48                 {
49                 }
50
51                 public DataContractJsonSerializer (Type type, IEnumerable<Type> knownTypes)
52                         : this (type, default_root_name, knownTypes)
53                 {
54                 }
55
56                 public DataContractJsonSerializer (Type type, string rootName)
57                         : this (type, rootName, Type.EmptyTypes)
58                 {
59                 }
60
61                 public DataContractJsonSerializer (Type type, XmlDictionaryString rootName)
62                         : this (type, rootName != null ? rootName.Value : default_root_name, Type.EmptyTypes)
63                 {
64                 }
65
66                 public DataContractJsonSerializer (Type type, string rootName, IEnumerable<Type> knownTypes)
67                         : this (type, rootName, knownTypes, int.MaxValue, false, false)
68                 {
69                 }
70
71                 public DataContractJsonSerializer (Type type, XmlDictionaryString rootName, IEnumerable<Type> knownTypes)
72                         : this (type, rootName != null ? rootName.Value : default_root_name, knownTypes)
73                 {
74                 }
75
76         DataContractJsonSerializer(Type type, string rootName, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool alwaysEmitTypeInformation)
77         {
78             if (type == null)
79                                 throw new ArgumentNullException ("type");
80                         if (rootName == null)
81                                 throw new ArgumentNullException ("rootName");
82                         if (maxItemsInObjectGraph < 0)
83                                 throw new ArgumentOutOfRangeException ("maxItemsInObjectGraph");
84
85                         List<Type> types = new List<Type> ();
86                         types.Add (type);
87                         if (knownTypes != null)
88                                 types.AddRange (knownTypes);
89
90                         this.type = type;
91                         known_types = new ReadOnlyCollection<Type> (types);
92                         root = rootName;
93                         max_items = maxItemsInObjectGraph;
94                         ignore_extension = ignoreExtensionDataObject;
95                         always_emit_type = alwaysEmitTypeInformation;
96                 }
97
98 #if !NET_2_1 || MONOTOUCH
99                 public DataContractJsonSerializer (Type type, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation)
100             : this (type, default_root_name, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, alwaysEmitTypeInformation)
101                 {
102         }
103
104                 public DataContractJsonSerializer (Type type, string rootName, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation)
105                         : this (type, rootName, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, alwaysEmitTypeInformation)
106                 {
107                         surrogate = dataContractSurrogate;
108                 }
109
110                 public DataContractJsonSerializer (Type type, XmlDictionaryString rootName, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation)
111                         : this (type, rootName != null ? rootName.Value : default_root_name, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, dataContractSurrogate, alwaysEmitTypeInformation)
112                 {
113                 }
114 #endif
115
116         #endregion
117
118         Type type;
119                 string root;
120                 ReadOnlyCollection<Type> known_types;
121                 int max_items;
122                 bool ignore_extension;
123                 bool always_emit_type;
124 #if !NET_2_1 || MONOTOUCH
125                 IDataContractSurrogate surrogate;
126
127                 [MonoTODO]
128                 public IDataContractSurrogate DataContractSurrogate {
129                         get { return surrogate; }
130                 }
131 #endif
132
133                 [MonoTODO]
134                 public bool IgnoreExtensionDataObject {
135                         get { return ignore_extension; }
136                 }
137
138                 [MonoTODO]
139                 public ReadOnlyCollection<Type> KnownTypes {
140                         get { return known_types; }
141                 }
142
143                 public int MaxItemsInObjectGraph {
144                         get { return max_items; }
145                 }
146
147                 public override bool IsStartObject (XmlReader reader)
148                 {
149                         if (reader == null)
150                                 throw new ArgumentNullException ("reader");
151                         reader.MoveToContent ();
152                         return reader.IsStartElement (root, String.Empty);
153                 }
154
155                 public override bool IsStartObject (XmlDictionaryReader reader)
156                 {
157                         return IsStartObject ((XmlReader) reader);
158                 }
159
160                 public override object ReadObject (Stream stream)
161                 {
162 #if NET_2_1
163                         var r = (JsonReader) JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max);
164                         r.LameSilverlightLiteralParser = true;
165                         return ReadObject(r);
166 #else
167                         return ReadObject (JsonReaderWriterFactory.CreateJsonReader (stream, new XmlDictionaryReaderQuotas ()));
168 #endif
169                 }
170
171                 public override object ReadObject (XmlDictionaryReader reader)
172                 {
173                         return ReadObject (reader, true);
174                 }
175
176                 public override object ReadObject (XmlReader reader)
177                 {
178                         return ReadObject (reader, true);
179                 }
180
181                 public override object ReadObject (XmlDictionaryReader reader, bool verifyObjectName)
182                 {
183                         return ReadObject ((XmlReader) reader, verifyObjectName);
184                 }
185
186                 public override object ReadObject (XmlReader reader, bool verifyObjectName)
187                 {
188                         if (reader == null)
189                                 throw new ArgumentNullException ("reader");
190                         try {
191                                 if (verifyObjectName && !IsStartObject (reader))
192                                         throw new SerializationException (String.Format ("Expected element was '{0}', but the actual input element was '{1}' in namespace '{2}'", root, reader.LocalName, reader.NamespaceURI));
193
194                                 return new JsonSerializationReader (this, reader, type, verifyObjectName).ReadRoot ();
195                         } catch (SerializationException) {
196                                 throw;
197                         } catch (Exception ex) {
198                                 throw new SerializationException ("Deserialization has failed", ex);
199                         }
200                 }
201
202                 public override void WriteObject (Stream stream, object graph)
203                 {
204                         using (var xw = JsonReaderWriterFactory.CreateJsonWriter (stream))
205                                 WriteObject (xw, graph);
206                 }
207
208                 public override void WriteObject (XmlWriter writer, object graph)
209                 {
210                         try {
211                                 WriteStartObject (writer, graph);
212                                 WriteObjectContent (writer, graph);
213                                 WriteEndObject (writer);
214                         } catch (NotImplementedException) {
215                                 throw;
216                         } catch (InvalidDataContractException) {
217                                 throw;
218                         } catch (Exception ex) {
219                                 throw new SerializationException (String.Format ("There was an error during serialization for object of type {0}", graph != null ? graph.GetType () : null), ex);
220                         }
221                 }
222
223                 public override void WriteObject (XmlDictionaryWriter writer, object graph)
224                 {
225                         WriteObject ((XmlWriter) writer, graph);
226                 }
227
228                 public override void WriteStartObject (XmlDictionaryWriter writer, object graph)
229                 {
230                         WriteStartObject ((XmlWriter) writer, graph);
231                 }
232
233                 public override void WriteStartObject (XmlWriter writer, object graph)
234                 {
235                         if (writer == null)
236                                 throw new ArgumentNullException ("writer");
237                         writer.WriteStartElement (root);
238                 }
239
240                 public override void WriteObjectContent (XmlDictionaryWriter writer, object graph)
241                 {
242                         WriteObjectContent ((XmlWriter) writer, graph);
243                 }
244
245                 public override void WriteObjectContent (XmlWriter writer, object graph)
246                 {
247                         new JsonSerializationWriter (this, writer, type, always_emit_type).WriteObjectContent (graph, true, false);
248                 }
249
250                 public override void WriteEndObject (XmlDictionaryWriter writer)
251                 {
252                         WriteEndObject ((XmlWriter) writer);
253                 }
254
255                 public override void WriteEndObject (XmlWriter writer)
256                 {
257                         if (writer == null)
258                                 throw new ArgumentNullException ("writer");
259                         writer.WriteEndElement ();
260                 }
261         }
262 }