1 #region License
2 // Copyright (c) 2007 James Newton-King
3 //
4 // Permission is hereby granted, free of charge, to any person
5 // obtaining a copy of this software and associated documentation
6 // files (the "Software"), to deal in the Software without
7 // restriction, including without limitation the rights to use,
8 // copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following
11 // conditions:
12 //
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 // OTHER DEALINGS IN THE SOFTWARE.
24 #endregion
25 
26 using System;
27 using System.Reflection;
28 using System.Runtime.Serialization;
29 using Newtonsoft.Json.Utilities;
30 #if NETFX_CORE
31 using IConvertible = Newtonsoft.Json.Utilities.Convertible;
32 #endif
33 
34 namespace Newtonsoft.Json.Serialization
35 {
36   internal enum JsonContractType
37   {
38     None,
39     Object,
40     Array,
41     Primitive,
42     String,
43     Dictionary,
44 #if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
45     Dynamic,
46 #endif
47 #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
48     Serializable,
49 #endif
50     Linq
51   }
52 
53   /// <summary>
54   /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
55   /// </summary>
56   public abstract class JsonContract
57   {
58     internal bool IsNullable;
59     internal bool IsConvertable;
60     internal Type NonNullableUnderlyingType;
61     internal ReadType InternalReadType;
62     internal JsonContractType ContractType;
63 
64     /// <summary>
65     /// Gets the underlying type for the contract.
66     /// </summary>
67     /// <value>The underlying type for the contract.</value>
68     public Type UnderlyingType { get; private set; }
69 
70     /// <summary>
71     /// Gets or sets the type created during deserialization.
72     /// </summary>
73     /// <value>The type created during deserialization.</value>
74     public Type CreatedType { get; set; }
75 
76     /// <summary>
77     /// Gets or sets whether this type contract is serialized as a reference.
78     /// </summary>
79     /// <value>Whether this type contract is serialized as a reference.</value>
80     public bool? IsReference { get; set; }
81 
82     /// <summary>
83     /// Gets or sets the default <see cref="JsonConverter" /> for this contract.
84     /// </summary>
85     /// <value>The converter.</value>
86     public JsonConverter Converter { get; set; }
87 
88     // internally specified JsonConverter's to override default behavour
89     // checked for after passed in converters and attribute specified converters
90     internal JsonConverter InternalConverter { get; set; }
91 
92 #if !PocketPC
93     /// <summary>
94     /// Gets or sets the method called immediately after deserialization of the object.
95     /// </summary>
96     /// <value>The method called immediately after deserialization of the object.</value>
97     public MethodInfo OnDeserialized { get; set; }
98 
99     /// <summary>
100     /// Gets or sets the method called during deserialization of the object.
101     /// </summary>
102     /// <value>The method called during deserialization of the object.</value>
103     public MethodInfo OnDeserializing { get; set; }
104 
105     /// <summary>
106     /// Gets or sets the method called after serialization of the object graph.
107     /// </summary>
108     /// <value>The method called after serialization of the object graph.</value>
109     public MethodInfo OnSerialized { get; set; }
110 
111     /// <summary>
112     /// Gets or sets the method called before serialization of the object.
113     /// </summary>
114     /// <value>The method called before serialization of the object.</value>
115     public MethodInfo OnSerializing { get; set; }
116 #endif
117 
118     /// <summary>
119     /// Gets or sets the default creator method used to create the object.
120     /// </summary>
121     /// <value>The default creator method used to create the object.</value>
122     public Func<object> DefaultCreator { get; set; }
123 
124     /// <summary>
125     /// Gets or sets a value indicating whether the default creator is non public.
126     /// </summary>
127     /// <value><c>true</c> if the default object creator is non-public; otherwise, <c>false</c>.</value>
128     public bool DefaultCreatorNonPublic { get; set; }
129 
130     /// <summary>
131     /// Gets or sets the method called when an error is thrown during the serialization of the object.
132     /// </summary>
133     /// <value>The method called when an error is thrown during the serialization of the object.</value>
134     public MethodInfo OnError { get; set; }
135 
InvokeOnSerializing(object o, StreamingContext context)136     internal void InvokeOnSerializing(object o, StreamingContext context)
137     {
138 #if !PocketPC
139       if (OnSerializing != null)
140         OnSerializing.Invoke(o, new object[] {context});
141 #endif
142     }
143 
InvokeOnSerialized(object o, StreamingContext context)144     internal void InvokeOnSerialized(object o, StreamingContext context)
145     {
146 #if !PocketPC
147       if (OnSerialized != null)
148         OnSerialized.Invoke(o, new object[] {context});
149 #endif
150     }
151 
InvokeOnDeserializing(object o, StreamingContext context)152     internal void InvokeOnDeserializing(object o, StreamingContext context)
153     {
154 #if !PocketPC
155       if (OnDeserializing != null)
156         OnDeserializing.Invoke(o, new object[] {context});
157 #endif
158     }
159 
InvokeOnDeserialized(object o, StreamingContext context)160     internal void InvokeOnDeserialized(object o, StreamingContext context)
161     {
162 #if !PocketPC
163       if (OnDeserialized != null)
164         OnDeserialized.Invoke(o, new object[] {context});
165 #endif
166     }
167 
InvokeOnError(object o, StreamingContext context, ErrorContext errorContext)168     internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext)
169     {
170       if (OnError != null)
171         OnError.Invoke(o, new object[] {context, errorContext});
172     }
173 
JsonContract(Type underlyingType)174     internal JsonContract(Type underlyingType)
175     {
176       ValidationUtils.ArgumentNotNull(underlyingType, "underlyingType");
177 
178       UnderlyingType = underlyingType;
179 
180       IsNullable = ReflectionUtils.IsNullable(underlyingType);
181       NonNullableUnderlyingType = (IsNullable && ReflectionUtils.IsNullableType(underlyingType)) ? Nullable.GetUnderlyingType(underlyingType) : underlyingType;
182 
183       CreatedType = NonNullableUnderlyingType;
184 
185       IsConvertable = ConvertUtils.IsConvertible(NonNullableUnderlyingType);
186 
187       if (NonNullableUnderlyingType == typeof(byte[]))
188       {
189         InternalReadType = ReadType.ReadAsBytes;
190       }
191       else if (NonNullableUnderlyingType == typeof(int))
192       {
193         InternalReadType = ReadType.ReadAsInt32;
194       }
195       else if (NonNullableUnderlyingType == typeof(decimal))
196       {
197         InternalReadType = ReadType.ReadAsDecimal;
198       }
199       else if (NonNullableUnderlyingType == typeof(string))
200       {
201         InternalReadType = ReadType.ReadAsString;
202       }
203       else if (NonNullableUnderlyingType == typeof(DateTime))
204       {
205         InternalReadType = ReadType.ReadAsDateTime;
206       }
207 #if !NET20
208       else if (NonNullableUnderlyingType == typeof(DateTimeOffset))
209       {
210         InternalReadType = ReadType.ReadAsDateTimeOffset;
211       }
212 #endif
213       else
214       {
215         InternalReadType = ReadType.Read;
216       }
217     }
218   }
219 }