~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.Collections;
 
28
using System.Collections.Generic;
 
29
using System.ComponentModel;
 
30
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
 
31
using System.Dynamic;
 
32
#endif
 
33
using System.Diagnostics;
 
34
using System.Globalization;
 
35
using System.Security;
 
36
using Newtonsoft.Json.Linq;
 
37
using Newtonsoft.Json.Utilities;
 
38
using System.Runtime.Serialization;
 
39
#if NET20
 
40
using Newtonsoft.Json.Utilities.LinqBridge;
 
41
#else
 
42
using System.Linq;
 
43
#endif
 
44
 
 
45
namespace Newtonsoft.Json.Serialization
 
46
{
 
47
  internal class JsonSerializerInternalWriter : JsonSerializerInternalBase
 
48
  {
 
49
    private readonly List<object> _serializeStack = new List<object>();
 
50
    private JsonSerializerProxy _internalSerializer;
 
51
 
 
52
    public JsonSerializerInternalWriter(JsonSerializer serializer)
 
53
      : base(serializer)
 
54
    {
 
55
    }
 
56
 
 
57
    public void Serialize(JsonWriter jsonWriter, object value)
 
58
    {
 
59
      if (jsonWriter == null)
 
60
        throw new ArgumentNullException("jsonWriter");
 
61
 
 
62
      SerializeValue(jsonWriter, value, GetContractSafe(value), null, null, null);
 
63
    }
 
64
 
 
65
    private JsonSerializerProxy GetInternalSerializer()
 
66
    {
 
67
      if (_internalSerializer == null)
 
68
        _internalSerializer = new JsonSerializerProxy(this);
 
69
 
 
70
      return _internalSerializer;
 
71
    }
 
72
 
 
73
    private JsonContract GetContractSafe(object value)
 
74
    {
 
75
      if (value == null)
 
76
        return null;
 
77
 
 
78
      return Serializer.ContractResolver.ResolveContract(value.GetType());
 
79
    }
 
80
 
 
81
    private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
 
82
    {
 
83
      if (contract.UnderlyingType == typeof (byte[]))
 
84
      {
 
85
        bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty);
 
86
        if (includeTypeDetails)
 
87
        {
 
88
          writer.WriteStartObject();
 
89
          WriteTypeProperty(writer, contract.CreatedType);
 
90
          writer.WritePropertyName(JsonTypeReflector.ValuePropertyName);
 
91
          writer.WriteValue(value);
 
92
          writer.WriteEndObject();
 
93
          return;
 
94
        }
 
95
      }
 
96
 
 
97
      writer.WriteValue(value);
 
98
    }
 
99
 
 
100
    private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
 
101
    {
 
102
      if (value == null)
 
103
      {
 
104
        writer.WriteNull();
 
105
        return;
 
106
      }
 
107
 
 
108
      JsonConverter converter;
 
109
      if ((((converter = (member != null) ? member.Converter : null) != null)
 
110
           || ((converter = (containerProperty != null) ? containerProperty.ItemConverter : null) != null)
 
111
           || ((converter = (containerContract != null) ? containerContract.ItemConverter : null) != null)
 
112
           || ((converter = valueContract.Converter) != null)
 
113
           || ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
 
114
           || ((converter = valueContract.InternalConverter) != null))
 
115
          && converter.CanWrite)
 
116
      {
 
117
        SerializeConvertable(writer, converter, value, valueContract, containerContract, containerProperty);
 
118
        return;
 
119
      }
 
120
 
 
121
      switch (valueContract.ContractType)
 
122
      {
 
123
        case JsonContractType.Object:
 
124
          SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty);
 
125
          break;
 
126
        case JsonContractType.Array:
 
127
          JsonArrayContract arrayContract = (JsonArrayContract) valueContract;
 
128
          if (!arrayContract.IsMultidimensionalArray)
 
129
            SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, containerContract, containerProperty);
 
130
          else
 
131
            SerializeMultidimensionalArray(writer, (Array)value, arrayContract, member, containerContract, containerProperty);
 
132
          break;
 
133
        case JsonContractType.Primitive:
 
134
          SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty);
 
135
          break;
 
136
        case JsonContractType.String:
 
137
          SerializeString(writer, value, (JsonStringContract)valueContract);
 
138
          break;
 
139
        case JsonContractType.Dictionary:
 
140
          JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract;
 
141
          SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty);
 
142
          break;
 
143
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
 
144
        case JsonContractType.Dynamic:
 
145
          SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty);
 
146
          break;
 
147
#endif
 
148
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
 
149
        case JsonContractType.Serializable:
 
150
          SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty);
 
151
          break;
 
152
#endif
 
153
        case JsonContractType.Linq:
 
154
          ((JToken) value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
 
155
          break;
 
156
      }
 
157
    }
 
158
 
 
159
    private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
160
    {
 
161
      bool? isReference = null;
 
162
 
 
163
      // value could be coming from a dictionary or array and not have a property
 
164
      if (property != null)
 
165
        isReference = property.IsReference;
 
166
 
 
167
      if (isReference == null && containerProperty != null)
 
168
        isReference = containerProperty.ItemIsReference;
 
169
 
 
170
      if (isReference == null && collectionContract != null)
 
171
        isReference = collectionContract.ItemIsReference;
 
172
 
 
173
      if (isReference == null)
 
174
        isReference = contract.IsReference;
 
175
 
 
176
      return isReference;
 
177
    }
 
178
 
 
179
    private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
180
    {
 
181
      if (value == null)
 
182
        return false;
 
183
      if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String)
 
184
        return false;
 
185
 
 
186
      bool? isReference = ResolveIsReference(valueContract, property, collectionContract, containerProperty);
 
187
 
 
188
      if (isReference == null)
 
189
      {
 
190
        if (valueContract.ContractType == JsonContractType.Array)
 
191
          isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
 
192
        else
 
193
          isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
 
194
      }
 
195
 
 
196
      if (!isReference.Value)
 
197
        return false;
 
198
 
 
199
      return Serializer.ReferenceResolver.IsReferenced(this, value);
 
200
    }
 
201
 
 
202
    private bool ShouldWriteProperty(object memberValue, JsonProperty property)
 
203
    {
 
204
      if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore &&
 
205
          memberValue == null)
 
206
        return false;
 
207
 
 
208
      if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore)
 
209
          && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue()))
 
210
        return false;
 
211
 
 
212
      return true;
 
213
    }
 
214
 
 
215
    private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
 
216
    {
 
217
      if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
 
218
        return true;
 
219
 
 
220
      ReferenceLoopHandling? referenceLoopHandling = null;
 
221
 
 
222
      if (property != null)
 
223
        referenceLoopHandling = property.ReferenceLoopHandling;
 
224
 
 
225
      if (referenceLoopHandling == null && containerProperty != null)
 
226
        referenceLoopHandling = containerProperty.ItemReferenceLoopHandling;
 
227
 
 
228
      if (referenceLoopHandling == null && containerContract != null)
 
229
        referenceLoopHandling = containerContract.ItemReferenceLoopHandling;
 
230
 
 
231
      if (_serializeStack.IndexOf(value) != -1)
 
232
      {
 
233
        string message = "Self referencing loop detected";
 
234
        if (property != null)
 
235
          message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName);
 
236
        message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType());
 
237
 
 
238
        switch (referenceLoopHandling.GetValueOrDefault(Serializer.ReferenceLoopHandling))
 
239
        {
 
240
          case ReferenceLoopHandling.Error:
 
241
            throw JsonSerializationException.Create(null, writer.ContainerPath, message, null);
 
242
          case ReferenceLoopHandling.Ignore:
 
243
            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
 
244
              TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Skipping serializing self referenced value."), null);
 
245
 
 
246
            return false;
 
247
          case ReferenceLoopHandling.Serialize:
 
248
            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
 
249
              TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Serializing self referenced value."), null);
 
250
 
 
251
            return true;
 
252
        }
 
253
      }
 
254
 
 
255
      return true;
 
256
    }
 
257
 
 
258
    private void WriteReference(JsonWriter writer, object value)
 
259
    {
 
260
      string reference = GetReference(writer, value);
 
261
 
 
262
      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
 
263
        TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference to Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, value.GetType())), null);
 
264
 
 
265
      writer.WriteStartObject();
 
266
      writer.WritePropertyName(JsonTypeReflector.RefPropertyName);
 
267
      writer.WriteValue(reference);
 
268
      writer.WriteEndObject();
 
269
    }
 
270
 
 
271
    private string GetReference(JsonWriter writer, object value)
 
272
    {
 
273
      try
 
274
      {
 
275
        string reference = Serializer.ReferenceResolver.GetReference(this, value);
 
276
 
 
277
        return reference;
 
278
      }
 
279
      catch (Exception ex)
 
280
      {
 
281
        throw JsonSerializationException.Create(null, writer.ContainerPath, "Error writing object reference for '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), ex);
 
282
      }
 
283
    }
 
284
 
 
285
    internal static bool TryConvertToString(object value, Type type, out string s)
 
286
    {
 
287
#if !(PocketPC || NETFX_CORE || PORTABLE)
 
288
      TypeConverter converter = ConvertUtils.GetConverter(type);
 
289
 
 
290
      // use the objectType's TypeConverter if it has one and can convert to a string
 
291
      if (converter != null
 
292
#if !SILVERLIGHT
 
293
 && !(converter is ComponentConverter)
 
294
#endif
 
295
 && converter.GetType() != typeof(TypeConverter))
 
296
      {
 
297
        if (converter.CanConvertTo(typeof(string)))
 
298
        {
 
299
#if !SILVERLIGHT
 
300
          s = converter.ConvertToInvariantString(value);
 
301
#else
 
302
          s = converter.ConvertToString(value);
 
303
#endif
 
304
          
 
305
          return true;
 
306
        }
 
307
      }
 
308
#endif
 
309
 
 
310
#if SILVERLIGHT || PocketPC || NETFX_CORE
 
311
      if (value is Guid || value is Uri || value is TimeSpan)
 
312
      {
 
313
        s = value.ToString();
 
314
        return true;
 
315
      }
 
316
#endif
 
317
 
 
318
      if (value is Type)
 
319
      {
 
320
        s = ((Type)value).AssemblyQualifiedName;
 
321
        return true;
 
322
      }
 
323
 
 
324
      s = null;
 
325
      return false;
 
326
    }
 
327
 
 
328
    private void SerializeString(JsonWriter writer, object value, JsonStringContract contract)
 
329
    {
 
330
      OnSerializing(writer, contract, value);
 
331
 
 
332
      string s;
 
333
      TryConvertToString(value, contract.UnderlyingType, out s);
 
334
      writer.WriteValue(s);
 
335
 
 
336
      OnSerialized(writer, contract, value);
 
337
    }
 
338
 
 
339
    private void OnSerializing(JsonWriter writer, JsonContract contract, object value)
 
340
    {
 
341
      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
 
342
        TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
 
343
 
 
344
      contract.InvokeOnSerializing(value, Serializer.Context);
 
345
    }
 
346
 
 
347
    private void OnSerialized(JsonWriter writer, JsonContract contract, object value)
 
348
    {
 
349
      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
 
350
        TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
 
351
 
 
352
      contract.InvokeOnSerialized(value, Serializer.Context);
 
353
    }
 
354
 
 
355
    private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
356
    {
 
357
      OnSerializing(writer, contract, value);
 
358
 
 
359
      _serializeStack.Add(value);
 
360
 
 
361
      WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
 
362
 
 
363
      int initialDepth = writer.Top;
 
364
 
 
365
      foreach (JsonProperty property in contract.Properties)
 
366
      {
 
367
        try
 
368
        {
 
369
          object memberValue;
 
370
          JsonContract memberContract;
 
371
 
 
372
          if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
 
373
            continue;
 
374
 
 
375
          writer.WritePropertyName(property.PropertyName);
 
376
          SerializeValue(writer, memberValue, memberContract, property, contract, member);
 
377
        }
 
378
        catch (Exception ex)
 
379
        {
 
380
          if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex))
 
381
            HandleError(writer, initialDepth);
 
382
          else
 
383
            throw;
 
384
        }
 
385
      }
 
386
 
 
387
      writer.WriteEndObject();
 
388
 
 
389
      _serializeStack.RemoveAt(_serializeStack.Count - 1);
 
390
 
 
391
      OnSerialized(writer, contract, value);
 
392
    }
 
393
 
 
394
    private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, out JsonContract memberContract, out object memberValue)
 
395
    {
 
396
      if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value))
 
397
      {
 
398
        if (property.PropertyContract == null)
 
399
          property.PropertyContract = Serializer.ContractResolver.ResolveContract(property.PropertyType);
 
400
 
 
401
        memberValue = property.ValueProvider.GetValue(value);
 
402
        memberContract = (property.PropertyContract.UnderlyingType.IsSealed()) ? property.PropertyContract : GetContractSafe(memberValue);
 
403
 
 
404
        if (ShouldWriteProperty(memberValue, property))
 
405
        {
 
406
          if (ShouldWriteReference(memberValue, property, memberContract, contract, member))
 
407
          {
 
408
            writer.WritePropertyName(property.PropertyName);
 
409
            WriteReference(writer, memberValue);
 
410
            return false;
 
411
          }
 
412
 
 
413
          if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member))
 
414
            return false;
 
415
 
 
416
          if (memberValue == null)
 
417
          {
 
418
            JsonObjectContract objectContract = contract as JsonObjectContract;
 
419
            Required resolvedRequired = property._required ?? ((objectContract != null) ? objectContract.ItemRequired : null) ?? Required.Default;
 
420
            if (resolvedRequired == Required.Always)
 
421
              throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
 
422
          }
 
423
 
 
424
          return true;
 
425
        }
 
426
      }
 
427
 
 
428
      memberContract = null;
 
429
      memberValue = null;
 
430
      return false;
 
431
    }
 
432
 
 
433
    private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
434
    {
 
435
      writer.WriteStartObject();
 
436
 
 
437
      bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
 
438
      if (isReference)
 
439
      {
 
440
        WriteReferenceIdProperty(writer, contract.UnderlyingType, value);
 
441
      }
 
442
      if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty))
 
443
      {
 
444
        WriteTypeProperty(writer, contract.UnderlyingType);
 
445
      }
 
446
    }
 
447
 
 
448
    private void WriteReferenceIdProperty(JsonWriter writer, Type type, object value)
 
449
    {
 
450
      string reference = GetReference(writer, value);
 
451
 
 
452
      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
 
453
        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, type)), null);
 
454
 
 
455
      writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
 
456
      writer.WriteValue(reference);
 
457
    }
 
458
 
 
459
    private void WriteTypeProperty(JsonWriter writer, Type type)
 
460
    {
 
461
      string typeName = ReflectionUtils.GetTypeName(type, Serializer.TypeNameAssemblyFormat, Serializer.Binder);
 
462
 
 
463
      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
 
464
        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing type name '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, typeName, type)), null);
 
465
 
 
466
      writer.WritePropertyName(JsonTypeReflector.TypePropertyName);
 
467
      writer.WriteValue(typeName);
 
468
    }
 
469
 
 
470
    private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
 
471
    {
 
472
      return ((value & flag) == flag);
 
473
    }
 
474
 
 
475
    private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag)
 
476
    {
 
477
      return ((value & flag) == flag);
 
478
    }
 
479
 
 
480
    private bool HasFlag(TypeNameHandling value, TypeNameHandling flag)
 
481
    {
 
482
      return ((value & flag) == flag);
 
483
    }
 
484
 
 
485
    private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
486
    {
 
487
      if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty))
 
488
      {
 
489
        WriteReference(writer, value);
 
490
      }
 
491
      else
 
492
      {
 
493
        if (!CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty))
 
494
          return;
 
495
 
 
496
        _serializeStack.Add(value);
 
497
 
 
498
        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
 
499
          TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
 
500
 
 
501
        converter.WriteJson(writer, value, GetInternalSerializer());
 
502
 
 
503
        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
 
504
          TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
 
505
 
 
506
        _serializeStack.RemoveAt(_serializeStack.Count - 1);
 
507
      }
 
508
    }
 
509
 
 
510
    private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
511
    {
 
512
      OnSerializing(writer, contract, values.UnderlyingCollection);
 
513
 
 
514
      _serializeStack.Add(values.UnderlyingCollection);
 
515
 
 
516
      bool hasWrittenMetadataObject = WriteStartArray(writer, values.UnderlyingCollection, contract, member, collectionContract, containerProperty);
 
517
 
 
518
      writer.WriteStartArray();
 
519
 
 
520
      int initialDepth = writer.Top;
 
521
 
 
522
      int index = 0;
 
523
      // note that an error in the IEnumerable won't be caught
 
524
      foreach (object value in values)
 
525
      {
 
526
        try
 
527
        {
 
528
          JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
 
529
 
 
530
          if (ShouldWriteReference(value, null, valueContract, contract, member))
 
531
          {
 
532
            WriteReference(writer, value);
 
533
          }
 
534
          else
 
535
          {
 
536
            if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
 
537
            {
 
538
              SerializeValue(writer, value, valueContract, null, contract, member);
 
539
            }
 
540
          }
 
541
        }
 
542
        catch (Exception ex)
 
543
        {
 
544
          if (IsErrorHandled(values.UnderlyingCollection, contract, index, null, writer.ContainerPath, ex))
 
545
            HandleError(writer, initialDepth);
 
546
          else
 
547
            throw;
 
548
        }
 
549
        finally
 
550
        {
 
551
          index++;
 
552
        }
 
553
      }
 
554
 
 
555
      writer.WriteEndArray();
 
556
 
 
557
      if (hasWrittenMetadataObject)
 
558
        writer.WriteEndObject();
 
559
 
 
560
      _serializeStack.RemoveAt(_serializeStack.Count - 1);
 
561
 
 
562
      OnSerialized(writer, contract, values.UnderlyingCollection);
 
563
    }
 
564
 
 
565
    private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
566
    {
 
567
      OnSerializing(writer, contract, values);
 
568
 
 
569
      _serializeStack.Add(values);
 
570
 
 
571
      bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty);
 
572
 
 
573
      SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]);
 
574
 
 
575
      if (hasWrittenMetadataObject)
 
576
        writer.WriteEndObject();
 
577
 
 
578
      _serializeStack.RemoveAt(_serializeStack.Count - 1);
 
579
 
 
580
      OnSerialized(writer, contract, values);
 
581
    }
 
582
 
 
583
    private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, int initialDepth, int[] indices)
 
584
    {
 
585
      int dimension = indices.Length;
 
586
      int[] newIndices = new int[dimension + 1];
 
587
      for (int i = 0; i < dimension; i++)
 
588
      {
 
589
        newIndices[i] = indices[i];
 
590
      }
 
591
 
 
592
      writer.WriteStartArray();
 
593
 
 
594
      for (int i = 0; i < values.GetLength(dimension); i++)
 
595
      {
 
596
        newIndices[dimension] = i;
 
597
        bool isTopLevel = (newIndices.Length == values.Rank);
 
598
 
 
599
        if (isTopLevel)
 
600
        {
 
601
          object value = values.GetValue(newIndices);
 
602
 
 
603
          try
 
604
          {
 
605
            JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
 
606
 
 
607
            if (ShouldWriteReference(value, null, valueContract, contract, member))
 
608
            {
 
609
              WriteReference(writer, value);
 
610
            }
 
611
            else
 
612
            {
 
613
              if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
 
614
              {
 
615
                SerializeValue(writer, value, valueContract, null, contract, member);
 
616
              }
 
617
            }
 
618
          }
 
619
          catch (Exception ex)
 
620
          {
 
621
            if (IsErrorHandled(values, contract, i, null, writer.ContainerPath, ex))
 
622
              HandleError(writer, initialDepth + 1);
 
623
            else
 
624
              throw;
 
625
          }
 
626
        }
 
627
        else
 
628
        {
 
629
          SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, newIndices);
 
630
        }
 
631
      }
 
632
 
 
633
      writer.WriteEndArray();
 
634
    }
 
635
 
 
636
    private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
 
637
    {
 
638
      bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
 
639
      bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
 
640
      bool writeMetadataObject = isReference || includeTypeDetails;
 
641
 
 
642
      if (writeMetadataObject)
 
643
      {
 
644
        writer.WriteStartObject();
 
645
 
 
646
        if (isReference)
 
647
        {
 
648
          WriteReferenceIdProperty(writer, contract.UnderlyingType, values);
 
649
        }
 
650
        if (includeTypeDetails)
 
651
        {
 
652
          WriteTypeProperty(writer, values.GetType());
 
653
        }
 
654
        writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName);
 
655
      }
 
656
 
 
657
      if (contract.ItemContract == null)
 
658
        contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof (object));
 
659
 
 
660
      return writeMetadataObject;
 
661
    }
 
662
 
 
663
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
 
664
#if !(NET20 || NET35)
 
665
    [SecuritySafeCritical]
 
666
#endif
 
667
    private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
668
    {
 
669
      if (!JsonTypeReflector.FullyTrusted)
 
670
      {
 
671
        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.
 
672
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);
 
673
      }
 
674
 
 
675
      OnSerializing(writer, contract, value);
 
676
      _serializeStack.Add(value);
 
677
 
 
678
      WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
 
679
 
 
680
      SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter());
 
681
      value.GetObjectData(serializationInfo, Serializer.Context);
 
682
 
 
683
      foreach (SerializationEntry serializationEntry in serializationInfo)
 
684
      {
 
685
        JsonContract valueContract = GetContractSafe(serializationEntry.Value);
 
686
 
 
687
        if (CheckForCircularReference(writer, serializationEntry.Value, null, valueContract, contract, member))
 
688
        {
 
689
          writer.WritePropertyName(serializationEntry.Name);
 
690
          SerializeValue(writer, serializationEntry.Value, valueContract, null, contract, member);
 
691
        }
 
692
      }
 
693
 
 
694
      writer.WriteEndObject();
 
695
 
 
696
      _serializeStack.RemoveAt(_serializeStack.Count - 1);
 
697
      OnSerialized(writer, contract, value);
 
698
    }
 
699
#endif
 
700
 
 
701
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
 
702
    private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
703
    {
 
704
      OnSerializing(writer, contract, value);
 
705
      _serializeStack.Add(value);
 
706
 
 
707
      WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
 
708
 
 
709
      int initialDepth = writer.Top;
 
710
 
 
711
      foreach (JsonProperty property in contract.Properties)
 
712
      {
 
713
        // only write non-dynamic properties that have an explicit attribute
 
714
        if (property.HasMemberAttribute)
 
715
        {
 
716
          try
 
717
          {
 
718
            object memberValue;
 
719
            JsonContract memberContract;
 
720
 
 
721
            if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
 
722
              continue;
 
723
 
 
724
            writer.WritePropertyName(property.PropertyName);
 
725
            SerializeValue(writer, memberValue, memberContract, property, contract, member);
 
726
          }
 
727
          catch (Exception ex)
 
728
          {
 
729
            if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex))
 
730
              HandleError(writer, initialDepth);
 
731
            else
 
732
              throw;
 
733
          }
 
734
        }
 
735
      }
 
736
 
 
737
      foreach (string memberName in value.GetDynamicMemberNames())
 
738
      {
 
739
        object memberValue;
 
740
        if (value.TryGetMember(memberName, out memberValue))
 
741
        {
 
742
          try
 
743
          {
 
744
            JsonContract valueContract = GetContractSafe(memberValue);
 
745
 
 
746
            if (CheckForCircularReference(writer, memberValue, null, valueContract, contract, member))
 
747
            {
 
748
              string resolvedPropertyName = (contract.PropertyNameResolver != null)
 
749
                                              ? contract.PropertyNameResolver(memberName)
 
750
                                              : memberName;
 
751
 
 
752
              writer.WritePropertyName(resolvedPropertyName);
 
753
              SerializeValue(writer, memberValue, valueContract, null, contract, member);
 
754
            }
 
755
          }
 
756
          catch (Exception ex)
 
757
          {
 
758
            if (IsErrorHandled(value, contract, memberName, null, writer.ContainerPath, ex))
 
759
              HandleError(writer, initialDepth);
 
760
            else
 
761
              throw;
 
762
          }
 
763
        }
 
764
      }
 
765
 
 
766
      writer.WriteEndObject();
 
767
 
 
768
      _serializeStack.RemoveAt(_serializeStack.Count - 1);
 
769
      OnSerialized(writer, contract, value);
 
770
    }
 
771
#endif
 
772
 
 
773
    private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
 
774
    {
 
775
      TypeNameHandling resolvedTypeNameHandling =
 
776
        ((member != null) ? member.TypeNameHandling : null)
 
777
        ?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null)
 
778
        ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
 
779
        ?? Serializer.TypeNameHandling;
 
780
 
 
781
      if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag))
 
782
        return true;
 
783
 
 
784
      // 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)
 
785
      if (HasFlag(resolvedTypeNameHandling, TypeNameHandling.Auto))
 
786
      {
 
787
        if (member != null)
 
788
        {
 
789
          if (contract.UnderlyingType != member.PropertyContract.CreatedType)
 
790
            return true;
 
791
        }
 
792
        else if (containerContract != null && containerContract.ItemContract != null)
 
793
        {
 
794
          if (contract.UnderlyingType != containerContract.ItemContract.CreatedType)
 
795
            return true;
 
796
        }
 
797
      }
 
798
 
 
799
      return false;
 
800
    }
 
801
 
 
802
    private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
 
803
    {
 
804
      OnSerializing(writer, contract, values.UnderlyingDictionary);
 
805
      _serializeStack.Add(values.UnderlyingDictionary);
 
806
 
 
807
      WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionContract, containerProperty);
 
808
 
 
809
      if (contract.ItemContract == null)
 
810
        contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
 
811
 
 
812
      int initialDepth = writer.Top;
 
813
 
 
814
      // Mono Unity 3.0 fix
 
815
      IWrappedDictionary d = values;
 
816
 
 
817
      foreach (DictionaryEntry entry in d)
 
818
      {
 
819
        string propertyName = GetPropertyName(entry);
 
820
 
 
821
        propertyName = (contract.PropertyNameResolver != null)
 
822
                         ? contract.PropertyNameResolver(propertyName)
 
823
                         : propertyName;
 
824
 
 
825
        try
 
826
        {
 
827
          object value = entry.Value;
 
828
          JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
 
829
 
 
830
          if (ShouldWriteReference(value, null, valueContract, contract, member))
 
831
          {
 
832
            writer.WritePropertyName(propertyName);
 
833
            WriteReference(writer, value);
 
834
          }
 
835
          else
 
836
          {
 
837
            if (!CheckForCircularReference(writer, value, null, valueContract, contract, member))
 
838
              continue;
 
839
 
 
840
            writer.WritePropertyName(propertyName);
 
841
 
 
842
            SerializeValue(writer, value, valueContract, null, contract, member);
 
843
          }
 
844
        }
 
845
        catch (Exception ex)
 
846
        {
 
847
          if (IsErrorHandled(values.UnderlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex))
 
848
            HandleError(writer, initialDepth);
 
849
          else
 
850
            throw;
 
851
        }
 
852
      }
 
853
 
 
854
      writer.WriteEndObject();
 
855
 
 
856
      _serializeStack.RemoveAt(_serializeStack.Count - 1);
 
857
 
 
858
      OnSerialized(writer, contract, values.UnderlyingDictionary);
 
859
    }
 
860
 
 
861
    private string GetPropertyName(DictionaryEntry entry)
 
862
    {
 
863
      string propertyName;
 
864
 
 
865
      if (ConvertUtils.IsConvertible(entry.Key))
 
866
        return Convert.ToString(entry.Key, CultureInfo.InvariantCulture);
 
867
      else if (TryConvertToString(entry.Key, entry.Key.GetType(), out propertyName))
 
868
        return propertyName;
 
869
      else
 
870
        return entry.Key.ToString();
 
871
    }
 
872
 
 
873
    private void HandleError(JsonWriter writer, int initialDepth)
 
874
    {
 
875
      ClearErrorContext();
 
876
 
 
877
      if (writer.WriteState == WriteState.Property)
 
878
        writer.WriteNull();
 
879
 
 
880
      while (writer.Top > initialDepth)
 
881
      {
 
882
        writer.WriteEnd();
 
883
      }
 
884
    }
 
885
 
 
886
    private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target)
 
887
    {
 
888
      if (property.ShouldSerialize == null)
 
889
        return true;
 
890
 
 
891
      bool shouldSerialize = property.ShouldSerialize(target);
 
892
 
 
893
      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
 
894
        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "ShouldSerialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, shouldSerialize)), null);
 
895
 
 
896
      return shouldSerialize;
 
897
    }
 
898
 
 
899
    private bool IsSpecified(JsonWriter writer, JsonProperty property, object target)
 
900
    {
 
901
      if (property.GetIsSpecified == null)
 
902
        return true;
 
903
 
 
904
      bool isSpecified = property.GetIsSpecified(target);
 
905
 
 
906
      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
 
907
        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "IsSpecified result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, isSpecified)), null);
 
908
 
 
909
      return isSpecified;
 
910
    }
 
911
  }
 
912
}
 
 
b'\\ No newline at end of file'