~ubuntu-branches/ubuntu/trusty/smuxi/trusty-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Mirco Bauer
  • Date: 2013-05-25 22:11:31 UTC
  • mfrom: (1.2.12)
  • Revision ID: package-import@ubuntu.com-20130525221131-nd2mc0kzubuwyx20
Tags: 0.8.11-1
* [22d13d5] Imported Upstream version 0.8.11
* [6d2b95a] Refreshed patches
* [89eb66e] Added ServiceStack libraries to smuxi-engine package
* [848ab10] Enable Campfire engine
* [c6dbdc7] Always build db4o for predictable build result
* [13ec489] Exclude OS X specific libraries from dh_clideps

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