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 System.Globalization;
30
using Newtonsoft.Json.Linq;
31
using Newtonsoft.Json.Utilities;
33
namespace Newtonsoft.Json
36
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
38
public abstract class JsonReader : IDisposable
41
/// Specifies the state of the reader.
46
/// The Read method has not been called.
50
/// The end of the file has been reached successfully.
54
/// Reader is at a property.
58
/// Reader is at the start of an object.
62
/// Reader is in an object.
66
/// Reader is at the start of an array.
70
/// Reader is in an array.
74
/// The Close method has been called.
78
/// Reader has just read a value.
82
/// Reader is at the start of a constructor.
86
/// Reader in a constructor.
90
/// An error occurred that prevents the read operation from continuing.
94
/// The end of the file has been reached successfully.
100
private JsonToken _token;
101
private object _value;
102
private Type _valueType;
103
private char _quoteChar;
104
private State _currentState;
105
private JTokenType _currentTypeContext;
108
/// Gets the current reader state.
110
/// <value>The current reader state.</value>
111
protected State CurrentState
113
get { return _currentState; }
118
private readonly List<JTokenType> _stack;
121
/// Gets the quotation mark character used to enclose the value of a string.
123
public virtual char QuoteChar
125
get { return _quoteChar; }
126
protected internal set { _quoteChar = value; }
130
/// Gets the type of the current Json token.
132
public virtual JsonToken TokenType
134
get { return _token; }
138
/// Gets the text value of the current Json token.
140
public virtual object Value
142
get { return _value; }
146
/// Gets The Common Language Runtime (CLR) type for the current Json token.
148
public virtual Type ValueType
150
get { return _valueType; }
154
/// Gets the depth of the current token in the JSON document.
156
/// <value>The depth of the current token in the JSON document.</value>
157
public virtual int Depth
161
int depth = _top - 1;
162
if (IsStartToken(TokenType))
170
/// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
172
protected JsonReader()
174
_currentState = State.Start;
175
_stack = new List<JTokenType>();
176
Push(JTokenType.None);
179
private void Push(JTokenType value)
183
_currentTypeContext = value;
186
private JTokenType Pop()
188
JTokenType value = Peek();
189
_stack.RemoveAt(_stack.Count - 1);
191
_currentTypeContext = _stack[_top - 1];
196
private JTokenType Peek()
198
return _currentTypeContext;
202
/// Reads the next JSON token from the stream.
204
/// <returns>true if the next token was read successfully; false if there are no more tokens to read.</returns>
205
public abstract bool Read();
208
/// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
210
/// <returns>A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.</returns>
211
public abstract byte[] ReadAsBytes();
214
/// Skips the children of the current token.
218
if (IsStartToken(TokenType))
222
while (Read() && (depth < Depth))
229
/// Sets the current token.
231
/// <param name="newToken">The new token.</param>
232
protected void SetToken(JsonToken newToken)
234
SetToken(newToken, null);
238
/// Sets the current token and value.
240
/// <param name="newToken">The new token.</param>
241
/// <param name="value">The value.</param>
242
protected virtual void SetToken(JsonToken newToken, object value)
248
case JsonToken.StartObject:
249
_currentState = State.ObjectStart;
250
Push(JTokenType.Object);
252
case JsonToken.StartArray:
253
_currentState = State.ArrayStart;
254
Push(JTokenType.Array);
256
case JsonToken.StartConstructor:
257
_currentState = State.ConstructorStart;
258
Push(JTokenType.Constructor);
260
case JsonToken.EndObject:
261
ValidateEnd(JsonToken.EndObject);
262
_currentState = State.PostValue;
264
case JsonToken.EndArray:
265
ValidateEnd(JsonToken.EndArray);
266
_currentState = State.PostValue;
268
case JsonToken.EndConstructor:
269
ValidateEnd(JsonToken.EndConstructor);
270
_currentState = State.PostValue;
272
case JsonToken.PropertyName:
273
_currentState = State.Property;
274
Push(JTokenType.Property);
276
case JsonToken.Undefined:
277
case JsonToken.Integer:
278
case JsonToken.Float:
279
case JsonToken.Boolean:
282
case JsonToken.String:
284
case JsonToken.Bytes:
285
_currentState = State.PostValue;
289
JTokenType current = Peek();
290
if (current == JTokenType.Property && _currentState == State.PostValue)
296
_valueType = value.GetType();
305
private void ValidateEnd(JsonToken endToken)
307
JTokenType currentObject = Pop();
309
if (GetTypeForCloseToken(endToken) != currentObject)
310
throw new JsonReaderException("JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, currentObject));
314
/// Sets the state based on current token type.
316
protected void SetStateBasedOnCurrent()
318
JTokenType currentObject = Peek();
320
switch (currentObject)
322
case JTokenType.Object:
323
_currentState = State.Object;
325
case JTokenType.Array:
326
_currentState = State.Array;
328
case JTokenType.Constructor:
329
_currentState = State.Constructor;
331
case JTokenType.None:
332
_currentState = State.Finished;
335
throw new JsonReaderException("While setting the reader state back to current object an unexpected JsonType was encountered: " + currentObject);
339
internal static bool IsPrimitiveToken(JsonToken token)
343
case JsonToken.Integer:
344
case JsonToken.Float:
345
case JsonToken.String:
346
case JsonToken.Boolean:
347
case JsonToken.Undefined:
350
case JsonToken.Bytes:
357
internal static bool IsStartToken(JsonToken token)
361
case JsonToken.StartObject:
362
case JsonToken.StartArray:
363
case JsonToken.StartConstructor:
364
case JsonToken.PropertyName:
367
case JsonToken.Comment:
368
case JsonToken.Integer:
369
case JsonToken.Float:
370
case JsonToken.String:
371
case JsonToken.Boolean:
373
case JsonToken.Undefined:
374
case JsonToken.EndObject:
375
case JsonToken.EndArray:
376
case JsonToken.EndConstructor:
379
case JsonToken.Bytes:
382
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("token", token, "Unexpected JsonToken value.");
386
private JTokenType GetTypeForCloseToken(JsonToken token)
390
case JsonToken.EndObject:
391
return JTokenType.Object;
392
case JsonToken.EndArray:
393
return JTokenType.Array;
394
case JsonToken.EndConstructor:
395
return JTokenType.Constructor;
397
throw new JsonReaderException("Not a valid close JsonToken: " + token);
402
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
404
void IDisposable.Dispose()
410
/// Releases unmanaged and - optionally - managed resources
412
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
413
protected virtual void Dispose(bool disposing)
415
if (_currentState != State.Closed && disposing)
420
/// Changes the <see cref="State"/> to Closed.
422
public virtual void Close()
424
_currentState = State.Closed;
425
_token = JsonToken.None;
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 System.Globalization;
30
using Newtonsoft.Json.Utilities;
32
using Newtonsoft.Json.Utilities.LinqBridge;
37
namespace Newtonsoft.Json
40
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
42
public abstract class JsonReader : IDisposable
45
/// Specifies the state of the reader.
47
protected internal enum State
50
/// The Read method has not been called.
54
/// The end of the file has been reached successfully.
58
/// Reader is at a property.
62
/// Reader is at the start of an object.
66
/// Reader is in an object.
70
/// Reader is at the start of an array.
74
/// Reader is in an array.
78
/// The Close method has been called.
82
/// Reader has just read a value.
86
/// Reader is at the start of a constructor.
90
/// Reader in a constructor.
94
/// An error occurred that prevents the read operation from continuing.
98
/// The end of the file has been reached successfully.
103
// current Token data
104
private JsonToken _tokenType;
105
private object _value;
106
private char _quoteChar;
107
internal State _currentState;
108
internal ReadType _readType;
109
private JsonPosition _currentPosition;
110
private CultureInfo _culture;
111
private DateTimeZoneHandling _dateTimeZoneHandling;
112
private int? _maxDepth;
113
private bool _hasExceededMaxDepth;
114
internal DateParseHandling _dateParseHandling;
115
private readonly List<JsonPosition> _stack;
118
/// Gets the current reader state.
120
/// <value>The current reader state.</value>
121
protected State CurrentState
123
get { return _currentState; }
127
/// Gets or sets a value indicating whether the underlying stream or
128
/// <see cref="TextReader"/> should be closed when the reader is closed.
131
/// true to close the underlying stream or <see cref="TextReader"/> when
132
/// the reader is closed; otherwise false. The default is true.
134
public bool CloseInput { get; set; }
137
/// Gets the quotation mark character used to enclose the value of a string.
139
public virtual char QuoteChar
141
get { return _quoteChar; }
142
protected internal set { _quoteChar = value; }
146
/// Get or set how <see cref="DateTime"/> time zones are handling when reading JSON.
148
public DateTimeZoneHandling DateTimeZoneHandling
150
get { return _dateTimeZoneHandling; }
151
set { _dateTimeZoneHandling = value; }
155
/// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
157
public DateParseHandling DateParseHandling
159
get { return _dateParseHandling; }
160
set { _dateParseHandling = value; }
164
/// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
168
get { return _maxDepth; }
172
throw new ArgumentException("Value must be positive.", "value");
179
/// Gets the type of the current JSON token.
181
public virtual JsonToken TokenType
183
get { return _tokenType; }
187
/// Gets the text value of the current JSON token.
189
public virtual object Value
191
get { return _value; }
195
/// Gets The Common Language Runtime (CLR) type for the current JSON token.
197
public virtual Type ValueType
199
get { return (_value != null) ? _value.GetType() : null; }
203
/// Gets the depth of the current token in the JSON document.
205
/// <value>The depth of the current token in the JSON document.</value>
206
public virtual int Depth
210
int depth = _stack.Count;
211
if (IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
219
/// Gets the path of the current JSON token.
221
public virtual string Path
225
if (_currentPosition.Type == JsonContainerType.None)
228
return JsonPosition.BuildPath(_stack.Concat(new[] { _currentPosition }));
233
/// Gets or sets the culture used when reading JSON. Defaults to <see cref="CultureInfo.InvariantCulture"/>.
235
public CultureInfo Culture
237
get { return _culture ?? CultureInfo.InvariantCulture; }
238
set { _culture = value; }
241
internal JsonPosition GetPosition(int depth)
243
if (depth < _stack.Count)
244
return _stack[depth];
246
return _currentPosition;
250
/// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
252
protected JsonReader()
254
_currentState = State.Start;
255
_stack = new List<JsonPosition>(4);
256
_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
257
_dateParseHandling = DateParseHandling.DateTime;
262
private void Push(JsonContainerType value)
264
UpdateScopeWithFinishedValue();
266
if (_currentPosition.Type == JsonContainerType.None)
268
_currentPosition.Type = value;
272
_stack.Add(_currentPosition);
273
JsonPosition state = new JsonPosition
277
_currentPosition = state;
279
// this is a little hacky because Depth increases when first property/value is written but only testing here is faster/simpler
280
if (_maxDepth != null && Depth + 1 > _maxDepth && !_hasExceededMaxDepth)
282
_hasExceededMaxDepth = true;
283
throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth));
288
private JsonContainerType Pop()
290
JsonPosition oldPosition;
291
if (_stack.Count > 0)
293
oldPosition = _currentPosition;
294
_currentPosition = _stack[_stack.Count - 1];
295
_stack.RemoveAt(_stack.Count - 1);
299
oldPosition = _currentPosition;
300
_currentPosition = new JsonPosition();
303
if (_maxDepth != null && Depth <= _maxDepth)
304
_hasExceededMaxDepth = false;
306
return oldPosition.Type;
309
private JsonContainerType Peek()
311
return _currentPosition.Type;
315
/// Reads the next JSON token from the stream.
317
/// <returns>true if the next token was read successfully; false if there are no more tokens to read.</returns>
318
public abstract bool Read();
321
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
323
/// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
324
public abstract int? ReadAsInt32();
327
/// Reads the next JSON token from the stream as a <see cref="String"/>.
329
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
330
public abstract string ReadAsString();
333
/// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
335
/// <returns>A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns>
336
public abstract byte[] ReadAsBytes();
339
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
341
/// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
342
public abstract decimal? ReadAsDecimal();
345
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
347
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
348
public abstract DateTime? ReadAsDateTime();
352
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
354
/// <returns>A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.</returns>
355
public abstract DateTimeOffset? ReadAsDateTimeOffset();
358
internal virtual bool ReadInternal()
360
throw new NotImplementedException();
364
internal DateTimeOffset? ReadAsDateTimeOffsetInternal()
366
_readType = ReadType.ReadAsDateTimeOffset;
372
SetToken(JsonToken.None);
375
} while (TokenType == JsonToken.Comment);
377
if (TokenType == JsonToken.Date)
379
if (Value is DateTime)
380
SetToken(JsonToken.Date, new DateTimeOffset((DateTime)Value));
382
return (DateTimeOffset)Value;
385
if (TokenType == JsonToken.Null)
389
if (TokenType == JsonToken.String)
391
if (DateTimeOffset.TryParse((string)Value, Culture, DateTimeStyles.RoundtripKind, out dt))
393
SetToken(JsonToken.Date, dt);
398
throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
402
if (TokenType == JsonToken.EndArray)
405
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
409
internal byte[] ReadAsBytesInternal()
411
_readType = ReadType.ReadAsBytes;
417
SetToken(JsonToken.None);
420
} while (TokenType == JsonToken.Comment);
422
if (IsWrappedInTypeObject())
424
byte[] data = ReadAsBytes();
426
SetToken(JsonToken.Bytes, data);
430
// attempt to convert possible base 64 string to bytes
431
if (TokenType == JsonToken.String)
433
string s = (string)Value;
434
byte[] data = (s.Length == 0) ? new byte[0] : Convert.FromBase64String(s);
435
SetToken(JsonToken.Bytes, data);
438
if (TokenType == JsonToken.Null)
441
if (TokenType == JsonToken.Bytes)
442
return (byte[])Value;
444
if (TokenType == JsonToken.StartArray)
446
List<byte> data = new List<byte>();
448
while (ReadInternal())
452
case JsonToken.Integer:
453
data.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
455
case JsonToken.EndArray:
456
byte[] d = data.ToArray();
457
SetToken(JsonToken.Bytes, d);
459
case JsonToken.Comment:
463
throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
467
throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
470
if (TokenType == JsonToken.EndArray)
473
throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
476
internal decimal? ReadAsDecimalInternal()
478
_readType = ReadType.ReadAsDecimal;
484
SetToken(JsonToken.None);
487
} while (TokenType == JsonToken.Comment);
489
if (TokenType == JsonToken.Integer || TokenType == JsonToken.Float)
491
if (!(Value is decimal))
492
SetToken(JsonToken.Float, Convert.ToDecimal(Value, CultureInfo.InvariantCulture));
494
return (decimal)Value;
497
if (TokenType == JsonToken.Null)
501
if (TokenType == JsonToken.String)
503
if (decimal.TryParse((string)Value, NumberStyles.Number, Culture, out d))
505
SetToken(JsonToken.Float, d);
510
throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
514
if (TokenType == JsonToken.EndArray)
517
throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
520
internal int? ReadAsInt32Internal()
522
_readType = ReadType.ReadAsInt32;
528
SetToken(JsonToken.None);
531
} while (TokenType == JsonToken.Comment);
533
if (TokenType == JsonToken.Integer || TokenType == JsonToken.Float)
536
SetToken(JsonToken.Integer, Convert.ToInt32(Value, CultureInfo.InvariantCulture));
541
if (TokenType == JsonToken.Null)
545
if (TokenType == JsonToken.String)
547
if (int.TryParse((string)Value, NumberStyles.Integer, Culture, out i))
549
SetToken(JsonToken.Integer, i);
554
throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
558
if (TokenType == JsonToken.EndArray)
561
throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
564
internal string ReadAsStringInternal()
566
_readType = ReadType.ReadAsString;
572
SetToken(JsonToken.None);
575
} while (TokenType == JsonToken.Comment);
577
if (TokenType == JsonToken.String)
578
return (string)Value;
580
if (TokenType == JsonToken.Null)
583
if (IsPrimitiveToken(TokenType))
588
if (ConvertUtils.IsConvertible(Value))
589
s = ConvertUtils.ToConvertible(Value).ToString(Culture);
590
else if (Value is IFormattable)
591
s = ((IFormattable)Value).ToString(null, Culture);
593
s = Value.ToString();
595
SetToken(JsonToken.String, s);
600
if (TokenType == JsonToken.EndArray)
603
throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
606
internal DateTime? ReadAsDateTimeInternal()
608
_readType = ReadType.ReadAsDateTime;
614
SetToken(JsonToken.None);
617
} while (TokenType == JsonToken.Comment);
619
if (TokenType == JsonToken.Date)
620
return (DateTime)Value;
622
if (TokenType == JsonToken.Null)
626
if (TokenType == JsonToken.String)
628
string s = (string)Value;
629
if (string.IsNullOrEmpty(s))
631
SetToken(JsonToken.Null);
635
if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
637
dt = JsonConvert.EnsureDateTime(dt, DateTimeZoneHandling);
638
SetToken(JsonToken.Date, dt);
643
throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
647
if (TokenType == JsonToken.EndArray)
650
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
653
private bool IsWrappedInTypeObject()
655
_readType = ReadType.Read;
657
if (TokenType == JsonToken.StartObject)
660
throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
662
if (Value.ToString() == "$type")
665
if (Value != null && Value.ToString().StartsWith("System.Byte[]"))
668
if (Value.ToString() == "$value")
675
throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject));
682
/// Skips the children of the current token.
686
if (TokenType == JsonToken.PropertyName)
689
if (IsStartToken(TokenType))
693
while (Read() && (depth < Depth))
700
/// Sets the current token.
702
/// <param name="newToken">The new token.</param>
703
protected void SetToken(JsonToken newToken)
705
SetToken(newToken, null);
709
/// Sets the current token and value.
711
/// <param name="newToken">The new token.</param>
712
/// <param name="value">The value.</param>
713
protected void SetToken(JsonToken newToken, object value)
715
_tokenType = newToken;
720
case JsonToken.StartObject:
721
_currentState = State.ObjectStart;
722
Push(JsonContainerType.Object);
724
case JsonToken.StartArray:
725
_currentState = State.ArrayStart;
726
Push(JsonContainerType.Array);
728
case JsonToken.StartConstructor:
729
_currentState = State.ConstructorStart;
730
Push(JsonContainerType.Constructor);
732
case JsonToken.EndObject:
733
ValidateEnd(JsonToken.EndObject);
735
case JsonToken.EndArray:
736
ValidateEnd(JsonToken.EndArray);
738
case JsonToken.EndConstructor:
739
ValidateEnd(JsonToken.EndConstructor);
741
case JsonToken.PropertyName:
742
_currentState = State.Property;
744
_currentPosition.PropertyName = (string) value;
746
case JsonToken.Undefined:
747
case JsonToken.Integer:
748
case JsonToken.Float:
749
case JsonToken.Boolean:
752
case JsonToken.String:
754
case JsonToken.Bytes:
755
_currentState = (Peek() != JsonContainerType.None) ? State.PostValue : State.Finished;
757
UpdateScopeWithFinishedValue();
762
private void UpdateScopeWithFinishedValue()
764
if (_currentPosition.Type == JsonContainerType.Array
765
|| _currentPosition.Type == JsonContainerType.Constructor)
767
if (_currentPosition.Position == null)
768
_currentPosition.Position = 0;
770
_currentPosition.Position++;
774
private void ValidateEnd(JsonToken endToken)
776
JsonContainerType currentObject = Pop();
778
if (GetTypeForCloseToken(endToken) != currentObject)
779
throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, currentObject));
781
_currentState = (Peek() != JsonContainerType.None) ? State.PostValue : State.Finished;
785
/// Sets the state based on current token type.
787
protected void SetStateBasedOnCurrent()
789
JsonContainerType currentObject = Peek();
791
switch (currentObject)
793
case JsonContainerType.Object:
794
_currentState = State.Object;
796
case JsonContainerType.Array:
797
_currentState = State.Array;
799
case JsonContainerType.Constructor:
800
_currentState = State.Constructor;
802
case JsonContainerType.None:
803
_currentState = State.Finished;
806
throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, currentObject));
810
internal static bool IsPrimitiveToken(JsonToken token)
814
case JsonToken.Integer:
815
case JsonToken.Float:
816
case JsonToken.String:
817
case JsonToken.Boolean:
818
case JsonToken.Undefined:
821
case JsonToken.Bytes:
828
internal static bool IsStartToken(JsonToken token)
832
case JsonToken.StartObject:
833
case JsonToken.StartArray:
834
case JsonToken.StartConstructor:
841
private JsonContainerType GetTypeForCloseToken(JsonToken token)
845
case JsonToken.EndObject:
846
return JsonContainerType.Object;
847
case JsonToken.EndArray:
848
return JsonContainerType.Array;
849
case JsonToken.EndConstructor:
850
return JsonContainerType.Constructor;
852
throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token));
857
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
859
void IDisposable.Dispose()
865
/// Releases unmanaged and - optionally - managed resources
867
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
868
protected virtual void Dispose(bool disposing)
870
if (_currentState != State.Closed && disposing)
875
/// Changes the <see cref="State"/> to Closed.
877
public virtual void Close()
879
_currentState = State.Closed;
880
_tokenType = JsonToken.None;
b'\\ No newline at end of file'