2
// Copyright (c) 2007 James Newton-King
4
// Permission is hereby granted, free of charge, to any person
5
// obtaining a copy of this software and associated documentation
6
// files (the "Software"), to deal in the Software without
7
// restriction, including without limitation the rights to use,
8
// copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the
10
// Software is furnished to do so, subject to the following
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
// OTHER DEALINGS IN THE SOFTWARE.
27
using System.Collections.Generic;
31
using Newtonsoft.Json.Utilities;
32
using Newtonsoft.Json.Linq;
33
using System.Globalization;
35
namespace Newtonsoft.Json
38
/// Specifies the state of the <see cref="JsonWriter"/>.
40
public enum WriteState
43
/// An exception has been thrown, which has left the <see cref="JsonWriter"/> in an invalid state.
44
/// You may call the <see cref="JsonWriter.Close"/> method to put the <see cref="JsonWriter"/> in the <c>Closed</c> state.
45
/// Any other <see cref="JsonWriter"/> method calls results in an <see cref="InvalidOperationException"/> being thrown.
49
/// The <see cref="JsonWriter.Close"/> method has been called.
53
/// An object is being written.
57
/// A array is being written.
61
/// A constructor is being written.
65
/// A property is being written.
69
/// A write method has not been called.
75
/// Specifies formatting options for the <see cref="JsonTextWriter"/>.
77
public enum Formatting
80
/// No special formatting is applied. This is the default.
84
/// Causes child objects to be indented according to the <see cref="JsonTextWriter.Indentation"/> and <see cref="JsonTextWriter.IndentChar"/> settings.
90
/// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
92
public abstract class JsonWriter : IDisposable
109
// array that gives a new state based on the current state an the token being written
110
private static readonly State[][] stateArray = new[] {
111
// Start PropertyName ObjectStart Object ArrayStart Array ConstructorStart Constructor Closed Error
113
/* None */new[]{ State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
114
/* StartObject */new[]{ State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.Error, State.Error },
115
/* StartArray */new[]{ State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.Error, State.Error },
116
/* StartConstructor */new[]{ State.ConstructorStart, State.ConstructorStart, State.Error, State.Error, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error, State.Error },
117
/* StartProperty */new[]{ State.Property, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
118
/* Comment */new[]{ State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
119
/* Raw */new[]{ State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
120
/* Value */new[]{ State.Start, State.Object, State.Error, State.Error, State.Array, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
125
private readonly List<JTokenType> _stack;
126
private State _currentState;
127
private Formatting _formatting;
132
/// <value>The top.</value>
133
protected internal int Top
139
/// Gets the state of the writer.
141
public WriteState WriteState
145
switch (_currentState)
148
return WriteState.Error;
150
return WriteState.Closed;
152
case State.ObjectStart:
153
return WriteState.Object;
155
case State.ArrayStart:
156
return WriteState.Array;
157
case State.Constructor:
158
case State.ConstructorStart:
159
return WriteState.Constructor;
161
return WriteState.Property;
163
return WriteState.Start;
165
throw new JsonWriterException("Invalid state: " + _currentState);
171
/// Indicates how the output is formatted.
173
public Formatting Formatting
175
get { return _formatting; }
176
set { _formatting = value; }
180
/// Creates an instance of the <c>JsonWriter</c> class.
184
_stack = new List<JTokenType>(8);
185
_stack.Add(JTokenType.None);
186
_currentState = State.Start;
187
_formatting = Formatting.None;
190
private void Push(JTokenType value)
193
if (_stack.Count <= _top)
196
_stack[_top] = value;
199
private JTokenType Pop()
201
JTokenType value = Peek();
207
private JTokenType Peek()
213
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
215
public abstract void Flush();
218
/// Closes this stream and the underlying stream.
220
public virtual void Close()
226
/// Writes the beginning of a Json object.
228
public virtual void WriteStartObject()
230
AutoComplete(JsonToken.StartObject);
231
Push(JTokenType.Object);
235
/// Writes the end of a Json object.
237
public void WriteEndObject()
239
AutoCompleteClose(JsonToken.EndObject);
243
/// Writes the beginning of a Json array.
245
public virtual void WriteStartArray()
247
AutoComplete(JsonToken.StartArray);
248
Push(JTokenType.Array);
252
/// Writes the end of an array.
254
public void WriteEndArray()
256
AutoCompleteClose(JsonToken.EndArray);
260
/// Writes the start of a constructor with the given name.
262
/// <param name="name">The name of the constructor.</param>
263
public virtual void WriteStartConstructor(string name)
265
AutoComplete(JsonToken.StartConstructor);
266
Push(JTokenType.Constructor);
270
/// Writes the end constructor.
272
public void WriteEndConstructor()
274
AutoCompleteClose(JsonToken.EndConstructor);
278
/// Writes the property name of a name/value pair on a Json object.
280
/// <param name="name">The name of the property.</param>
281
public virtual void WritePropertyName(string name)
283
AutoComplete(JsonToken.PropertyName);
287
/// Writes the end of the current Json object or array.
289
public void WriteEnd()
295
/// Writes the current <see cref="JsonReader"/> token.
297
/// <param name="reader">The <see cref="JsonReader"/> to read the token from.</param>
298
public void WriteToken(JsonReader reader)
300
ValidationUtils.ArgumentNotNull(reader, "reader");
304
if (reader.TokenType == JsonToken.None)
306
else if (!IsStartToken(reader.TokenType))
307
initialDepth = reader.Depth + 1;
309
initialDepth = reader.Depth;
311
WriteToken(reader, initialDepth);
314
internal void WriteToken(JsonReader reader, int initialDepth)
318
switch (reader.TokenType)
323
case JsonToken.StartObject:
326
case JsonToken.StartArray:
329
case JsonToken.StartConstructor:
330
string constructorName = reader.Value.ToString();
331
// write a JValue date when the constructor is for a date
332
if (string.Compare(constructorName, "Date", StringComparison.Ordinal) == 0)
333
WriteConstructorDate(reader);
335
WriteStartConstructor(reader.Value.ToString());
337
case JsonToken.PropertyName:
338
WritePropertyName(reader.Value.ToString());
340
case JsonToken.Comment:
341
WriteComment(reader.Value.ToString());
343
case JsonToken.Integer:
344
WriteValue((long)reader.Value);
346
case JsonToken.Float:
347
WriteValue((double)reader.Value);
349
case JsonToken.String:
350
WriteValue(reader.Value.ToString());
352
case JsonToken.Boolean:
353
WriteValue((bool)reader.Value);
358
case JsonToken.Undefined:
361
case JsonToken.EndObject:
364
case JsonToken.EndArray:
367
case JsonToken.EndConstructor:
368
WriteEndConstructor();
371
WriteValue((DateTime)reader.Value);
374
WriteRawValue((string)reader.Value);
376
case JsonToken.Bytes:
377
WriteValue((byte[])reader.Value);
380
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", reader.TokenType, "Unexpected token type.");
384
// stop if we have reached the end of the token being read
385
initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0)
389
private void WriteConstructorDate(JsonReader reader)
392
throw new Exception("Unexpected end while reading date constructor.");
393
if (reader.TokenType != JsonToken.Integer)
394
throw new Exception("Unexpected token while reading date constructor. Expected Integer, got " + reader.TokenType);
396
long ticks = (long)reader.Value;
397
DateTime date = JsonConvert.ConvertJavaScriptTicksToDateTime(ticks);
400
throw new Exception("Unexpected end while reading date constructor.");
401
if (reader.TokenType != JsonToken.EndConstructor)
402
throw new Exception("Unexpected token while reading date constructor. Expected EndConstructor, got " + reader.TokenType);
407
private bool IsEndToken(JsonToken token)
411
case JsonToken.EndObject:
412
case JsonToken.EndArray:
413
case JsonToken.EndConstructor:
420
private bool IsStartToken(JsonToken token)
424
case JsonToken.StartObject:
425
case JsonToken.StartArray:
426
case JsonToken.StartConstructor:
433
private void WriteEnd(JTokenType type)
437
case JTokenType.Object:
440
case JTokenType.Array:
443
case JTokenType.Constructor:
444
WriteEndConstructor();
447
throw new JsonWriterException("Unexpected type when writing end: " + type);
451
private void AutoCompleteAll()
459
private JTokenType GetTypeForCloseToken(JsonToken token)
463
case JsonToken.EndObject:
464
return JTokenType.Object;
465
case JsonToken.EndArray:
466
return JTokenType.Array;
467
case JsonToken.EndConstructor:
468
return JTokenType.Constructor;
470
throw new JsonWriterException("No type for token: " + token);
474
private JsonToken GetCloseTokenForType(JTokenType type)
478
case JTokenType.Object:
479
return JsonToken.EndObject;
480
case JTokenType.Array:
481
return JsonToken.EndArray;
482
case JTokenType.Constructor:
483
return JsonToken.EndConstructor;
485
throw new JsonWriterException("No close token for type: " + type);
489
private void AutoCompleteClose(JsonToken tokenBeingClosed)
491
// write closing symbol and calculate new state
493
int levelsToComplete = 0;
495
for (int i = 0; i < _top; i++)
497
int currentLevel = _top - i;
499
if (_stack[currentLevel] == GetTypeForCloseToken(tokenBeingClosed))
501
levelsToComplete = i + 1;
506
if (levelsToComplete == 0)
507
throw new JsonWriterException("No token to close.");
509
for (int i = 0; i < levelsToComplete; i++)
511
JsonToken token = GetCloseTokenForType(Pop());
513
if (_currentState != State.ObjectStart && _currentState != State.ArrayStart)
519
JTokenType currentLevelType = Peek();
521
switch (currentLevelType)
523
case JTokenType.Object:
524
_currentState = State.Object;
526
case JTokenType.Array:
527
_currentState = State.Array;
529
case JTokenType.Constructor:
530
_currentState = State.Array;
532
case JTokenType.None:
533
_currentState = State.Start;
536
throw new JsonWriterException("Unknown JsonType: " + currentLevelType);
541
/// Writes the specified end token.
543
/// <param name="token">The end token to write.</param>
544
protected virtual void WriteEnd(JsonToken token)
549
/// Writes indent characters.
551
protected virtual void WriteIndent()
556
/// Writes the JSON value delimiter.
558
protected virtual void WriteValueDelimiter()
563
/// Writes an indent space.
565
protected virtual void WriteIndentSpace()
569
internal void AutoComplete(JsonToken tokenBeingWritten)
573
switch (tokenBeingWritten)
576
token = (int)tokenBeingWritten;
578
case JsonToken.Integer:
579
case JsonToken.Float:
580
case JsonToken.String:
581
case JsonToken.Boolean:
583
case JsonToken.Undefined:
585
case JsonToken.Bytes:
586
// a value is being written
591
// gets new state based on the current state and what is being written
592
State newState = stateArray[token][(int)_currentState];
594
if (newState == State.Error)
595
throw new JsonWriterException("Token {0} in state {1} would result in an invalid JavaScript object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()));
597
if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment)
599
WriteValueDelimiter();
601
else if (_currentState == State.Property)
603
if (_formatting == Formatting.Indented)
607
WriteState writeState = WriteState;
609
// don't indent a property when it is the first token to be written (i.e. at the start)
610
if ((tokenBeingWritten == JsonToken.PropertyName && writeState != WriteState.Start) ||
611
writeState == WriteState.Array || writeState == WriteState.Constructor)
616
_currentState = newState;
619
#region WriteValue methods
621
/// Writes a null value.
623
public virtual void WriteNull()
625
AutoComplete(JsonToken.Null);
629
/// Writes an undefined value.
631
public virtual void WriteUndefined()
633
AutoComplete(JsonToken.Undefined);
637
/// Writes raw JSON without changing the writer's state.
639
/// <param name="json">The raw JSON to write.</param>
640
public virtual void WriteRaw(string json)
645
/// Writes raw JSON where a value is expected and updates the writer's state.
647
/// <param name="json">The raw JSON to write.</param>
648
public virtual void WriteRawValue(string json)
650
// hack. want writer to change state as if a value had been written
651
AutoComplete(JsonToken.Undefined);
656
/// Writes a <see cref="String"/> value.
658
/// <param name="value">The <see cref="String"/> value to write.</param>
659
public virtual void WriteValue(string value)
661
AutoComplete(JsonToken.String);
665
/// Writes a <see cref="Int32"/> value.
667
/// <param name="value">The <see cref="Int32"/> value to write.</param>
668
public virtual void WriteValue(int value)
670
AutoComplete(JsonToken.Integer);
674
/// Writes a <see cref="UInt32"/> value.
676
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
677
[CLSCompliant(false)]
678
public virtual void WriteValue(uint value)
680
AutoComplete(JsonToken.Integer);
684
/// Writes a <see cref="Int64"/> value.
686
/// <param name="value">The <see cref="Int64"/> value to write.</param>
687
public virtual void WriteValue(long value)
689
AutoComplete(JsonToken.Integer);
693
/// Writes a <see cref="UInt64"/> value.
695
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
696
[CLSCompliant(false)]
697
public virtual void WriteValue(ulong value)
699
AutoComplete(JsonToken.Integer);
703
/// Writes a <see cref="Single"/> value.
705
/// <param name="value">The <see cref="Single"/> value to write.</param>
706
public virtual void WriteValue(float value)
708
AutoComplete(JsonToken.Float);
712
/// Writes a <see cref="Double"/> value.
714
/// <param name="value">The <see cref="Double"/> value to write.</param>
715
public virtual void WriteValue(double value)
717
AutoComplete(JsonToken.Float);
721
/// Writes a <see cref="Boolean"/> value.
723
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
724
public virtual void WriteValue(bool value)
726
AutoComplete(JsonToken.Boolean);
730
/// Writes a <see cref="Int16"/> value.
732
/// <param name="value">The <see cref="Int16"/> value to write.</param>
733
public virtual void WriteValue(short value)
735
AutoComplete(JsonToken.Integer);
739
/// Writes a <see cref="UInt16"/> value.
741
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
742
[CLSCompliant(false)]
743
public virtual void WriteValue(ushort value)
745
AutoComplete(JsonToken.Integer);
749
/// Writes a <see cref="Char"/> value.
751
/// <param name="value">The <see cref="Char"/> value to write.</param>
752
public virtual void WriteValue(char value)
754
AutoComplete(JsonToken.String);
758
/// Writes a <see cref="Byte"/> value.
760
/// <param name="value">The <see cref="Byte"/> value to write.</param>
761
public virtual void WriteValue(byte value)
763
AutoComplete(JsonToken.Integer);
767
/// Writes a <see cref="SByte"/> value.
769
/// <param name="value">The <see cref="SByte"/> value to write.</param>
770
[CLSCompliant(false)]
771
public virtual void WriteValue(sbyte value)
773
AutoComplete(JsonToken.Integer);
777
/// Writes a <see cref="Decimal"/> value.
779
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
780
public virtual void WriteValue(decimal value)
782
AutoComplete(JsonToken.Float);
786
/// Writes a <see cref="DateTime"/> value.
788
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
789
public virtual void WriteValue(DateTime value)
791
AutoComplete(JsonToken.Date);
794
#if !PocketPC && !NET20
796
/// Writes a <see cref="DateTimeOffset"/> value.
798
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
799
public virtual void WriteValue(DateTimeOffset value)
801
AutoComplete(JsonToken.Date);
806
/// Writes a <see cref="Nullable{Int32}"/> value.
808
/// <param name="value">The <see cref="Nullable{Int32}"/> value to write.</param>
809
public virtual void WriteValue(int? value)
814
WriteValue(value.Value);
818
/// Writes a <see cref="Nullable{UInt32}"/> value.
820
/// <param name="value">The <see cref="Nullable{UInt32}"/> value to write.</param>
821
[CLSCompliant(false)]
822
public virtual void WriteValue(uint? value)
827
WriteValue(value.Value);
831
/// Writes a <see cref="Nullable{Int64}"/> value.
833
/// <param name="value">The <see cref="Nullable{Int64}"/> value to write.</param>
834
public virtual void WriteValue(long? value)
839
WriteValue(value.Value);
843
/// Writes a <see cref="Nullable{UInt64}"/> value.
845
/// <param name="value">The <see cref="Nullable{UInt64}"/> value to write.</param>
846
[CLSCompliant(false)]
847
public virtual void WriteValue(ulong? value)
852
WriteValue(value.Value);
856
/// Writes a <see cref="Nullable{Single}"/> value.
858
/// <param name="value">The <see cref="Nullable{Single}"/> value to write.</param>
859
public virtual void WriteValue(float? value)
864
WriteValue(value.Value);
868
/// Writes a <see cref="Nullable{Double}"/> value.
870
/// <param name="value">The <see cref="Nullable{Double}"/> value to write.</param>
871
public virtual void WriteValue(double? value)
876
WriteValue(value.Value);
880
/// Writes a <see cref="Nullable{Boolean}"/> value.
882
/// <param name="value">The <see cref="Nullable{Boolean}"/> value to write.</param>
883
public virtual void WriteValue(bool? value)
888
WriteValue(value.Value);
892
/// Writes a <see cref="Nullable{Int16}"/> value.
894
/// <param name="value">The <see cref="Nullable{Int16}"/> value to write.</param>
895
public virtual void WriteValue(short? value)
900
WriteValue(value.Value);
904
/// Writes a <see cref="Nullable{UInt16}"/> value.
906
/// <param name="value">The <see cref="Nullable{UInt16}"/> value to write.</param>
907
[CLSCompliant(false)]
908
public virtual void WriteValue(ushort? value)
913
WriteValue(value.Value);
917
/// Writes a <see cref="Nullable{Char}"/> value.
919
/// <param name="value">The <see cref="Nullable{Char}"/> value to write.</param>
920
public virtual void WriteValue(char? value)
925
WriteValue(value.Value);
929
/// Writes a <see cref="Nullable{Byte}"/> value.
931
/// <param name="value">The <see cref="Nullable{Byte}"/> value to write.</param>
932
public virtual void WriteValue(byte? value)
937
WriteValue(value.Value);
941
/// Writes a <see cref="Nullable{SByte}"/> value.
943
/// <param name="value">The <see cref="Nullable{SByte}"/> value to write.</param>
944
[CLSCompliant(false)]
945
public virtual void WriteValue(sbyte? value)
950
WriteValue(value.Value);
954
/// Writes a <see cref="Nullable{Decimal}"/> value.
956
/// <param name="value">The <see cref="Nullable{Decimal}"/> value to write.</param>
957
public virtual void WriteValue(decimal? value)
962
WriteValue(value.Value);
966
/// Writes a <see cref="Nullable{DateTime}"/> value.
968
/// <param name="value">The <see cref="Nullable{DateTime}"/> value to write.</param>
969
public virtual void WriteValue(DateTime? value)
974
WriteValue(value.Value);
977
#if !PocketPC && !NET20
979
/// Writes a <see cref="Nullable{DateTimeOffset}"/> value.
981
/// <param name="value">The <see cref="Nullable{DateTimeOffset}"/> value to write.</param>
982
public virtual void WriteValue(DateTimeOffset? value)
987
WriteValue(value.Value);
992
/// Writes a <see cref="T:Byte[]"/> value.
994
/// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
995
public virtual void WriteValue(byte[] value)
1000
AutoComplete(JsonToken.Bytes);
1004
/// Writes a <see cref="Object"/> value.
1005
/// An error will raised if the value cannot be written as a single JSON token.
1007
/// <param name="value">The <see cref="Object"/> value to write.</param>
1008
public virtual void WriteValue(object value)
1015
else if (value is IConvertible)
1017
IConvertible convertible = value as IConvertible;
1019
switch (convertible.GetTypeCode())
1021
case TypeCode.String:
1022
WriteValue(convertible.ToString(CultureInfo.InvariantCulture));
1025
WriteValue(convertible.ToChar(CultureInfo.InvariantCulture));
1027
case TypeCode.Boolean:
1028
WriteValue(convertible.ToBoolean(CultureInfo.InvariantCulture));
1030
case TypeCode.SByte:
1031
WriteValue(convertible.ToSByte(CultureInfo.InvariantCulture));
1033
case TypeCode.Int16:
1034
WriteValue(convertible.ToInt16(CultureInfo.InvariantCulture));
1036
case TypeCode.UInt16:
1037
WriteValue(convertible.ToUInt16(CultureInfo.InvariantCulture));
1039
case TypeCode.Int32:
1040
WriteValue(convertible.ToInt32(CultureInfo.InvariantCulture));
1043
WriteValue(convertible.ToByte(CultureInfo.InvariantCulture));
1045
case TypeCode.UInt32:
1046
WriteValue(convertible.ToUInt32(CultureInfo.InvariantCulture));
1048
case TypeCode.Int64:
1049
WriteValue(convertible.ToInt64(CultureInfo.InvariantCulture));
1051
case TypeCode.UInt64:
1052
WriteValue(convertible.ToUInt64(CultureInfo.InvariantCulture));
1054
case TypeCode.Single:
1055
WriteValue(convertible.ToSingle(CultureInfo.InvariantCulture));
1057
case TypeCode.Double:
1058
WriteValue(convertible.ToDouble(CultureInfo.InvariantCulture));
1060
case TypeCode.DateTime:
1061
WriteValue(convertible.ToDateTime(CultureInfo.InvariantCulture));
1063
case TypeCode.Decimal:
1064
WriteValue(convertible.ToDecimal(CultureInfo.InvariantCulture));
1066
case TypeCode.DBNull:
1071
#if !PocketPC && !NET20
1072
else if (value is DateTimeOffset)
1074
WriteValue((DateTimeOffset)value);
1078
else if (value is byte[])
1080
WriteValue((byte[])value);
1084
throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
1089
/// Writes out a comment <code>/*...*/</code> containing the specified text.
1091
/// <param name="text">Text to place inside the comment.</param>
1092
public virtual void WriteComment(string text)
1094
AutoComplete(JsonToken.Comment);
1098
/// Writes out the given white space.
1100
/// <param name="ws">The string of white space characters.</param>
1101
public virtual void WriteWhitespace(string ws)
1105
if (!StringUtils.IsWhiteSpace(ws))
1106
throw new JsonWriterException("Only white space characters should be used.");
1111
void IDisposable.Dispose()
1116
private void Dispose(bool disposing)
1118
if (WriteState != WriteState.Closed)
2
// Copyright (c) 2007 James Newton-King
4
// Permission is hereby granted, free of charge, to any person
5
// obtaining a copy of this software and associated documentation
6
// files (the "Software"), to deal in the Software without
7
// restriction, including without limitation the rights to use,
8
// copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the
10
// Software is furnished to do so, subject to the following
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
// OTHER DEALINGS IN THE SOFTWARE.
27
using System.Collections.Generic;
29
using Newtonsoft.Json.Utilities;
30
using System.Globalization;
32
using IConvertible = Newtonsoft.Json.Utilities.Convertible;
35
using Newtonsoft.Json.Utilities.LinqBridge;
40
namespace Newtonsoft.Json
43
/// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
45
public abstract class JsonWriter : IDisposable
62
// array that gives a new state based on the current state an the token being written
63
private static readonly State[][] StateArray;
65
internal static readonly State[][] StateArrayTempate = new[] {
66
// Start PropertyName ObjectStart Object ArrayStart Array ConstructorStart Constructor Closed Error
68
/* None */new[]{ State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
69
/* StartObject */new[]{ State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.Error, State.Error },
70
/* StartArray */new[]{ State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.Error, State.Error },
71
/* StartConstructor */new[]{ State.ConstructorStart, State.ConstructorStart, State.Error, State.Error, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error, State.Error },
72
/* StartProperty */new[]{ State.Property, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
73
/* Comment */new[]{ State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
74
/* Raw */new[]{ State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
75
/* Value (this will be copied) */new[]{ State.Start, State.Object, State.Error, State.Error, State.Array, State.Array, State.Constructor, State.Constructor, State.Error, State.Error }
78
internal static State[][] BuildStateArray()
80
var allStates = StateArrayTempate.ToList();
81
var errorStates = StateArrayTempate[0];
82
var valueStates = StateArrayTempate[7];
84
foreach (JsonToken valueToken in EnumUtils.GetValues(typeof(JsonToken)))
86
if (allStates.Count <= (int)valueToken)
90
case JsonToken.Integer:
92
case JsonToken.String:
93
case JsonToken.Boolean:
95
case JsonToken.Undefined:
98
allStates.Add(valueStates);
101
allStates.Add(errorStates);
107
return allStates.ToArray();
112
StateArray = BuildStateArray();
115
private readonly List<JsonPosition> _stack;
116
private JsonPosition _currentPosition;
117
private State _currentState;
118
private Formatting _formatting;
121
/// Gets or sets a value indicating whether the underlying stream or
122
/// <see cref="TextReader"/> should be closed when the writer is closed.
125
/// true to close the underlying stream or <see cref="TextReader"/> when
126
/// the writer is closed; otherwise false. The default is true.
128
public bool CloseOutput { get; set; }
133
/// <value>The top.</value>
134
protected internal int Top
138
int depth = _stack.Count;
139
if (Peek() != JsonContainerType.None)
146
internal string ContainerPath
150
if (_currentPosition.Type == JsonContainerType.None)
153
IEnumerable<JsonPosition> positions = (_currentPosition.InsideContainer())
155
: _stack.Concat(new[] { _currentPosition });
157
return JsonPosition.BuildPath(positions);
162
/// Gets the state of the writer.
164
public WriteState WriteState
168
switch (_currentState)
171
return WriteState.Error;
173
return WriteState.Closed;
175
case State.ObjectStart:
176
return WriteState.Object;
178
case State.ArrayStart:
179
return WriteState.Array;
180
case State.Constructor:
181
case State.ConstructorStart:
182
return WriteState.Constructor;
184
return WriteState.Property;
186
return WriteState.Start;
188
throw JsonWriterException.Create(this, "Invalid state: " + _currentState, null);
194
/// Gets the path of the writer.
200
if (_currentPosition.Type == JsonContainerType.None)
203
return JsonPosition.BuildPath(_stack.Concat(new[] { _currentPosition }));
207
private DateFormatHandling _dateFormatHandling;
208
private DateTimeZoneHandling _dateTimeZoneHandling;
211
/// Indicates how JSON text output is formatted.
213
public Formatting Formatting
215
get { return _formatting; }
216
set { _formatting = value; }
220
/// Get or set how dates are written to JSON text.
222
public DateFormatHandling DateFormatHandling
224
get { return _dateFormatHandling; }
225
set { _dateFormatHandling = value; }
229
/// Get or set how <see cref="DateTime"/> time zones are handling when writing JSON.
231
public DateTimeZoneHandling DateTimeZoneHandling
233
get { return _dateTimeZoneHandling; }
234
set { _dateTimeZoneHandling = value; }
238
/// Creates an instance of the <c>JsonWriter</c> class.
240
protected JsonWriter()
242
_stack = new List<JsonPosition>(4);
243
_currentState = State.Start;
244
_formatting = Formatting.None;
245
_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
250
private void UpdateScopeWithFinishedValue()
252
if (_currentPosition.Type == JsonContainerType.Array
253
|| _currentPosition.Type == JsonContainerType.Constructor)
255
if (_currentPosition.Position == null)
256
_currentPosition.Position = 0;
258
_currentPosition.Position++;
262
private void Push(JsonContainerType value)
264
UpdateScopeWithFinishedValue();
266
if (_currentPosition.Type == JsonContainerType.None)
268
_currentPosition.Type = value;
272
_stack.Add(_currentPosition);
273
var state = new JsonPosition
277
_currentPosition = state;
281
private JsonContainerType Pop()
283
JsonPosition oldPosition;
284
if (_stack.Count > 0)
286
oldPosition = _currentPosition;
287
_currentPosition = _stack[_stack.Count - 1];
288
_stack.RemoveAt(_stack.Count - 1);
292
oldPosition = _currentPosition;
293
_currentPosition = new JsonPosition();
296
return oldPosition.Type;
299
private JsonContainerType Peek()
301
return _currentPosition.Type;
305
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
307
public abstract void Flush();
310
/// Closes this stream and the underlying stream.
312
public virtual void Close()
318
/// Writes the beginning of a Json object.
320
public virtual void WriteStartObject()
322
AutoComplete(JsonToken.StartObject);
323
Push(JsonContainerType.Object);
327
/// Writes the end of a Json object.
329
public virtual void WriteEndObject()
331
AutoCompleteClose(JsonToken.EndObject);
335
/// Writes the beginning of a Json array.
337
public virtual void WriteStartArray()
339
AutoComplete(JsonToken.StartArray);
340
Push(JsonContainerType.Array);
344
/// Writes the end of an array.
346
public virtual void WriteEndArray()
348
AutoCompleteClose(JsonToken.EndArray);
352
/// Writes the start of a constructor with the given name.
354
/// <param name="name">The name of the constructor.</param>
355
public virtual void WriteStartConstructor(string name)
357
AutoComplete(JsonToken.StartConstructor);
358
Push(JsonContainerType.Constructor);
362
/// Writes the end constructor.
364
public virtual void WriteEndConstructor()
366
AutoCompleteClose(JsonToken.EndConstructor);
370
/// Writes the property name of a name/value pair on a Json object.
372
/// <param name="name">The name of the property.</param>
373
public virtual void WritePropertyName(string name)
375
_currentPosition.PropertyName = name;
376
AutoComplete(JsonToken.PropertyName);
380
/// Writes the end of the current Json object or array.
382
public virtual void WriteEnd()
388
/// Writes the current <see cref="JsonReader"/> token.
390
/// <param name="reader">The <see cref="JsonReader"/> to read the token from.</param>
391
public void WriteToken(JsonReader reader)
393
ValidationUtils.ArgumentNotNull(reader, "reader");
397
if (reader.TokenType == JsonToken.None)
399
else if (!IsStartToken(reader.TokenType))
400
initialDepth = reader.Depth + 1;
402
initialDepth = reader.Depth;
404
WriteToken(reader, initialDepth);
407
internal void WriteToken(JsonReader reader, int initialDepth)
411
switch (reader.TokenType)
416
case JsonToken.StartObject:
419
case JsonToken.StartArray:
422
case JsonToken.StartConstructor:
423
string constructorName = reader.Value.ToString();
424
// write a JValue date when the constructor is for a date
425
if (string.Equals(constructorName, "Date", StringComparison.Ordinal))
426
WriteConstructorDate(reader);
428
WriteStartConstructor(reader.Value.ToString());
430
case JsonToken.PropertyName:
431
WritePropertyName(reader.Value.ToString());
433
case JsonToken.Comment:
434
WriteComment(reader.Value.ToString());
436
case JsonToken.Integer:
437
WriteValue(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture));
439
case JsonToken.Float:
440
WriteValue(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture));
442
case JsonToken.String:
443
WriteValue(reader.Value.ToString());
445
case JsonToken.Boolean:
446
WriteValue(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
451
case JsonToken.Undefined:
454
case JsonToken.EndObject:
457
case JsonToken.EndArray:
460
case JsonToken.EndConstructor:
461
WriteEndConstructor();
464
WriteValue((DateTime)reader.Value);
467
WriteRawValue((string)reader.Value);
469
case JsonToken.Bytes:
470
WriteValue((byte[])reader.Value);
473
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", reader.TokenType, "Unexpected token type.");
477
// stop if we have reached the end of the token being read
478
initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0)
482
private void WriteConstructorDate(JsonReader reader)
485
throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null);
486
if (reader.TokenType != JsonToken.Integer)
487
throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null);
489
long ticks = (long)reader.Value;
490
DateTime date = JsonConvert.ConvertJavaScriptTicksToDateTime(ticks);
493
throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null);
494
if (reader.TokenType != JsonToken.EndConstructor)
495
throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected EndConstructor, got " + reader.TokenType, null);
500
private bool IsEndToken(JsonToken token)
504
case JsonToken.EndObject:
505
case JsonToken.EndArray:
506
case JsonToken.EndConstructor:
513
private bool IsStartToken(JsonToken token)
517
case JsonToken.StartObject:
518
case JsonToken.StartArray:
519
case JsonToken.StartConstructor:
526
private void WriteEnd(JsonContainerType type)
530
case JsonContainerType.Object:
533
case JsonContainerType.Array:
536
case JsonContainerType.Constructor:
537
WriteEndConstructor();
540
throw JsonWriterException.Create(this, "Unexpected type when writing end: " + type, null);
544
private void AutoCompleteAll()
552
private JsonContainerType GetTypeForCloseToken(JsonToken token)
556
case JsonToken.EndObject:
557
return JsonContainerType.Object;
558
case JsonToken.EndArray:
559
return JsonContainerType.Array;
560
case JsonToken.EndConstructor:
561
return JsonContainerType.Constructor;
563
throw JsonWriterException.Create(this, "No type for token: " + token, null);
567
private JsonToken GetCloseTokenForType(JsonContainerType type)
571
case JsonContainerType.Object:
572
return JsonToken.EndObject;
573
case JsonContainerType.Array:
574
return JsonToken.EndArray;
575
case JsonContainerType.Constructor:
576
return JsonToken.EndConstructor;
578
throw JsonWriterException.Create(this, "No close token for type: " + type, null);
582
private void AutoCompleteClose(JsonToken tokenBeingClosed)
584
// write closing symbol and calculate new state
585
int levelsToComplete = 0;
586
JsonContainerType type = GetTypeForCloseToken(tokenBeingClosed);
588
if (_currentPosition.Type == type)
590
levelsToComplete = 1;
595
for (int i = top; i >= 0; i--)
597
int currentLevel = top - i;
599
if (_stack[currentLevel].Type == type)
601
levelsToComplete = i + 2;
607
if (levelsToComplete == 0)
608
throw JsonWriterException.Create(this, "No token to close.", null);
610
for (int i = 0; i < levelsToComplete; i++)
612
JsonToken token = GetCloseTokenForType(Pop());
614
if (_currentState == State.Property)
617
if (_formatting == Formatting.Indented)
619
if (_currentState != State.ObjectStart && _currentState != State.ArrayStart)
625
JsonContainerType currentLevelType = Peek();
627
switch (currentLevelType)
629
case JsonContainerType.Object:
630
_currentState = State.Object;
632
case JsonContainerType.Array:
633
_currentState = State.Array;
635
case JsonContainerType.Constructor:
636
_currentState = State.Array;
638
case JsonContainerType.None:
639
_currentState = State.Start;
642
throw JsonWriterException.Create(this, "Unknown JsonType: " + currentLevelType, null);
648
/// Writes the specified end token.
650
/// <param name="token">The end token to write.</param>
651
protected virtual void WriteEnd(JsonToken token)
656
/// Writes indent characters.
658
protected virtual void WriteIndent()
663
/// Writes the JSON value delimiter.
665
protected virtual void WriteValueDelimiter()
670
/// Writes an indent space.
672
protected virtual void WriteIndentSpace()
676
internal void AutoComplete(JsonToken tokenBeingWritten)
678
if (tokenBeingWritten != JsonToken.StartObject
679
&& tokenBeingWritten != JsonToken.StartArray
680
&& tokenBeingWritten != JsonToken.StartConstructor)
681
UpdateScopeWithFinishedValue();
683
// gets new state based on the current state and what is being written
684
State newState = StateArray[(int)tokenBeingWritten][(int)_currentState];
686
if (newState == State.Error)
687
throw JsonWriterException.Create(this, "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()), null);
689
if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment)
691
WriteValueDelimiter();
693
else if (_currentState == State.Property)
695
if (_formatting == Formatting.Indented)
699
if (_formatting == Formatting.Indented)
701
WriteState writeState = WriteState;
703
// don't indent a property when it is the first token to be written (i.e. at the start)
704
if ((tokenBeingWritten == JsonToken.PropertyName && writeState != WriteState.Start) ||
705
writeState == WriteState.Array || writeState == WriteState.Constructor)
711
_currentState = newState;
714
#region WriteValue methods
716
/// Writes a null value.
718
public virtual void WriteNull()
720
AutoComplete(JsonToken.Null);
724
/// Writes an undefined value.
726
public virtual void WriteUndefined()
728
AutoComplete(JsonToken.Undefined);
732
/// Writes raw JSON without changing the writer's state.
734
/// <param name="json">The raw JSON to write.</param>
735
public virtual void WriteRaw(string json)
740
/// Writes raw JSON where a value is expected and updates the writer's state.
742
/// <param name="json">The raw JSON to write.</param>
743
public virtual void WriteRawValue(string json)
745
// hack. want writer to change state as if a value had been written
746
AutoComplete(JsonToken.Undefined);
751
/// Writes a <see cref="String"/> value.
753
/// <param name="value">The <see cref="String"/> value to write.</param>
754
public virtual void WriteValue(string value)
756
AutoComplete(JsonToken.String);
760
/// Writes a <see cref="Int32"/> value.
762
/// <param name="value">The <see cref="Int32"/> value to write.</param>
763
public virtual void WriteValue(int value)
765
AutoComplete(JsonToken.Integer);
769
/// Writes a <see cref="UInt32"/> value.
771
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
772
[CLSCompliant(false)]
773
public virtual void WriteValue(uint value)
775
AutoComplete(JsonToken.Integer);
779
/// Writes a <see cref="Int64"/> value.
781
/// <param name="value">The <see cref="Int64"/> value to write.</param>
782
public virtual void WriteValue(long value)
784
AutoComplete(JsonToken.Integer);
788
/// Writes a <see cref="UInt64"/> value.
790
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
791
[CLSCompliant(false)]
792
public virtual void WriteValue(ulong value)
794
AutoComplete(JsonToken.Integer);
798
/// Writes a <see cref="Single"/> value.
800
/// <param name="value">The <see cref="Single"/> value to write.</param>
801
public virtual void WriteValue(float value)
803
AutoComplete(JsonToken.Float);
807
/// Writes a <see cref="Double"/> value.
809
/// <param name="value">The <see cref="Double"/> value to write.</param>
810
public virtual void WriteValue(double value)
812
AutoComplete(JsonToken.Float);
816
/// Writes a <see cref="Boolean"/> value.
818
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
819
public virtual void WriteValue(bool value)
821
AutoComplete(JsonToken.Boolean);
825
/// Writes a <see cref="Int16"/> value.
827
/// <param name="value">The <see cref="Int16"/> value to write.</param>
828
public virtual void WriteValue(short value)
830
AutoComplete(JsonToken.Integer);
834
/// Writes a <see cref="UInt16"/> value.
836
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
837
[CLSCompliant(false)]
838
public virtual void WriteValue(ushort value)
840
AutoComplete(JsonToken.Integer);
844
/// Writes a <see cref="Char"/> value.
846
/// <param name="value">The <see cref="Char"/> value to write.</param>
847
public virtual void WriteValue(char value)
849
AutoComplete(JsonToken.String);
853
/// Writes a <see cref="Byte"/> value.
855
/// <param name="value">The <see cref="Byte"/> value to write.</param>
856
public virtual void WriteValue(byte value)
858
AutoComplete(JsonToken.Integer);
862
/// Writes a <see cref="SByte"/> value.
864
/// <param name="value">The <see cref="SByte"/> value to write.</param>
865
[CLSCompliant(false)]
866
public virtual void WriteValue(sbyte value)
868
AutoComplete(JsonToken.Integer);
872
/// Writes a <see cref="Decimal"/> value.
874
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
875
public virtual void WriteValue(decimal value)
877
AutoComplete(JsonToken.Float);
881
/// Writes a <see cref="DateTime"/> value.
883
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
884
public virtual void WriteValue(DateTime value)
886
AutoComplete(JsonToken.Date);
889
#if !PocketPC && !NET20
891
/// Writes a <see cref="DateTimeOffset"/> value.
893
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
894
public virtual void WriteValue(DateTimeOffset value)
896
AutoComplete(JsonToken.Date);
901
/// Writes a <see cref="Guid"/> value.
903
/// <param name="value">The <see cref="Guid"/> value to write.</param>
904
public virtual void WriteValue(Guid value)
906
AutoComplete(JsonToken.String);
910
/// Writes a <see cref="TimeSpan"/> value.
912
/// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
913
public virtual void WriteValue(TimeSpan value)
915
AutoComplete(JsonToken.String);
919
/// Writes a <see cref="Nullable{Int32}"/> value.
921
/// <param name="value">The <see cref="Nullable{Int32}"/> value to write.</param>
922
public virtual void WriteValue(int? value)
927
WriteValue(value.Value);
931
/// Writes a <see cref="Nullable{UInt32}"/> value.
933
/// <param name="value">The <see cref="Nullable{UInt32}"/> value to write.</param>
934
[CLSCompliant(false)]
935
public virtual void WriteValue(uint? value)
940
WriteValue(value.Value);
944
/// Writes a <see cref="Nullable{Int64}"/> value.
946
/// <param name="value">The <see cref="Nullable{Int64}"/> value to write.</param>
947
public virtual void WriteValue(long? value)
952
WriteValue(value.Value);
956
/// Writes a <see cref="Nullable{UInt64}"/> value.
958
/// <param name="value">The <see cref="Nullable{UInt64}"/> value to write.</param>
959
[CLSCompliant(false)]
960
public virtual void WriteValue(ulong? value)
965
WriteValue(value.Value);
969
/// Writes a <see cref="Nullable{Single}"/> value.
971
/// <param name="value">The <see cref="Nullable{Single}"/> value to write.</param>
972
public virtual void WriteValue(float? value)
977
WriteValue(value.Value);
981
/// Writes a <see cref="Nullable{Double}"/> value.
983
/// <param name="value">The <see cref="Nullable{Double}"/> value to write.</param>
984
public virtual void WriteValue(double? value)
989
WriteValue(value.Value);
993
/// Writes a <see cref="Nullable{Boolean}"/> value.
995
/// <param name="value">The <see cref="Nullable{Boolean}"/> value to write.</param>
996
public virtual void WriteValue(bool? value)
1001
WriteValue(value.Value);
1005
/// Writes a <see cref="Nullable{Int16}"/> value.
1007
/// <param name="value">The <see cref="Nullable{Int16}"/> value to write.</param>
1008
public virtual void WriteValue(short? value)
1013
WriteValue(value.Value);
1017
/// Writes a <see cref="Nullable{UInt16}"/> value.
1019
/// <param name="value">The <see cref="Nullable{UInt16}"/> value to write.</param>
1020
[CLSCompliant(false)]
1021
public virtual void WriteValue(ushort? value)
1026
WriteValue(value.Value);
1030
/// Writes a <see cref="Nullable{Char}"/> value.
1032
/// <param name="value">The <see cref="Nullable{Char}"/> value to write.</param>
1033
public virtual void WriteValue(char? value)
1038
WriteValue(value.Value);
1042
/// Writes a <see cref="Nullable{Byte}"/> value.
1044
/// <param name="value">The <see cref="Nullable{Byte}"/> value to write.</param>
1045
public virtual void WriteValue(byte? value)
1050
WriteValue(value.Value);
1054
/// Writes a <see cref="Nullable{SByte}"/> value.
1056
/// <param name="value">The <see cref="Nullable{SByte}"/> value to write.</param>
1057
[CLSCompliant(false)]
1058
public virtual void WriteValue(sbyte? value)
1063
WriteValue(value.Value);
1067
/// Writes a <see cref="Nullable{Decimal}"/> value.
1069
/// <param name="value">The <see cref="Nullable{Decimal}"/> value to write.</param>
1070
public virtual void WriteValue(decimal? value)
1075
WriteValue(value.Value);
1079
/// Writes a <see cref="Nullable{DateTime}"/> value.
1081
/// <param name="value">The <see cref="Nullable{DateTime}"/> value to write.</param>
1082
public virtual void WriteValue(DateTime? value)
1087
WriteValue(value.Value);
1090
#if !PocketPC && !NET20
1092
/// Writes a <see cref="Nullable{DateTimeOffset}"/> value.
1094
/// <param name="value">The <see cref="Nullable{DateTimeOffset}"/> value to write.</param>
1095
public virtual void WriteValue(DateTimeOffset? value)
1100
WriteValue(value.Value);
1105
/// Writes a <see cref="Nullable{Guid}"/> value.
1107
/// <param name="value">The <see cref="Nullable{Guid}"/> value to write.</param>
1108
public virtual void WriteValue(Guid? value)
1113
WriteValue(value.Value);
1117
/// Writes a <see cref="Nullable{TimeSpan}"/> value.
1119
/// <param name="value">The <see cref="Nullable{TimeSpan}"/> value to write.</param>
1120
public virtual void WriteValue(TimeSpan? value)
1125
WriteValue(value.Value);
1129
/// Writes a <see cref="T:Byte[]"/> value.
1131
/// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
1132
public virtual void WriteValue(byte[] value)
1137
AutoComplete(JsonToken.Bytes);
1141
/// Writes a <see cref="Uri"/> value.
1143
/// <param name="value">The <see cref="Uri"/> value to write.</param>
1144
public virtual void WriteValue(Uri value)
1149
AutoComplete(JsonToken.String);
1153
/// Writes a <see cref="Object"/> value.
1154
/// An error will raised if the value cannot be written as a single JSON token.
1156
/// <param name="value">The <see cref="Object"/> value to write.</param>
1157
public virtual void WriteValue(object value)
1164
else if (ConvertUtils.IsConvertible(value))
1166
IConvertible convertible = ConvertUtils.ToConvertible(value);
1168
switch (convertible.GetTypeCode())
1170
case TypeCode.String:
1171
WriteValue(convertible.ToString(CultureInfo.InvariantCulture));
1174
WriteValue(convertible.ToChar(CultureInfo.InvariantCulture));
1176
case TypeCode.Boolean:
1177
WriteValue(convertible.ToBoolean(CultureInfo.InvariantCulture));
1179
case TypeCode.SByte:
1180
WriteValue(convertible.ToSByte(CultureInfo.InvariantCulture));
1182
case TypeCode.Int16:
1183
WriteValue(convertible.ToInt16(CultureInfo.InvariantCulture));
1185
case TypeCode.UInt16:
1186
WriteValue(convertible.ToUInt16(CultureInfo.InvariantCulture));
1188
case TypeCode.Int32:
1189
WriteValue(convertible.ToInt32(CultureInfo.InvariantCulture));
1192
WriteValue(convertible.ToByte(CultureInfo.InvariantCulture));
1194
case TypeCode.UInt32:
1195
WriteValue(convertible.ToUInt32(CultureInfo.InvariantCulture));
1197
case TypeCode.Int64:
1198
WriteValue(convertible.ToInt64(CultureInfo.InvariantCulture));
1200
case TypeCode.UInt64:
1201
WriteValue(convertible.ToUInt64(CultureInfo.InvariantCulture));
1203
case TypeCode.Single:
1204
WriteValue(convertible.ToSingle(CultureInfo.InvariantCulture));
1206
case TypeCode.Double:
1207
WriteValue(convertible.ToDouble(CultureInfo.InvariantCulture));
1209
case TypeCode.DateTime:
1210
WriteValue(convertible.ToDateTime(CultureInfo.InvariantCulture));
1212
case TypeCode.Decimal:
1213
WriteValue(convertible.ToDecimal(CultureInfo.InvariantCulture));
1215
#if !(NETFX_CORE || PORTABLE)
1216
case TypeCode.DBNull:
1222
#if !PocketPC && !NET20
1223
else if (value is DateTimeOffset)
1225
WriteValue((DateTimeOffset)value);
1229
else if (value is byte[])
1231
WriteValue((byte[])value);
1234
else if (value is Guid)
1236
WriteValue((Guid)value);
1239
else if (value is Uri)
1241
WriteValue((Uri)value);
1244
else if (value is TimeSpan)
1246
WriteValue((TimeSpan)value);
1250
throw JsonWriterException.Create(this, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null);
1255
/// Writes out a comment <code>/*...*/</code> containing the specified text.
1257
/// <param name="text">Text to place inside the comment.</param>
1258
public virtual void WriteComment(string text)
1260
AutoComplete(JsonToken.Comment);
1264
/// Writes out the given white space.
1266
/// <param name="ws">The string of white space characters.</param>
1267
public virtual void WriteWhitespace(string ws)
1271
if (!StringUtils.IsWhiteSpace(ws))
1272
throw JsonWriterException.Create(this, "Only white space characters should be used.", null);
1277
void IDisposable.Dispose()
1282
private void Dispose(bool disposing)
1284
if (_currentState != State.Closed)
b'\\ No newline at end of file'