2
// Copyright (c) 2007 James Newton-King
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
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
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.
27
using System.Collections;
28
using System.Collections.Generic;
29
using System.ComponentModel;
30
using System.Globalization;
32
using System.Reflection;
33
using System.Runtime.Serialization.Formatters;
34
using Newtonsoft.Json.Linq;
35
using Newtonsoft.Json.Utilities;
36
using System.Runtime.Serialization;
38
namespace Newtonsoft.Json.Serialization
40
internal class JsonSerializerInternalWriter : JsonSerializerInternalBase
42
private JsonSerializerProxy _internalSerializer;
43
private List<object> _serializeStack;
45
private List<object> SerializeStack
49
if (_serializeStack == null)
50
_serializeStack = new List<object>();
52
return _serializeStack;
56
public JsonSerializerInternalWriter(JsonSerializer serializer) : base(serializer)
60
public void Serialize(JsonWriter jsonWriter, object value)
62
if (jsonWriter == null)
63
throw new ArgumentNullException("jsonWriter");
65
SerializeValue(jsonWriter, value, GetContractSafe(value), null, null);
68
private JsonSerializerProxy GetInternalSerializer()
70
if (_internalSerializer == null)
71
_internalSerializer = new JsonSerializerProxy(this);
73
return _internalSerializer;
76
private JsonContract GetContractSafe(object value)
81
return Serializer.ContractResolver.ResolveContract(value.GetType());
84
private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContract collectionValueContract)
86
JsonConverter converter = (member != null) ? member.Converter : null;
94
if ((converter != null
95
|| ((converter = valueContract.Converter) != null)
96
|| ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
97
|| ((converter = valueContract.InternalConverter) != null))
98
&& converter.CanWrite)
100
SerializeConvertable(writer, converter, value, valueContract);
102
else if (valueContract is JsonPrimitiveContract)
104
writer.WriteValue(value);
106
else if (valueContract is JsonStringContract)
108
SerializeString(writer, value, (JsonStringContract) valueContract);
110
else if (valueContract is JsonObjectContract)
112
SerializeObject(writer, value, (JsonObjectContract)valueContract, member, collectionValueContract);
114
else if (valueContract is JsonDictionaryContract)
116
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract;
117
SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionValueContract);
119
else if (valueContract is JsonArrayContract)
123
SerializeList(writer, (IList)value, (JsonArrayContract)valueContract, member, collectionValueContract);
125
else if (value is IEnumerable)
127
SerializeList(writer, ((IEnumerable)value).Cast<object>().ToList(), (JsonArrayContract)valueContract, member, collectionValueContract);
132
"Cannot serialize '{0}' into a JSON array. Type does not implement IEnumerable.".FormatWith(
133
CultureInfo.InvariantCulture, value.GetType()));
136
else if (valueContract is JsonLinqContract)
138
((JToken)value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
140
#if !SILVERLIGHT && !PocketPC
141
else if (valueContract is JsonISerializableContract)
143
SerializeISerializable(writer, (ISerializable) value, (JsonISerializableContract) valueContract);
148
private bool ShouldWriteReference(object value, JsonProperty property, JsonContract contract)
152
if (contract is JsonPrimitiveContract)
155
bool? isReference = null;
157
// value could be coming from a dictionary or array and not have a property
158
if (property != null)
159
isReference = property.IsReference;
161
if (isReference == null)
162
isReference = contract.IsReference;
164
if (isReference == null)
166
if (contract is JsonArrayContract)
167
isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
169
isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
172
if (!isReference.Value)
175
return Serializer.ReferenceResolver.IsReferenced(value);
178
private void WriteMemberInfoProperty(JsonWriter writer, object memberValue, JsonProperty property, JsonContract contract)
180
string propertyName = property.PropertyName;
181
object defaultValue = property.DefaultValue;
183
if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore &&
187
if (property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling) ==
188
DefaultValueHandling.Ignore && Equals(memberValue, defaultValue))
191
if (ShouldWriteReference(memberValue, property, contract))
193
writer.WritePropertyName(propertyName);
194
WriteReference(writer, memberValue);
198
if (!CheckForCircularReference(memberValue, property.ReferenceLoopHandling, contract))
201
if (memberValue == null && property.Required == Required.Always)
202
throw new JsonSerializationException("Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
204
writer.WritePropertyName(propertyName);
205
SerializeValue(writer, memberValue, contract, property, null);
208
private bool CheckForCircularReference(object value, ReferenceLoopHandling? referenceLoopHandling, JsonContract contract)
210
if (value == null || contract is JsonPrimitiveContract)
213
if (SerializeStack.IndexOf(value) != -1)
215
switch (referenceLoopHandling.GetValueOrDefault(Serializer.ReferenceLoopHandling))
217
case ReferenceLoopHandling.Error:
218
throw new JsonSerializationException("Self referencing loop");
219
case ReferenceLoopHandling.Ignore:
221
case ReferenceLoopHandling.Serialize:
224
throw new InvalidOperationException("Unexpected ReferenceLoopHandling value: '{0}'".FormatWith(CultureInfo.InvariantCulture, Serializer.ReferenceLoopHandling));
231
private void WriteReference(JsonWriter writer, object value)
233
writer.WriteStartObject();
234
writer.WritePropertyName(JsonTypeReflector.RefPropertyName);
235
writer.WriteValue(Serializer.ReferenceResolver.GetReference(value));
236
writer.WriteEndObject();
239
internal static bool TryConvertToString(object value, Type type, out string s)
242
TypeConverter converter = ConvertUtils.GetConverter(type);
244
// use the objectType's TypeConverter if it has one and can convert to a string
245
if (converter != null
247
&& !(converter is ComponentConverter)
249
&& converter.GetType() != typeof(TypeConverter))
251
if (converter.CanConvertTo(typeof(string)))
254
s = converter.ConvertToInvariantString(value);
256
s = converter.ConvertToString(value);
263
#if SILVERLIGHT || PocketPC
264
if (value is Guid || value is Uri || value is TimeSpan)
266
s = value.ToString();
273
s = ((Type)value).AssemblyQualifiedName;
281
private void SerializeString(JsonWriter writer, object value, JsonStringContract contract)
283
contract.InvokeOnSerializing(value, Serializer.Context);
286
TryConvertToString(value, contract.UnderlyingType, out s);
287
writer.WriteValue(s);
289
contract.InvokeOnSerialized(value, Serializer.Context);
292
private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContract collectionValueContract)
294
contract.InvokeOnSerializing(value, Serializer.Context);
296
SerializeStack.Add(value);
297
writer.WriteStartObject();
299
bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
302
writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
303
writer.WriteValue(Serializer.ReferenceResolver.GetReference(value));
305
if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract))
307
WriteTypeProperty(writer, contract.UnderlyingType);
310
int initialDepth = writer.Top;
312
foreach (JsonProperty property in contract.Properties)
316
if (!property.Ignored && property.Readable && ShouldSerialize(property, value))
318
object memberValue = property.ValueProvider.GetValue(value);
319
JsonContract memberContract = GetContractSafe(memberValue);
321
WriteMemberInfoProperty(writer, memberValue, property, memberContract);
326
if (IsErrorHandled(value, contract, property.PropertyName, ex))
327
HandleError(writer, initialDepth);
333
writer.WriteEndObject();
334
SerializeStack.RemoveAt(SerializeStack.Count - 1);
336
contract.InvokeOnSerialized(value, Serializer.Context);
339
private void WriteTypeProperty(JsonWriter writer, Type type)
341
writer.WritePropertyName(JsonTypeReflector.TypePropertyName);
342
writer.WriteValue(ReflectionUtils.GetTypeName(type, Serializer.TypeNameAssemblyFormat));
345
private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag)
347
return ((value & flag) == flag);
350
private bool HasFlag(TypeNameHandling value, TypeNameHandling flag)
352
return ((value & flag) == flag);
355
private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract)
357
if (ShouldWriteReference(value, null, contract))
359
WriteReference(writer, value);
363
if (!CheckForCircularReference(value, null, contract))
366
SerializeStack.Add(value);
368
converter.WriteJson(writer, value, GetInternalSerializer());
370
SerializeStack.RemoveAt(SerializeStack.Count - 1);
374
private void SerializeList(JsonWriter writer, IList values, JsonArrayContract contract, JsonProperty member, JsonContract collectionValueContract)
376
contract.InvokeOnSerializing(values, Serializer.Context);
378
SerializeStack.Add(values);
380
bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
381
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionValueContract);
383
if (isReference || includeTypeDetails)
385
writer.WriteStartObject();
389
writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
390
writer.WriteValue(Serializer.ReferenceResolver.GetReference(values));
392
if (includeTypeDetails)
394
WriteTypeProperty(writer, values.GetType());
396
writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName);
399
JsonContract childValuesContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object));
401
writer.WriteStartArray();
403
int initialDepth = writer.Top;
405
for (int i = 0; i < values.Count; i++)
409
object value = values[i];
410
JsonContract valueContract = GetContractSafe(value);
412
if (ShouldWriteReference(value, null, valueContract))
414
WriteReference(writer, value);
418
if (!CheckForCircularReference(value, null, contract))
421
SerializeValue(writer, value, valueContract, null, childValuesContract);
426
if (IsErrorHandled(values, contract, i, ex))
427
HandleError(writer, initialDepth);
433
writer.WriteEndArray();
435
if (isReference || includeTypeDetails)
437
writer.WriteEndObject();
440
SerializeStack.RemoveAt(SerializeStack.Count - 1);
442
contract.InvokeOnSerialized(values, Serializer.Context);
445
#if !SILVERLIGHT && !PocketPC
446
private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract)
448
contract.InvokeOnSerializing(value, Serializer.Context);
449
SerializeStack.Add(value);
451
writer.WriteStartObject();
453
SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter());
454
value.GetObjectData(serializationInfo, Serializer.Context);
456
foreach (SerializationEntry serializationEntry in serializationInfo)
458
writer.WritePropertyName(serializationEntry.Name);
459
SerializeValue(writer, serializationEntry.Value, GetContractSafe(serializationEntry.Value), null, null);
462
writer.WriteEndObject();
464
SerializeStack.RemoveAt(SerializeStack.Count - 1);
465
contract.InvokeOnSerialized(value, Serializer.Context);
469
//private bool ShouldWriteTypeProperty(JsonProperty member, JsonContract contract, TypeNameHandling typeFlag)
471
// if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeFlag))
474
// if ((((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto)
476
// || (member != null
477
// && (member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto
478
// && contract.UnderlyingType != member.PropertyType)
482
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContract collectionValueContract)
484
if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeNameHandlingFlag))
489
if ((member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto && contract.UnderlyingType != member.PropertyType)
492
else if (collectionValueContract != null)
494
if (Serializer.TypeNameHandling == TypeNameHandling.Auto && contract.UnderlyingType != collectionValueContract.UnderlyingType)
501
private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContract collectionValueContract)
503
contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context);
505
SerializeStack.Add(values.UnderlyingDictionary);
506
writer.WriteStartObject();
508
bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
511
writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
512
writer.WriteValue(Serializer.ReferenceResolver.GetReference(values.UnderlyingDictionary));
514
if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract))
516
WriteTypeProperty(writer, values.UnderlyingDictionary.GetType());
519
JsonContract childValuesContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
521
int initialDepth = writer.Top;
523
// Mono Unity 3.0 fix
524
IDictionary d = values;
526
foreach (DictionaryEntry entry in d)
528
string propertyName = GetPropertyName(entry);
532
object value = entry.Value;
533
JsonContract valueContract = GetContractSafe(value);
535
if (ShouldWriteReference(value, null, valueContract))
537
writer.WritePropertyName(propertyName);
538
WriteReference(writer, value);
542
if (!CheckForCircularReference(value, null, contract))
545
writer.WritePropertyName(propertyName);
547
SerializeValue(writer, value, valueContract, null, childValuesContract);
552
if (IsErrorHandled(values.UnderlyingDictionary, contract, propertyName, ex))
553
HandleError(writer, initialDepth);
559
writer.WriteEndObject();
560
SerializeStack.RemoveAt(SerializeStack.Count - 1);
562
contract.InvokeOnSerialized(values.UnderlyingDictionary, Serializer.Context);
565
private string GetPropertyName(DictionaryEntry entry)
569
if (entry.Key is IConvertible)
570
return Convert.ToString(entry.Key, CultureInfo.InvariantCulture);
571
else if (TryConvertToString(entry.Key, entry.Key.GetType(), out propertyName))
574
return entry.Key.ToString();
577
private void HandleError(JsonWriter writer, int initialDepth)
581
while (writer.Top > initialDepth)
587
private bool ShouldSerialize(JsonProperty property, object target)
589
if (property.ShouldSerialize == null)
592
return property.ShouldSerialize(target);
2
// Copyright (c) 2007 James Newton-King
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
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
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.
27
using System.Collections;
28
using System.Collections.Generic;
29
using System.ComponentModel;
30
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
33
using System.Globalization;
34
using System.Security;
35
using Newtonsoft.Json.Linq;
36
using Newtonsoft.Json.Utilities;
37
using System.Runtime.Serialization;
39
using Newtonsoft.Json.Utilities.LinqBridge;
44
namespace Newtonsoft.Json.Serialization
46
internal class JsonSerializerInternalWriter : JsonSerializerInternalBase
48
private readonly List<object> _serializeStack = new List<object>();
49
private JsonSerializerProxy _internalSerializer;
51
public JsonSerializerInternalWriter(JsonSerializer serializer)
56
public void Serialize(JsonWriter jsonWriter, object value)
58
if (jsonWriter == null)
59
throw new ArgumentNullException("jsonWriter");
61
SerializeValue(jsonWriter, value, GetContractSafe(value), null, null, null);
64
private JsonSerializerProxy GetInternalSerializer()
66
if (_internalSerializer == null)
67
_internalSerializer = new JsonSerializerProxy(this);
69
return _internalSerializer;
72
private JsonContract GetContractSafe(object value)
77
return Serializer.ContractResolver.ResolveContract(value.GetType());
80
private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
82
if (contract.UnderlyingType == typeof (byte[]))
84
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty);
85
if (includeTypeDetails)
87
writer.WriteStartObject();
88
WriteTypeProperty(writer, contract.CreatedType);
89
writer.WritePropertyName(JsonTypeReflector.ValuePropertyName);
90
writer.WriteValue(value);
91
writer.WriteEndObject();
96
writer.WriteValue(value);
99
private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
107
JsonConverter converter;
108
if ((((converter = (member != null) ? member.Converter : null) != null)
109
|| ((converter = (containerProperty != null) ? containerProperty.ItemConverter : null) != null)
110
|| ((converter = (containerContract != null) ? containerContract.ItemConverter : null) != null)
111
|| ((converter = valueContract.Converter) != null)
112
|| ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
113
|| ((converter = valueContract.InternalConverter) != null))
114
&& converter.CanWrite)
116
SerializeConvertable(writer, converter, value, valueContract, containerContract, containerProperty);
120
switch (valueContract.ContractType)
122
case JsonContractType.Object:
123
SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty);
125
case JsonContractType.Array:
126
JsonArrayContract arrayContract = (JsonArrayContract) valueContract;
127
if (!arrayContract.IsMultidimensionalArray)
128
SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, containerContract, containerProperty);
130
SerializeMultidimensionalArray(writer, (Array)value, arrayContract, member, containerContract, containerProperty);
132
case JsonContractType.Primitive:
133
SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty);
135
case JsonContractType.String:
136
SerializeString(writer, value, (JsonStringContract)valueContract);
138
case JsonContractType.Dictionary:
139
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract;
140
SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty);
142
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
143
case JsonContractType.Dynamic:
144
SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty);
147
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
148
case JsonContractType.Serializable:
149
SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty);
152
case JsonContractType.Linq:
153
((JToken) value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
158
private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty)
160
bool? isReference = null;
162
// value could be coming from a dictionary or array and not have a property
163
if (property != null)
164
isReference = property.IsReference;
166
if (isReference == null && containerProperty != null)
167
isReference = containerProperty.ItemIsReference;
169
if (isReference == null && collectionContract != null)
170
isReference = collectionContract.ItemIsReference;
172
if (isReference == null)
173
isReference = contract.IsReference;
178
private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract, JsonProperty containerProperty)
182
if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String)
185
bool? isReference = ResolveIsReference(valueContract, property, collectionContract, containerProperty);
187
if (isReference == null)
189
if (valueContract.ContractType == JsonContractType.Array)
190
isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
192
isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
195
if (!isReference.Value)
198
return Serializer.ReferenceResolver.IsReferenced(this, value);
201
private bool ShouldWriteProperty(object memberValue, JsonProperty property)
203
if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore &&
207
if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore)
208
&& MiscellaneousUtils.ValueEquals(memberValue, property.DefaultValue))
214
private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
216
if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
219
ReferenceLoopHandling? referenceLoopHandling = null;
221
if (property != null)
222
referenceLoopHandling = property.ReferenceLoopHandling;
224
if (referenceLoopHandling == null && containerProperty != null)
225
referenceLoopHandling = containerProperty.ItemReferenceLoopHandling;
227
if (referenceLoopHandling == null && containerContract != null)
228
referenceLoopHandling = containerContract.ItemReferenceLoopHandling;
230
if (_serializeStack.IndexOf(value) != -1)
232
switch (referenceLoopHandling.GetValueOrDefault(Serializer.ReferenceLoopHandling))
234
case ReferenceLoopHandling.Error:
235
string message = "Self referencing loop detected";
236
if (property != null)
237
message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName);
238
message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType());
240
throw JsonSerializationException.Create(null, writer.ContainerPath, message, null);
241
case ReferenceLoopHandling.Ignore:
243
case ReferenceLoopHandling.Serialize:
246
throw new InvalidOperationException("Unexpected ReferenceLoopHandling value: '{0}'".FormatWith(CultureInfo.InvariantCulture, Serializer.ReferenceLoopHandling));
253
private void WriteReference(JsonWriter writer, object value)
255
writer.WriteStartObject();
256
writer.WritePropertyName(JsonTypeReflector.RefPropertyName);
257
writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value));
258
writer.WriteEndObject();
261
internal static bool TryConvertToString(object value, Type type, out string s)
263
#if !(PocketPC || NETFX_CORE || PORTABLE)
264
TypeConverter converter = ConvertUtils.GetConverter(type);
266
// use the objectType's TypeConverter if it has one and can convert to a string
267
if (converter != null
269
&& !(converter is ComponentConverter)
271
&& converter.GetType() != typeof(TypeConverter))
273
if (converter.CanConvertTo(typeof(string)))
276
s = converter.ConvertToInvariantString(value);
278
s = converter.ConvertToString(value);
285
#if SILVERLIGHT || PocketPC || NETFX_CORE
286
if (value is Guid || value is Uri || value is TimeSpan)
288
s = value.ToString();
295
s = ((Type)value).AssemblyQualifiedName;
303
private void SerializeString(JsonWriter writer, object value, JsonStringContract contract)
305
contract.InvokeOnSerializing(value, Serializer.Context);
308
TryConvertToString(value, contract.UnderlyingType, out s);
309
writer.WriteValue(s);
311
contract.InvokeOnSerialized(value, Serializer.Context);
314
private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
316
contract.InvokeOnSerializing(value, Serializer.Context);
318
_serializeStack.Add(value);
320
WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
322
int initialDepth = writer.Top;
324
foreach (JsonProperty property in contract.Properties)
329
JsonContract memberContract;
331
if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
334
writer.WritePropertyName(property.PropertyName);
335
SerializeValue(writer, memberValue, memberContract, property, contract, member);
339
if (IsErrorHandled(value, contract, property.PropertyName, writer.ContainerPath, ex))
340
HandleError(writer, initialDepth);
346
writer.WriteEndObject();
348
_serializeStack.RemoveAt(_serializeStack.Count - 1);
350
contract.InvokeOnSerialized(value, Serializer.Context);
353
private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, out JsonContract memberContract, out object memberValue)
355
if (!property.Ignored && property.Readable && ShouldSerialize(property, value) && IsSpecified(property, value))
357
if (property.PropertyContract == null)
358
property.PropertyContract = Serializer.ContractResolver.ResolveContract(property.PropertyType);
360
memberValue = property.ValueProvider.GetValue(value);
361
memberContract = (property.PropertyContract.UnderlyingType.IsSealed()) ? property.PropertyContract : GetContractSafe(memberValue);
363
if (ShouldWriteProperty(memberValue, property))
365
if (ShouldWriteReference(memberValue, property, memberContract, contract, member))
367
writer.WritePropertyName(property.PropertyName);
368
WriteReference(writer, memberValue);
372
if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member))
375
if (memberValue == null)
377
JsonObjectContract objectContract = contract as JsonObjectContract;
378
Required resolvedRequired = property._required ?? ((objectContract != null) ? objectContract.ItemRequired : null) ?? Required.Default;
379
if (resolvedRequired == Required.Always)
380
throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
387
memberContract = null;
392
private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
394
writer.WriteStartObject();
396
bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
399
writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
400
writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value));
402
if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty))
404
WriteTypeProperty(writer, contract.UnderlyingType);
408
private void WriteTypeProperty(JsonWriter writer, Type type)
410
writer.WritePropertyName(JsonTypeReflector.TypePropertyName);
411
writer.WriteValue(ReflectionUtils.GetTypeName(type, Serializer.TypeNameAssemblyFormat, Serializer.Binder));
414
private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
416
return ((value & flag) == flag);
419
private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag)
421
return ((value & flag) == flag);
424
private bool HasFlag(TypeNameHandling value, TypeNameHandling flag)
426
return ((value & flag) == flag);
429
private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
431
if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty))
433
WriteReference(writer, value);
437
if (!CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty))
440
_serializeStack.Add(value);
442
converter.WriteJson(writer, value, GetInternalSerializer());
444
_serializeStack.RemoveAt(_serializeStack.Count - 1);
448
private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
450
contract.InvokeOnSerializing(values.UnderlyingCollection, Serializer.Context);
452
_serializeStack.Add(values.UnderlyingCollection);
454
bool hasWrittenMetadataObject = WriteStartArray(writer, values.UnderlyingCollection, contract, member, collectionContract, containerProperty);
456
writer.WriteStartArray();
458
int initialDepth = writer.Top;
461
// note that an error in the IEnumerable won't be caught
462
foreach (object value in values)
466
JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
468
if (ShouldWriteReference(value, null, valueContract, contract, member))
470
WriteReference(writer, value);
474
if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
476
SerializeValue(writer, value, valueContract, null, contract, member);
482
if (IsErrorHandled(values.UnderlyingCollection, contract, index, writer.ContainerPath, ex))
483
HandleError(writer, initialDepth);
493
writer.WriteEndArray();
495
if (hasWrittenMetadataObject)
496
writer.WriteEndObject();
498
_serializeStack.RemoveAt(_serializeStack.Count - 1);
500
contract.InvokeOnSerialized(values.UnderlyingCollection, Serializer.Context);
503
private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
505
contract.InvokeOnSerializing(values, Serializer.Context);
507
_serializeStack.Add(values);
509
bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty);
511
SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]);
513
if (hasWrittenMetadataObject)
514
writer.WriteEndObject();
516
_serializeStack.RemoveAt(_serializeStack.Count - 1);
518
contract.InvokeOnSerialized(values, Serializer.Context);
521
private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, int initialDepth, int[] indices)
523
int dimension = indices.Length;
524
int[] newIndices = new int[dimension + 1];
525
for (int i = 0; i < dimension; i++)
527
newIndices[i] = indices[i];
530
writer.WriteStartArray();
532
for (int i = 0; i < values.GetLength(dimension); i++)
534
newIndices[dimension] = i;
535
bool isTopLevel = (newIndices.Length == values.Rank);
539
object value = values.GetValue(newIndices);
543
JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
545
if (ShouldWriteReference(value, null, valueContract, contract, member))
547
WriteReference(writer, value);
551
if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
553
SerializeValue(writer, value, valueContract, null, contract, member);
559
if (IsErrorHandled(values, contract, i, writer.ContainerPath, ex))
560
HandleError(writer, initialDepth + 1);
567
SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, newIndices);
571
writer.WriteEndArray();
574
private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
576
bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
577
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
578
bool writeMetadataObject = isReference || includeTypeDetails;
580
if (writeMetadataObject)
582
writer.WriteStartObject();
586
writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
587
writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values));
589
if (includeTypeDetails)
591
WriteTypeProperty(writer, values.GetType());
593
writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName);
596
if (contract.ItemContract == null)
597
contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof (object));
599
return writeMetadataObject;
602
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
603
#if !(NET20 || NET35)
604
[SecuritySafeCritical]
606
private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
608
if (!JsonTypeReflector.FullyTrusted)
610
throw JsonSerializationException.Create(null, writer.ContainerPath, @"Type '{0}' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data.
611
To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null);
614
contract.InvokeOnSerializing(value, Serializer.Context);
615
_serializeStack.Add(value);
617
WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
619
SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter());
620
value.GetObjectData(serializationInfo, Serializer.Context);
622
foreach (SerializationEntry serializationEntry in serializationInfo)
624
writer.WritePropertyName(serializationEntry.Name);
625
SerializeValue(writer, serializationEntry.Value, GetContractSafe(serializationEntry.Value), null, null, member);
628
writer.WriteEndObject();
630
_serializeStack.RemoveAt(_serializeStack.Count - 1);
631
contract.InvokeOnSerialized(value, Serializer.Context);
635
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
636
private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
638
contract.InvokeOnSerializing(value, Serializer.Context);
639
_serializeStack.Add(value);
641
WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
643
int initialDepth = writer.Top;
645
foreach (JsonProperty property in contract.Properties)
647
// only write non-dynamic properties that have an explicit attribute
648
if (property.HasMemberAttribute)
653
JsonContract memberContract;
655
if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
658
writer.WritePropertyName(property.PropertyName);
659
SerializeValue(writer, memberValue, memberContract, property, contract, member);
663
if (IsErrorHandled(value, contract, property.PropertyName, writer.ContainerPath, ex))
664
HandleError(writer, initialDepth);
671
foreach (string memberName in value.GetDynamicMemberNames())
674
if (value.TryGetMember(memberName, out memberValue))
678
string resolvedPropertyName = (contract.PropertyNameResolver != null)
679
? contract.PropertyNameResolver(memberName)
682
writer.WritePropertyName(resolvedPropertyName);
683
SerializeValue(writer, memberValue, GetContractSafe(memberValue), null, null, member);
687
if (IsErrorHandled(value, contract, memberName, writer.ContainerPath, ex))
688
HandleError(writer, initialDepth);
695
writer.WriteEndObject();
697
_serializeStack.RemoveAt(_serializeStack.Count - 1);
698
contract.InvokeOnSerialized(value, Serializer.Context);
702
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
704
TypeNameHandling resolvedTypeNameHandling =
705
((member != null) ? member.TypeNameHandling : null)
706
?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null)
707
?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
708
?? Serializer.TypeNameHandling;
710
if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag))
713
// instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default)
714
if (HasFlag(resolvedTypeNameHandling, TypeNameHandling.Auto))
718
if (contract.UnderlyingType != member.PropertyContract.CreatedType)
721
else if (containerContract != null && containerContract.ItemContract != null)
723
if (contract.UnderlyingType != containerContract.ItemContract.CreatedType)
731
private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
733
contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context);
735
_serializeStack.Add(values.UnderlyingDictionary);
737
WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionContract, containerProperty);
739
if (contract.ItemContract == null)
740
contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
742
int initialDepth = writer.Top;
744
// Mono Unity 3.0 fix
745
IWrappedDictionary d = values;
747
foreach (DictionaryEntry entry in d)
749
string propertyName = GetPropertyName(entry);
751
propertyName = (contract.PropertyNameResolver != null)
752
? contract.PropertyNameResolver(propertyName)
757
object value = entry.Value;
758
JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
760
if (ShouldWriteReference(value, null, valueContract, contract, member))
762
writer.WritePropertyName(propertyName);
763
WriteReference(writer, value);
767
if (!CheckForCircularReference(writer, value, null, valueContract, contract, member))
770
writer.WritePropertyName(propertyName);
772
SerializeValue(writer, value, valueContract, null, contract, member);
777
if (IsErrorHandled(values.UnderlyingDictionary, contract, propertyName, writer.ContainerPath, ex))
778
HandleError(writer, initialDepth);
784
writer.WriteEndObject();
786
_serializeStack.RemoveAt(_serializeStack.Count - 1);
788
contract.InvokeOnSerialized(values.UnderlyingDictionary, Serializer.Context);
791
private string GetPropertyName(DictionaryEntry entry)
795
if (ConvertUtils.IsConvertible(entry.Key))
796
return Convert.ToString(entry.Key, CultureInfo.InvariantCulture);
797
else if (TryConvertToString(entry.Key, entry.Key.GetType(), out propertyName))
800
return entry.Key.ToString();
803
private void HandleError(JsonWriter writer, int initialDepth)
807
if (writer.WriteState == WriteState.Property)
810
while (writer.Top > initialDepth)
816
private bool ShouldSerialize(JsonProperty property, object target)
818
if (property.ShouldSerialize == null)
821
return property.ShouldSerialize(target);
824
private bool IsSpecified(JsonProperty property, object target)
826
if (property.GetIsSpecified == null)
829
return property.GetIsSpecified(target);
b'\\ No newline at end of file'