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;
130 /// Gets or sets a value indicating whether the underlying stream or
131 /// <see cref="TextReader"/> should be closed when the writer is closed.
134 /// true to close the underlying stream or <see cref="TextReader"/> when
135 /// the writer is closed; otherwise false. The default is true.
137 public bool CloseOutput { get; set; }
142 /// <value>The top.</value>
143 protected internal int Top
149 /// Gets the state of the writer.
151 public WriteState WriteState
155 switch (_currentState)
158 return WriteState.Error;
160 return WriteState.Closed;
162 case State.ObjectStart:
163 return WriteState.Object;
165 case State.ArrayStart:
166 return WriteState.Array;
167 case State.Constructor:
168 case State.ConstructorStart:
169 return WriteState.Constructor;
171 return WriteState.Property;
173 return WriteState.Start;
175 throw new JsonWriterException("Invalid state: " + _currentState);
181 /// Indicates how the output is formatted.
183 public Formatting Formatting
185 get { return _formatting; }
186 set { _formatting = value; }
190 /// Creates an instance of the <c>JsonWriter</c> class.
192 protected JsonWriter()
194 _stack = new List<JTokenType>(8);
195 _stack.Add(JTokenType.None);
196 _currentState = State.Start;
197 _formatting = Formatting.None;
202 private void Push(JTokenType value)
205 if (_stack.Count <= _top)
208 _stack[_top] = value;
211 private JTokenType Pop()
213 JTokenType value = Peek();
219 private JTokenType Peek()
225 /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
227 public abstract void Flush();
230 /// Closes this stream and the underlying stream.
232 public virtual void Close()
238 /// Writes the beginning of a Json object.
240 public virtual void WriteStartObject()
242 AutoComplete(JsonToken.StartObject);
243 Push(JTokenType.Object);
247 /// Writes the end of a Json object.
249 public void WriteEndObject()
251 AutoCompleteClose(JsonToken.EndObject);
255 /// Writes the beginning of a Json array.
257 public virtual void WriteStartArray()
259 AutoComplete(JsonToken.StartArray);
260 Push(JTokenType.Array);
264 /// Writes the end of an array.
266 public void WriteEndArray()
268 AutoCompleteClose(JsonToken.EndArray);
272 /// Writes the start of a constructor with the given name.
274 /// <param name="name">The name of the constructor.</param>
275 public virtual void WriteStartConstructor(string name)
277 AutoComplete(JsonToken.StartConstructor);
278 Push(JTokenType.Constructor);
282 /// Writes the end constructor.
284 public void WriteEndConstructor()
286 AutoCompleteClose(JsonToken.EndConstructor);
290 /// Writes the property name of a name/value pair on a Json object.
292 /// <param name="name">The name of the property.</param>
293 public virtual void WritePropertyName(string name)
295 AutoComplete(JsonToken.PropertyName);
299 /// Writes the end of the current Json object or array.
301 public void WriteEnd()
307 /// Writes the current <see cref="JsonReader"/> token.
309 /// <param name="reader">The <see cref="JsonReader"/> to read the token from.</param>
310 public void WriteToken(JsonReader reader)
312 ValidationUtils.ArgumentNotNull(reader, "reader");
316 if (reader.TokenType == JsonToken.None)
318 else if (!IsStartToken(reader.TokenType))
319 initialDepth = reader.Depth + 1;
321 initialDepth = reader.Depth;
323 WriteToken(reader, initialDepth);
326 internal void WriteToken(JsonReader reader, int initialDepth)
330 switch (reader.TokenType)
335 case JsonToken.StartObject:
338 case JsonToken.StartArray:
341 case JsonToken.StartConstructor:
342 string constructorName = reader.Value.ToString();
343 // write a JValue date when the constructor is for a date
344 if (string.Compare(constructorName, "Date", StringComparison.Ordinal) == 0)
345 WriteConstructorDate(reader);
347 WriteStartConstructor(reader.Value.ToString());
349 case JsonToken.PropertyName:
350 WritePropertyName(reader.Value.ToString());
352 case JsonToken.Comment:
353 WriteComment(reader.Value.ToString());
355 case JsonToken.Integer:
356 WriteValue((long)reader.Value);
358 case JsonToken.Float:
359 WriteValue((double)reader.Value);
361 case JsonToken.String:
362 WriteValue(reader.Value.ToString());
364 case JsonToken.Boolean:
365 WriteValue((bool)reader.Value);
370 case JsonToken.Undefined:
373 case JsonToken.EndObject:
376 case JsonToken.EndArray:
379 case JsonToken.EndConstructor:
380 WriteEndConstructor();
383 WriteValue((DateTime)reader.Value);
386 WriteRawValue((string)reader.Value);
388 case JsonToken.Bytes:
389 WriteValue((byte[])reader.Value);
392 throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", reader.TokenType, "Unexpected token type.");
396 // stop if we have reached the end of the token being read
397 initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0)
401 private void WriteConstructorDate(JsonReader reader)
404 throw new Exception("Unexpected end while reading date constructor.");
405 if (reader.TokenType != JsonToken.Integer)
406 throw new Exception("Unexpected token while reading date constructor. Expected Integer, got " + reader.TokenType);
408 long ticks = (long)reader.Value;
409 DateTime date = JsonConvert.ConvertJavaScriptTicksToDateTime(ticks);
412 throw new Exception("Unexpected end while reading date constructor.");
413 if (reader.TokenType != JsonToken.EndConstructor)
414 throw new Exception("Unexpected token while reading date constructor. Expected EndConstructor, got " + reader.TokenType);
419 private bool IsEndToken(JsonToken token)
423 case JsonToken.EndObject:
424 case JsonToken.EndArray:
425 case JsonToken.EndConstructor:
432 private bool IsStartToken(JsonToken token)
436 case JsonToken.StartObject:
437 case JsonToken.StartArray:
438 case JsonToken.StartConstructor:
445 private void WriteEnd(JTokenType type)
449 case JTokenType.Object:
452 case JTokenType.Array:
455 case JTokenType.Constructor:
456 WriteEndConstructor();
459 throw new JsonWriterException("Unexpected type when writing end: " + type);
463 private void AutoCompleteAll()
471 private JTokenType GetTypeForCloseToken(JsonToken token)
475 case JsonToken.EndObject:
476 return JTokenType.Object;
477 case JsonToken.EndArray:
478 return JTokenType.Array;
479 case JsonToken.EndConstructor:
480 return JTokenType.Constructor;
482 throw new JsonWriterException("No type for token: " + token);
486 private JsonToken GetCloseTokenForType(JTokenType type)
490 case JTokenType.Object:
491 return JsonToken.EndObject;
492 case JTokenType.Array:
493 return JsonToken.EndArray;
494 case JTokenType.Constructor:
495 return JsonToken.EndConstructor;
497 throw new JsonWriterException("No close token for type: " + type);
501 private void AutoCompleteClose(JsonToken tokenBeingClosed)
503 // write closing symbol and calculate new state
505 int levelsToComplete = 0;
507 for (int i = 0; i < _top; i++)
509 int currentLevel = _top - i;
511 if (_stack[currentLevel] == GetTypeForCloseToken(tokenBeingClosed))
513 levelsToComplete = i + 1;
518 if (levelsToComplete == 0)
519 throw new JsonWriterException("No token to close.");
521 for (int i = 0; i < levelsToComplete; i++)
523 JsonToken token = GetCloseTokenForType(Pop());
525 if (_currentState != State.ObjectStart && _currentState != State.ArrayStart)
531 JTokenType currentLevelType = Peek();
533 switch (currentLevelType)
535 case JTokenType.Object:
536 _currentState = State.Object;
538 case JTokenType.Array:
539 _currentState = State.Array;
541 case JTokenType.Constructor:
542 _currentState = State.Array;
544 case JTokenType.None:
545 _currentState = State.Start;
548 throw new JsonWriterException("Unknown JsonType: " + currentLevelType);
553 /// Writes the specified end token.
555 /// <param name="token">The end token to write.</param>
556 protected virtual void WriteEnd(JsonToken token)
561 /// Writes indent characters.
563 protected virtual void WriteIndent()
568 /// Writes the JSON value delimiter.
570 protected virtual void WriteValueDelimiter()
575 /// Writes an indent space.
577 protected virtual void WriteIndentSpace()
581 internal void AutoComplete(JsonToken tokenBeingWritten)
585 switch (tokenBeingWritten)
588 token = (int)tokenBeingWritten;
590 case JsonToken.Integer:
591 case JsonToken.Float:
592 case JsonToken.String:
593 case JsonToken.Boolean:
595 case JsonToken.Undefined:
597 case JsonToken.Bytes:
598 // a value is being written
603 // gets new state based on the current state and what is being written
604 State newState = stateArray[token][(int)_currentState];
606 if (newState == State.Error)
607 throw new JsonWriterException("Token {0} in state {1} would result in an invalid JavaScript object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()));
609 if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment)
611 WriteValueDelimiter();
613 else if (_currentState == State.Property)
615 if (_formatting == Formatting.Indented)
619 WriteState writeState = WriteState;
621 // don't indent a property when it is the first token to be written (i.e. at the start)
622 if ((tokenBeingWritten == JsonToken.PropertyName && writeState != WriteState.Start) ||
623 writeState == WriteState.Array || writeState == WriteState.Constructor)
628 _currentState = newState;
631 #region WriteValue methods
633 /// Writes a null value.
635 public virtual void WriteNull()
637 AutoComplete(JsonToken.Null);
641 /// Writes an undefined value.
643 public virtual void WriteUndefined()
645 AutoComplete(JsonToken.Undefined);
649 /// Writes raw JSON without changing the writer's state.
651 /// <param name="json">The raw JSON to write.</param>
652 public virtual void WriteRaw(string json)
657 /// Writes raw JSON where a value is expected and updates the writer's state.
659 /// <param name="json">The raw JSON to write.</param>
660 public virtual void WriteRawValue(string json)
662 // hack. want writer to change state as if a value had been written
663 AutoComplete(JsonToken.Undefined);
668 /// Writes a <see cref="String"/> value.
670 /// <param name="value">The <see cref="String"/> value to write.</param>
671 public virtual void WriteValue(string value)
673 AutoComplete(JsonToken.String);
677 /// Writes a <see cref="Int32"/> value.
679 /// <param name="value">The <see cref="Int32"/> value to write.</param>
680 public virtual void WriteValue(int value)
682 AutoComplete(JsonToken.Integer);
686 /// Writes a <see cref="UInt32"/> value.
688 /// <param name="value">The <see cref="UInt32"/> value to write.</param>
689 [CLSCompliant(false)]
690 public virtual void WriteValue(uint value)
692 AutoComplete(JsonToken.Integer);
696 /// Writes a <see cref="Int64"/> value.
698 /// <param name="value">The <see cref="Int64"/> value to write.</param>
699 public virtual void WriteValue(long value)
701 AutoComplete(JsonToken.Integer);
705 /// Writes a <see cref="UInt64"/> value.
707 /// <param name="value">The <see cref="UInt64"/> value to write.</param>
708 [CLSCompliant(false)]
709 public virtual void WriteValue(ulong value)
711 AutoComplete(JsonToken.Integer);
715 /// Writes a <see cref="Single"/> value.
717 /// <param name="value">The <see cref="Single"/> value to write.</param>
718 public virtual void WriteValue(float value)
720 AutoComplete(JsonToken.Float);
724 /// Writes a <see cref="Double"/> value.
726 /// <param name="value">The <see cref="Double"/> value to write.</param>
727 public virtual void WriteValue(double value)
729 AutoComplete(JsonToken.Float);
733 /// Writes a <see cref="Boolean"/> value.
735 /// <param name="value">The <see cref="Boolean"/> value to write.</param>
736 public virtual void WriteValue(bool value)
738 AutoComplete(JsonToken.Boolean);
742 /// Writes a <see cref="Int16"/> value.
744 /// <param name="value">The <see cref="Int16"/> value to write.</param>
745 public virtual void WriteValue(short value)
747 AutoComplete(JsonToken.Integer);
751 /// Writes a <see cref="UInt16"/> value.
753 /// <param name="value">The <see cref="UInt16"/> value to write.</param>
754 [CLSCompliant(false)]
755 public virtual void WriteValue(ushort value)
757 AutoComplete(JsonToken.Integer);
761 /// Writes a <see cref="Char"/> value.
763 /// <param name="value">The <see cref="Char"/> value to write.</param>
764 public virtual void WriteValue(char value)
766 AutoComplete(JsonToken.String);
770 /// Writes a <see cref="Byte"/> value.
772 /// <param name="value">The <see cref="Byte"/> value to write.</param>
773 public virtual void WriteValue(byte value)
775 AutoComplete(JsonToken.Integer);
779 /// Writes a <see cref="SByte"/> value.
781 /// <param name="value">The <see cref="SByte"/> value to write.</param>
782 [CLSCompliant(false)]
783 public virtual void WriteValue(sbyte value)
785 AutoComplete(JsonToken.Integer);
789 /// Writes a <see cref="Decimal"/> value.
791 /// <param name="value">The <see cref="Decimal"/> value to write.</param>
792 public virtual void WriteValue(decimal value)
794 AutoComplete(JsonToken.Float);
798 /// Writes a <see cref="DateTime"/> value.
800 /// <param name="value">The <see cref="DateTime"/> value to write.</param>
801 public virtual void WriteValue(DateTime value)
803 AutoComplete(JsonToken.Date);
806 #if !PocketPC && !NET20
808 /// Writes a <see cref="DateTimeOffset"/> value.
810 /// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
811 public virtual void WriteValue(DateTimeOffset value)
813 AutoComplete(JsonToken.Date);
818 /// Writes a <see cref="Nullable{Int32}"/> value.
820 /// <param name="value">The <see cref="Nullable{Int32}"/> value to write.</param>
821 public virtual void WriteValue(int? value)
826 WriteValue(value.Value);
830 /// Writes a <see cref="Nullable{UInt32}"/> value.
832 /// <param name="value">The <see cref="Nullable{UInt32}"/> value to write.</param>
833 [CLSCompliant(false)]
834 public virtual void WriteValue(uint? value)
839 WriteValue(value.Value);
843 /// Writes a <see cref="Nullable{Int64}"/> value.
845 /// <param name="value">The <see cref="Nullable{Int64}"/> value to write.</param>
846 public virtual void WriteValue(long? value)
851 WriteValue(value.Value);
855 /// Writes a <see cref="Nullable{UInt64}"/> value.
857 /// <param name="value">The <see cref="Nullable{UInt64}"/> value to write.</param>
858 [CLSCompliant(false)]
859 public virtual void WriteValue(ulong? value)
864 WriteValue(value.Value);
868 /// Writes a <see cref="Nullable{Single}"/> value.
870 /// <param name="value">The <see cref="Nullable{Single}"/> value to write.</param>
871 public virtual void WriteValue(float? value)
876 WriteValue(value.Value);
880 /// Writes a <see cref="Nullable{Double}"/> value.
882 /// <param name="value">The <see cref="Nullable{Double}"/> value to write.</param>
883 public virtual void WriteValue(double? value)
888 WriteValue(value.Value);
892 /// Writes a <see cref="Nullable{Boolean}"/> value.
894 /// <param name="value">The <see cref="Nullable{Boolean}"/> value to write.</param>
895 public virtual void WriteValue(bool? value)
900 WriteValue(value.Value);
904 /// Writes a <see cref="Nullable{Int16}"/> value.
906 /// <param name="value">The <see cref="Nullable{Int16}"/> value to write.</param>
907 public virtual void WriteValue(short? value)
912 WriteValue(value.Value);
916 /// Writes a <see cref="Nullable{UInt16}"/> value.
918 /// <param name="value">The <see cref="Nullable{UInt16}"/> value to write.</param>
919 [CLSCompliant(false)]
920 public virtual void WriteValue(ushort? value)
925 WriteValue(value.Value);
929 /// Writes a <see cref="Nullable{Char}"/> value.
931 /// <param name="value">The <see cref="Nullable{Char}"/> value to write.</param>
932 public virtual void WriteValue(char? value)
937 WriteValue(value.Value);
941 /// Writes a <see cref="Nullable{Byte}"/> value.
943 /// <param name="value">The <see cref="Nullable{Byte}"/> value to write.</param>
944 public virtual void WriteValue(byte? value)
949 WriteValue(value.Value);
953 /// Writes a <see cref="Nullable{SByte}"/> value.
955 /// <param name="value">The <see cref="Nullable{SByte}"/> value to write.</param>
956 [CLSCompliant(false)]
957 public virtual void WriteValue(sbyte? value)
962 WriteValue(value.Value);
966 /// Writes a <see cref="Nullable{Decimal}"/> value.
968 /// <param name="value">The <see cref="Nullable{Decimal}"/> value to write.</param>
969 public virtual void WriteValue(decimal? value)
974 WriteValue(value.Value);
978 /// Writes a <see cref="Nullable{DateTime}"/> value.
980 /// <param name="value">The <see cref="Nullable{DateTime}"/> value to write.</param>
981 public virtual void WriteValue(DateTime? value)
986 WriteValue(value.Value);
989 #if !PocketPC && !NET20
991 /// Writes a <see cref="Nullable{DateTimeOffset}"/> value.
993 /// <param name="value">The <see cref="Nullable{DateTimeOffset}"/> value to write.</param>
994 public virtual void WriteValue(DateTimeOffset? value)
999 WriteValue(value.Value);
1004 /// Writes a <see cref="T:Byte[]"/> value.
1006 /// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
1007 public virtual void WriteValue(byte[] value)
1012 AutoComplete(JsonToken.Bytes);
1016 /// Writes a <see cref="Object"/> value.
1017 /// An error will raised if the value cannot be written as a single JSON token.
1019 /// <param name="value">The <see cref="Object"/> value to write.</param>
1020 public virtual void WriteValue(object value)
1027 else if (value is IConvertible)
1029 IConvertible convertible = value as IConvertible;
1031 switch (convertible.GetTypeCode())
1033 case TypeCode.String:
1034 WriteValue(convertible.ToString(CultureInfo.InvariantCulture));
1037 WriteValue(convertible.ToChar(CultureInfo.InvariantCulture));
1039 case TypeCode.Boolean:
1040 WriteValue(convertible.ToBoolean(CultureInfo.InvariantCulture));
1042 case TypeCode.SByte:
1043 WriteValue(convertible.ToSByte(CultureInfo.InvariantCulture));
1045 case TypeCode.Int16:
1046 WriteValue(convertible.ToInt16(CultureInfo.InvariantCulture));
1048 case TypeCode.UInt16:
1049 WriteValue(convertible.ToUInt16(CultureInfo.InvariantCulture));
1051 case TypeCode.Int32:
1052 WriteValue(convertible.ToInt32(CultureInfo.InvariantCulture));
1055 WriteValue(convertible.ToByte(CultureInfo.InvariantCulture));
1057 case TypeCode.UInt32:
1058 WriteValue(convertible.ToUInt32(CultureInfo.InvariantCulture));
1060 case TypeCode.Int64:
1061 WriteValue(convertible.ToInt64(CultureInfo.InvariantCulture));
1063 case TypeCode.UInt64:
1064 WriteValue(convertible.ToUInt64(CultureInfo.InvariantCulture));
1066 case TypeCode.Single:
1067 WriteValue(convertible.ToSingle(CultureInfo.InvariantCulture));
1069 case TypeCode.Double:
1070 WriteValue(convertible.ToDouble(CultureInfo.InvariantCulture));
1072 case TypeCode.DateTime:
1073 WriteValue(convertible.ToDateTime(CultureInfo.InvariantCulture));
1075 case TypeCode.Decimal:
1076 WriteValue(convertible.ToDecimal(CultureInfo.InvariantCulture));
1078 case TypeCode.DBNull:
1083 #if !PocketPC && !NET20
1084 else if (value is DateTimeOffset)
1086 WriteValue((DateTimeOffset)value);
1090 else if (value is byte[])
1092 WriteValue((byte[])value);
1096 throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
1101 /// Writes out a comment <code>/*...*/</code> containing the specified text.
1103 /// <param name="text">Text to place inside the comment.</param>
1104 public virtual void WriteComment(string text)
1106 AutoComplete(JsonToken.Comment);
1110 /// Writes out the given white space.
1112 /// <param name="ws">The string of white space characters.</param>
1113 public virtual void WriteWhitespace(string ws)
1117 if (!StringUtils.IsWhiteSpace(ws))
1118 throw new JsonWriterException("Only white space characters should be used.");
1123 void IDisposable.Dispose()
1128 private void Dispose(bool disposing)
1130 if (WriteState != WriteState.Closed)