Merge pull request #995 from yjoly/master
[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.Linq;
35 using System.Reflection;
36 using System.Text;
37 using System.Xml;
38
39 namespace System.Runtime.Serialization.Json
40 {
41         public sealed class DataContractJsonSerializer : XmlObjectSerializer
42         {
43                 const string default_root_name = "root";
44
45                 #region lengthy constructor list
46
47                 public DataContractJsonSerializer (Type type)
48                         : this (type, Type.EmptyTypes)
49                 {
50                 }
51
52                 public DataContractJsonSerializer (Type type, IEnumerable<Type> knownTypes)
53                         : this (type, default_root_name, knownTypes)
54                 {
55                 }
56
57                 public DataContractJsonSerializer (Type type, string rootName)
58                         : this (type, rootName, Type.EmptyTypes)
59                 {
60                 }
61
62                 public DataContractJsonSerializer (Type type, XmlDictionaryString rootName)
63                         : this (type, rootName != null ? rootName.Value : default_root_name, Type.EmptyTypes)
64                 {
65                 }
66
67                 public DataContractJsonSerializer (Type type, string rootName, IEnumerable<Type> knownTypes)
68                         : this (type, rootName, knownTypes, int.MaxValue, false, false)
69                 {
70                 }
71
72                 public DataContractJsonSerializer (Type type, XmlDictionaryString rootName, IEnumerable<Type> knownTypes)
73                         : this (type, rootName != null ? rootName.Value : default_root_name, knownTypes)
74                 {
75                 }
76
77                 DataContractJsonSerializer(Type type, string rootName, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool alwaysEmitTypeInformation)
78                 {
79                         if (type == null)
80                                 throw new ArgumentNullException ("type");
81                         if (rootName == null)
82                                 throw new ArgumentNullException ("rootName");
83                         if (maxItemsInObjectGraph < 0)
84                                 throw new ArgumentOutOfRangeException ("maxItemsInObjectGraph");
85
86                         this.type = type;
87                         known_types = new ReadOnlyCollection<Type> (knownTypes != null ? knownTypes.ToArray () : Type.EmptyTypes);
88                         root = rootName;
89                         max_items = maxItemsInObjectGraph;
90                         ignore_extension = ignoreExtensionDataObject;
91                         always_emit_type = alwaysEmitTypeInformation;
92                 }
93
94                 public DataContractJsonSerializer (Type type, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation)
95             : this (type, default_root_name, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, alwaysEmitTypeInformation)
96                 {
97         }
98
99                 public DataContractJsonSerializer (Type type, string rootName, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation)
100                         : this (type, rootName, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, alwaysEmitTypeInformation)
101                 {
102                         surrogate = dataContractSurrogate;
103                 }
104
105                 public DataContractJsonSerializer (Type type, XmlDictionaryString rootName, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation)
106                         : this (type, rootName != null ? rootName.Value : default_root_name, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, dataContractSurrogate, alwaysEmitTypeInformation)
107                 {
108                 }
109
110 #if NET_4_5
111                 public DataContractJsonSerializer (Type type, DataContractJsonSerializerSettings settings)
112                         : this (type, settings.RootName, settings.KnownTypes, settings.MaxItemsInObjectGraph, settings.IgnoreExtensionDataObject,
113                                 settings.DataContractSurrogate, false)
114                 {
115                 }
116 #endif
117
118         #endregion
119
120         Type type;
121                 string root;
122                 ReadOnlyCollection<Type> known_types;
123                 int max_items;
124                 bool ignore_extension;
125                 bool always_emit_type;
126                 IDataContractSurrogate surrogate;
127
128                 [MonoTODO]
129                 public IDataContractSurrogate DataContractSurrogate {
130                         get { return surrogate; }
131                 }
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 (InvalidDataContractException) {
198                                 throw;
199                         } catch (System.Reflection.TargetInvocationException ex) {
200                                 throw ex.InnerException;
201                         } catch (Exception ex) {
202                                 throw new SerializationException ("Deserialization has failed", ex);
203                         }
204                 }
205
206                 public override void WriteObject (Stream stream, object graph)
207                 {
208                         using (var xw = JsonReaderWriterFactory.CreateJsonWriter (stream))
209                                 WriteObject (xw, graph);
210                 }
211
212                 public override void WriteObject (XmlWriter writer, object graph)
213                 {
214                         try {
215                                 WriteStartObject (writer, graph);
216                                 WriteObjectContent (writer, graph);
217                                 WriteEndObject (writer);
218                         } catch (NotImplementedException) {
219                                 throw;
220                         } catch (InvalidDataContractException) {
221                                 throw;
222                         } catch (Exception ex) {
223                                 throw new SerializationException (String.Format ("There was an error during serialization for object of type {0}", graph != null ? graph.GetType () : null), ex);
224                         }
225                 }
226
227                 public override void WriteObject (XmlDictionaryWriter writer, object graph)
228                 {
229                         WriteObject ((XmlWriter) writer, graph);
230                 }
231
232                 public override void WriteStartObject (XmlDictionaryWriter writer, object graph)
233                 {
234                         WriteStartObject ((XmlWriter) writer, graph);
235                 }
236
237                 public override void WriteStartObject (XmlWriter writer, object graph)
238                 {
239                         if (writer == null)
240                                 throw new ArgumentNullException ("writer");
241                         writer.WriteStartElement (root);
242                 }
243
244                 public override void WriteObjectContent (XmlDictionaryWriter writer, object graph)
245                 {
246                         WriteObjectContent ((XmlWriter) writer, graph);
247                 }
248
249                 public override void WriteObjectContent (XmlWriter writer, object graph)
250                 {
251                         new JsonSerializationWriter (this, writer, type, always_emit_type).WriteObjectContent (graph, true, false);
252                 }
253
254                 public override void WriteEndObject (XmlDictionaryWriter writer)
255                 {
256                         WriteEndObject ((XmlWriter) writer);
257                 }
258
259                 public override void WriteEndObject (XmlWriter writer)
260                 {
261                         if (writer == null)
262                                 throw new ArgumentNullException ("writer");
263                         writer.WriteEndElement ();
264                 }
265
266 #if NET_4_5
267                 [MonoTODO]
268                 public DateTimeFormat DateTimeFormat {
269                         get { throw new NotImplementedException (); }
270                 }
271
272                 [MonoTODO]
273                 public EmitTypeInformation EmitTypeInformation {
274                         get { throw new NotImplementedException (); }
275                 }
276
277                 [MonoTODO]
278                 public bool SerializeReadOnlyTypes {
279                         get { throw new NotImplementedException (); }
280                 }
281
282                 [MonoTODO]
283                 public bool UseSimpleDictionaryFormat {
284                         get { throw new NotImplementedException (); }
285                 }
286 #endif
287
288         }
289 }