diff --git a/Src/Newtonsoft.Json/JavaScriptArray.cs b/Src/Newtonsoft.Json/JavaScriptArray.cs
deleted file mode 100644
index 6456cdd7..00000000
--- a/Src/Newtonsoft.Json/JavaScriptArray.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-#region License
-// Copyright (c) 2007 James Newton-King
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Newtonsoft.Json
-{
- ///
- /// Represents a JavaScript array.
- ///
- public class JavaScriptArray : List
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public JavaScriptArray()
- {
- }
-
- ///
- /// Initializes a new instance of the class that
- /// contains elements copied from the specified collection.
- ///
- /// The collection whose elements are copied to the new array.
- public JavaScriptArray(IEnumerable collection)
- : base(collection)
- {
- }
-
- ///
- /// Initializes a new instance of the class that
- /// is empty and has the specified initial capacity.
- ///
- /// The number of elements that the new array can initially store.
- public JavaScriptArray(int capacity)
- : base(capacity)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JavaScriptConstructor.cs b/Src/Newtonsoft.Json/JavaScriptConstructor.cs
deleted file mode 100644
index dd5b2b43..00000000
--- a/Src/Newtonsoft.Json/JavaScriptConstructor.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-#region License
-// Copyright (c) 2007 James Newton-King
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Newtonsoft.Json
-{
- ///
- /// Represents a JavaScript constructor.
- ///
- public class JavaScriptConstructor
- {
- private string _name;
- private JavaScriptParameters _parameters;
-
- public JavaScriptParameters Parameters
- {
- get { return _parameters; }
- }
-
- public string Name
- {
- get { return _name; }
- }
-
- public JavaScriptConstructor(string name, JavaScriptParameters parameters)
- {
- if (name == null)
- throw new ArgumentNullException("name");
-
- if (name.Length == 0)
- throw new ArgumentException("Constructor name cannot be empty.", "name");
-
- _name = name;
- _parameters = parameters ?? JavaScriptParameters.Empty;
- }
-
- public override string ToString()
- {
- StringBuilder sb = new StringBuilder();
-
- sb.Append("new ");
- sb.Append(_name);
- sb.Append("(");
- if (_parameters != null)
- {
- for (int i = 0; i < _parameters.Count; i++)
- {
- sb.Append(_parameters[i]);
- }
- }
- sb.Append(")");
-
- return sb.ToString();
- }
- }
-}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JavaScriptConvert.cs b/Src/Newtonsoft.Json/JavaScriptConvert.cs
index 5bb46380..f91d0532 100644
--- a/Src/Newtonsoft.Json/JavaScriptConvert.cs
+++ b/Src/Newtonsoft.Json/JavaScriptConvert.cs
@@ -388,7 +388,7 @@ namespace Newtonsoft.Json
}
}
- using (JsonWriter jsonWriter = new JsonWriter(sw))
+ using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
//jsonWriter.Formatting = Formatting.Indented;
jsonSerializer.Serialize(jsonWriter, value);
@@ -472,7 +472,7 @@ namespace Newtonsoft.Json
object deserializedValue;
- using (JsonReader jsonReader = new JsonReader(sr))
+ using (JsonReader jsonReader = new JsonTextReader(sr))
{
deserializedValue = jsonSerializer.Deserialize(jsonReader, type);
}
diff --git a/Src/Newtonsoft.Json/JavaScriptObject.cs b/Src/Newtonsoft.Json/JavaScriptObject.cs
deleted file mode 100644
index b1625bae..00000000
--- a/Src/Newtonsoft.Json/JavaScriptObject.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-#region License
-// Copyright (c) 2007 James Newton-King
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Newtonsoft.Json
-{
- ///
- /// Represents a JavaScript object.
- ///
- public class JavaScriptObject : Dictionary
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public JavaScriptObject()
- : base(EqualityComparer.Default)
- {
- }
-
- ///
- /// Initializes a new instance of the class that
- /// contains values copied from the specified .
- ///
- /// The whose elements are copied to the new object.
- public JavaScriptObject(JavaScriptObject javaScriptObject)
- : base(javaScriptObject, EqualityComparer.Default)
- {
- }
- }
-}
diff --git a/Src/Newtonsoft.Json/JavaScriptParameters.cs b/Src/Newtonsoft.Json/JavaScriptParameters.cs
deleted file mode 100644
index ba0a2cd3..00000000
--- a/Src/Newtonsoft.Json/JavaScriptParameters.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-#region License
-// Copyright (c) 2007 James Newton-King
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Collections.ObjectModel;
-
-namespace Newtonsoft.Json
-{
- public class JavaScriptParameters : ReadOnlyCollection
- {
- public static readonly JavaScriptParameters Empty = new JavaScriptParameters(new List());
-
- public JavaScriptParameters(IList list)
- : base(list)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs
index 8421c2db..7dea5e65 100644
--- a/Src/Newtonsoft.Json/JsonReader.cs
+++ b/Src/Newtonsoft.Json/JsonReader.cs
@@ -29,15 +29,16 @@ using System.Text;
using System.IO;
using System.Xml;
using System.Globalization;
+using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json
{
///
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
///
- public class JsonReader : IDisposable
+ public abstract class JsonReader : IDisposable
{
- private enum State
+ protected enum State
{
Start,
Complete,
@@ -54,20 +55,22 @@ namespace Newtonsoft.Json
Finished
}
- private TextReader _reader;
- private char _currentChar;
-
// current Token data
private JsonToken _token;
private object _value;
private Type _valueType;
private char _quoteChar;
- private StringBuffer _buffer;
- //private StringBuilder _testBuffer;
private State _currentState;
+ protected State CurrentState
+ {
+ get { return _currentState; }
+ private set { _currentState = value; }
+ }
+
private int _top;
- private List _stack;
+
+ private List _stack;
///
/// Gets the quotation mark character used to enclose the value of a string.
@@ -75,6 +78,7 @@ namespace Newtonsoft.Json
public char QuoteChar
{
get { return _quoteChar; }
+ protected set { _quoteChar = value; }
}
///
@@ -101,409 +105,55 @@ namespace Newtonsoft.Json
get { return _valueType; }
}
+ public int Depth
+ {
+ get { return _top - 1; }
+ }
+
///
/// Initializes a new instance of the class with the specified .
///
- /// The TextReader containing the XML data to read.
- public JsonReader(TextReader reader)
+ public JsonReader()
{
- if (reader == null)
- throw new ArgumentNullException("reader");
-
- _reader = reader;
- _buffer = new StringBuffer(4096);
//_testBuffer = new StringBuilder();
_currentState = State.Start;
- _stack = new List();
+ _stack = new List();
_top = 0;
- Push(JsonType.None);
+ Push(JsonTokenType.None);
}
- private void Push(JsonType value)
+ private void Push(JsonTokenType value)
{
_stack.Add(value);
_top++;
}
- private JsonType Pop()
+ private JsonTokenType Pop()
{
- JsonType value = Peek();
+ JsonTokenType value = Peek();
_stack.RemoveAt(_stack.Count - 1);
_top--;
return value;
}
- private JsonType Peek()
+ private JsonTokenType Peek()
{
return _stack[_top - 1];
}
- private void ParseString(char quote)
- {
- bool stringTerminated = false;
- bool hexNumber = false;
- int hexCount = 0;
-
- while (!stringTerminated && MoveNext())
- {
- if (hexNumber)
- hexCount++;
-
- switch (_currentChar)
- {
- case '\\':
- if (MoveNext())
- {
- switch (_currentChar)
- {
- case 'b':
- _buffer.Append('\b');
- break;
- case 't':
- _buffer.Append('\t');
- break;
- case 'n':
- _buffer.Append('\n');
- break;
- case 'f':
- _buffer.Append('\f');
- break;
- case 'r':
- _buffer.Append('\r');
- break;
- case 'u':
- // note the start of a hex character
- hexNumber = true;
- break;
- default:
- _buffer.Append(_currentChar);
- break;
- }
- }
- else
- {
- throw new JsonReaderException("Unterminated string. Expected delimiter: " + quote);
- }
- break;
- case '"':
- case '\'':
- if (_currentChar == quote)
- stringTerminated = true;
- else
- goto default;
- break;
- default:
- _buffer.Append(_currentChar);
- break;
- }
-
- if (hexCount == 4)
- {
- // remove hex characters from buffer, convert to char and then add
- string hexString = _buffer.ToString(_buffer.Position - 4, 4);
- char hexChar = Convert.ToChar(int.Parse(hexString, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo));
-
- _buffer.Position = _buffer.Position - 4;
- _buffer.Append(hexChar);
-
- hexNumber = false;
- hexCount = 0;
- }
- }
-
- if (!stringTerminated)
- throw new JsonReaderException("Unterminated string. Expected delimiter: " + quote);
-
- ClearCurrentChar();
- _currentState = State.PostValue;
- string text = _buffer.ToString();
- _buffer.Position = 0;
-
- if (text.StartsWith("/Date(", StringComparison.Ordinal) && text.EndsWith(")/", StringComparison.Ordinal))
- {
- ParseDate(text);
- }
- else
- {
- SetToken(JsonToken.String, text);
- _quoteChar = quote;
- }
- }
-
- private void ParseDate(string text)
- {
- string value = text.Substring(6, text.Length - 8);
- DateTimeKind kind = DateTimeKind.Utc;
-
- int index = value.IndexOf('+', 1);
-
- if (index == -1)
- index = value.IndexOf('-', 1);
-
- if (index != -1)
- {
- kind = DateTimeKind.Local;
- value = value.Substring(0, index);
- }
-
- long javaScriptTicks = long.Parse(value);
- DateTime utcDateTime = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
- DateTime dateTime;
-
- switch (kind)
- {
- case DateTimeKind.Unspecified:
- dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
- break;
- case DateTimeKind.Local:
- dateTime = utcDateTime.ToLocalTime();
- break;
- default:
- dateTime = utcDateTime;
- break;
- }
-
- SetToken(JsonToken.Date, dateTime);
- }
-
- private bool MoveNext()
- {
- int value = _reader.Read();
-
- if (value != -1)
- {
- _currentChar = (char)value;
- //_testBuffer.Append(_currentChar);
- return true;
- }
- else
- {
- return false;
- }
- }
-
- private bool HasNext()
- {
- return (_reader.Peek() != -1);
- }
-
- private char PeekNext()
- {
- return (char)_reader.Peek();
- }
-
- private void ClearCurrentChar()
- {
- _currentChar = '\0';
- }
-
- private bool MoveTo(char value)
- {
- while (MoveNext())
- {
- if (_currentChar == value)
- return true;
- }
- return false;
- }
-
///
/// Reads the next Json token from the stream.
///
///
- public bool Read()
- {
- while (true)
- {
- if (_currentChar == '\0')
- {
- if (!MoveNext())
- return false;
- }
+ public abstract bool Read();
- switch (_currentState)
- {
- case State.Start:
- case State.Property:
- case State.Array:
- case State.ArrayStart:
- case State.Constructor:
- case State.ConstructorStart:
- return ParseValue();
- case State.Complete:
- break;
- case State.Object:
- case State.ObjectStart:
- return ParseObject();
- case State.PostValue:
- // returns true if it hits
- // end of object or array
- if (ParsePostValue())
- return true;
- break;
- case State.Closed:
- break;
- case State.Error:
- break;
- default:
- throw new JsonReaderException("Unexpected state: " + _currentState);
- }
- }
- }
-
- private bool ParsePostValue()
- {
- do
- {
- switch (_currentChar)
- {
- case '}':
- SetToken(JsonToken.EndObject);
- ClearCurrentChar();
- return true;
- case ']':
- SetToken(JsonToken.EndArray);
- ClearCurrentChar();
- return true;
- case ')':
- SetToken(JsonToken.EndConstructor);
- ClearCurrentChar();
- return true;
- case '/':
- ParseComment();
- return true;
- case ',':
- // finished paring
- SetStateBasedOnCurrent();
- ClearCurrentChar();
- return false;
- default:
- if (char.IsWhiteSpace(_currentChar))
- {
- // eat whitespace
- ClearCurrentChar();
- }
- else
- {
- throw new JsonReaderException("After parsing a value an unexpected character was encoutered: " + _currentChar);
- }
- break;
- }
- } while (MoveNext());
-
- return false;
- }
-
- private bool ParseObject()
- {
- do
- {
- switch (_currentChar)
- {
- case '}':
- SetToken(JsonToken.EndObject);
- return true;
- case '/':
- ParseComment();
- return true;
- case ',':
- SetToken(JsonToken.Undefined);
- return true;
- default:
- if (char.IsWhiteSpace(_currentChar))
- {
- // eat
- }
- else
- {
- return ParseProperty();
- }
- break;
- }
- } while (MoveNext());
-
- return false;
- }
-
- private bool ParseProperty()
- {
- if (ValidIdentifierChar(_currentChar))
- {
- ParseUnquotedProperty();
- }
- else if (_currentChar == '"' || _currentChar == '\'')
- {
- ParseQuotedProperty(_currentChar);
- }
- else
- {
- throw new JsonReaderException("Invalid property identifier character: " + _currentChar);
- }
-
- // finished property. move to colon
- if (_currentChar != ':')
- {
- MoveTo(':');
- }
-
- SetToken(JsonToken.PropertyName, _buffer.ToString());
- _buffer.Position = 0;
-
- return true;
- }
-
- private void ParseQuotedProperty(char quoteChar)
- {
- // parse property name until quoted char is hit
- while (MoveNext())
- {
- if (_currentChar == quoteChar)
- {
- return;
- }
- else
- {
- _buffer.Append(_currentChar);
- }
- }
-
- throw new JsonReaderException("Unclosed quoted property. Expected: " + quoteChar);
- }
-
- private bool ValidIdentifierChar(char value)
- {
- return (char.IsLetterOrDigit(_currentChar) || _currentChar == '_' || _currentChar == '$');
- }
-
- private void ParseUnquotedProperty()
- {
- // parse unquoted property name until whitespace or colon
- _buffer.Append(_currentChar);
-
- while (MoveNext())
- {
- if (char.IsWhiteSpace(_currentChar) || _currentChar == ':')
- {
- break;
- }
- else if (ValidIdentifierChar(_currentChar))
- {
- _buffer.Append(_currentChar);
- }
- else
- {
- throw new JsonReaderException("Invalid JavaScript property identifier character: " + _currentChar);
- }
- }
- }
-
- private void SetToken(JsonToken newToken)
+ protected void SetToken(JsonToken newToken)
{
SetToken(newToken, null);
}
- private void SetToken(JsonToken newToken, object value)
+ protected virtual void SetToken(JsonToken newToken, object value)
{
_token = newToken;
@@ -511,37 +161,30 @@ namespace Newtonsoft.Json
{
case JsonToken.StartObject:
_currentState = State.ObjectStart;
- Push(JsonType.Object);
- ClearCurrentChar();
+ Push(JsonTokenType.Object);
break;
case JsonToken.StartArray:
_currentState = State.ArrayStart;
- Push(JsonType.Array);
- ClearCurrentChar();
+ Push(JsonTokenType.Array);
break;
case JsonToken.StartConstructor:
_currentState = State.ConstructorStart;
- Push(JsonType.Constructor);
- ClearCurrentChar();
+ Push(JsonTokenType.Constructor);
break;
case JsonToken.EndObject:
ValidateEnd(JsonToken.EndObject);
- ClearCurrentChar();
_currentState = State.PostValue;
break;
case JsonToken.EndArray:
ValidateEnd(JsonToken.EndArray);
- ClearCurrentChar();
_currentState = State.PostValue;
break;
case JsonToken.EndConstructor:
ValidateEnd(JsonToken.EndConstructor);
- ClearCurrentChar();
_currentState = State.PostValue;
break;
case JsonToken.PropertyName:
_currentState = State.Property;
- ClearCurrentChar();
break;
case JsonToken.Undefined:
case JsonToken.Integer:
@@ -549,6 +192,7 @@ namespace Newtonsoft.Json
case JsonToken.Boolean:
case JsonToken.Null:
case JsonToken.Date:
+ case JsonToken.String:
_currentState = State.PostValue;
break;
}
@@ -565,242 +209,30 @@ namespace Newtonsoft.Json
}
}
- private bool ParseValue()
- {
- do
- {
- switch (_currentChar)
- {
- case '"':
- case '\'':
- ParseString(_currentChar);
- return true;
- case 't':
- ParseTrue();
- return true;
- case 'f':
- ParseFalse();
- return true;
- case 'n':
- if (HasNext())
- {
- char next = PeekNext();
-
- if (next == 'u')
- ParseNull();
- else if (next == 'e')
- ParseConstructor();
- else
- throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
- }
- else
- {
- throw new JsonReaderException("Unexpected end");
- }
- return true;
- case '/':
- ParseComment();
- return true;
- case 'u':
- ParseUndefined();
- return true;
- case '{':
- SetToken(JsonToken.StartObject);
- return true;
- case '[':
- SetToken(JsonToken.StartArray);
- return true;
- case '}':
- SetToken(JsonToken.EndObject);
- return true;
- case ']':
- SetToken(JsonToken.EndArray);
- return true;
- case ',':
- SetToken(JsonToken.Undefined);
- //ClearCurrentChar();
- return true;
- case ')':
- SetToken(JsonToken.EndConstructor);
- return true;
- //if (_currentState == State.Constructor)
- //{
- // _currentState = State.ConstructorEnd;
- // return false;
- //}
- //else
- //{
- // throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
- //}
- default:
- if (char.IsWhiteSpace(_currentChar))
- {
- // eat
- }
- else if (char.IsNumber(_currentChar) || _currentChar == '-' || _currentChar == '.')
- {
- ParseNumber();
- return true;
- }
- else
- {
- throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
- }
- break;
- }
- } while (MoveNext());
-
- return false;
- }
-
- private bool EatWhitespace(bool oneOrMore)
- {
- bool whitespace = false;
- while (char.IsWhiteSpace(_currentChar))
- {
- whitespace = true;
- MoveNext();
- }
-
- return (!oneOrMore || whitespace);
- }
-
- private void ParseConstructor()
- {
- if (MatchValue("new", true))
- {
- if (EatWhitespace(true))
- {
- while (char.IsLetter(_currentChar))
- {
- _buffer.Append(_currentChar);
- MoveNext();
- }
-
-
- EatWhitespace(false);
-
- if (_currentChar != '(')
- throw new JsonReaderException("Unexpected character while parsing constructor: " + _currentChar);
-
- string constructorName = _buffer.ToString();
- _buffer.Position = 0;
-
- SetToken(JsonToken.StartConstructor);
-
- _value = constructorName;
- _valueType = typeof(string);
-
- //if (string.CompareOrdinal(constructorName, "Date") == 0)
- //{
- // IList parameters = new List();
-
- // MoveNext();
- // while (ParseValue() && _token != JsonToken.EndConstructor)
- // {
- // parameters.Add(_value);
- // }
-
- // long javaScriptTicks = Convert.ToInt64(parameters[0]);
-
- // DateTime date = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
-
- // SetToken(JsonToken.Date, date);
- //}
-
-
-
- //{
- // _currentState = State.Constructor;
-
- // while (ParseValue())
- // {
- // parameters.Add(_value);
- // _currentState = State.Constructor;
- // }
-
- // if (string.CompareOrdinal(constructorName, "Date") == 0)
- // {
- // long javaScriptTicks = Convert.ToInt64(parameters[0]);
-
- // DateTime date = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
-
- // SetToken(JsonToken.Date, date);
- // }
- // else
- // {
- // JavaScriptConstructor constructor = new JavaScriptConstructor(constructorName, new JavaScriptParameters(parameters));
-
- // if (_currentState == State.ConstructorEnd)
- // {
- // SetToken(JsonToken.Constructor, constructor);
- // }
- // }
-
- // // move past ')'
- // MoveNext();
- //}
- }
- }
- }
-
- private void ParseNumber()
- {
- // parse until seperator character or end
- bool end = false;
- do
- {
- if (CurrentIsSeperator())
- end = true;
- else
- _buffer.Append(_currentChar);
-
- } while (!end && MoveNext());
-
- string number = _buffer.ToString();
- object numberValue;
- JsonToken numberType;
-
- if (number.IndexOf('.') == -1)
- {
- numberValue = Convert.ToInt64(_buffer.ToString(), CultureInfo.InvariantCulture);
- numberType = JsonToken.Integer;
- }
- else
- {
- numberValue = Convert.ToDouble(_buffer.ToString(), CultureInfo.InvariantCulture);
- numberType = JsonToken.Float;
- }
-
- _buffer.Position = 0;
-
- SetToken(numberType, numberValue);
- }
-
private void ValidateEnd(JsonToken endToken)
{
- JsonType currentObject = Pop();
+ JsonTokenType currentObject = Pop();
if (GetTypeForCloseToken(endToken) != currentObject)
throw new JsonReaderException(string.Format("JsonToken {0} is not valid for closing JsonType {1}.", endToken, currentObject));
}
-
- private void SetStateBasedOnCurrent()
+
+ protected void SetStateBasedOnCurrent()
{
- JsonType currentObject = Peek();
+ JsonTokenType currentObject = Peek();
switch (currentObject)
{
- case JsonType.Object:
+ case JsonTokenType.Object:
_currentState = State.Object;
break;
- case JsonType.Array:
+ case JsonTokenType.Array:
_currentState = State.Array;
break;
- case JsonType.Constructor:
+ case JsonTokenType.Constructor:
_currentState = State.Constructor;
break;
- case JsonType.None:
+ case JsonTokenType.None:
_currentState = State.Finished;
break;
default:
@@ -808,172 +240,27 @@ namespace Newtonsoft.Json
}
}
- private JsonType GetTypeForCloseToken(JsonToken token)
+ private JsonTokenType GetTypeForCloseToken(JsonToken token)
{
switch (token)
{
case JsonToken.EndObject:
- return JsonType.Object;
+ return JsonTokenType.Object;
case JsonToken.EndArray:
- return JsonType.Array;
+ return JsonTokenType.Array;
case JsonToken.EndConstructor:
- return JsonType.Constructor;
+ return JsonTokenType.Constructor;
default:
throw new JsonReaderException("Not a valid close JsonToken: " + token);
}
}
- private void ParseComment()
- {
- // should have already parsed / character before reaching this method
-
- MoveNext();
-
- if (_currentChar == '*')
- {
- while (MoveNext())
- {
- if (_currentChar == '*')
- {
- if (MoveNext())
- {
- if (_currentChar == '/')
- {
- break;
- }
- else
- {
- _buffer.Append('*');
- _buffer.Append(_currentChar);
- }
- }
- }
- else
- {
- _buffer.Append(_currentChar);
- }
- }
- }
- else
- {
- throw new JsonReaderException("Error parsing comment. Expected: *");
- }
-
- SetToken(JsonToken.Comment, _buffer.ToString());
-
- _buffer.Position = 0;
-
- ClearCurrentChar();
- }
-
- private bool MatchValue(string value)
- {
- int i = 0;
- do
- {
- if (_currentChar != value[i])
- {
- break;
- }
- i++;
- }
- while (i < value.Length && MoveNext());
-
- return (i == value.Length);
- }
-
- private bool MatchValue(string value, bool noTrailingNonSeperatorCharacters)
- {
- // will match value and then move to the next character, checking that it is a seperator character
- bool match = MatchValue(value);
-
- if (!noTrailingNonSeperatorCharacters)
- return match;
- else
- return (match && (!MoveNext() || CurrentIsSeperator()));
- }
-
- private bool CurrentIsSeperator()
- {
- switch (_currentChar)
- {
- case '}':
- case ']':
- case ',':
- return true;
- case '/':
- // check next character to see if start of a comment
- return (HasNext() && PeekNext() == '*');
- case ')':
- if (_currentState == State.Constructor || _currentState == State.ConstructorStart)
- return true;
- break;
- default:
- if (char.IsWhiteSpace(_currentChar))
- return true;
- break;
- }
-
- return false;
- }
-
- private void ParseTrue()
- {
- // check characters equal 'true'
- // and that it is followed by either a seperator character
- // or the text ends
- if (MatchValue(JavaScriptConvert.True, true))
- {
- SetToken(JsonToken.Boolean, true);
- }
- else
- {
- throw new JsonReaderException("Error parsing boolean value.");
- }
- }
-
- private void ParseNull()
- {
- if (MatchValue(JavaScriptConvert.Null, true))
- {
- SetToken(JsonToken.Null);
- }
- else
- {
- throw new JsonReaderException("Error parsing null value.");
- }
- }
-
- private void ParseUndefined()
- {
- if (MatchValue(JavaScriptConvert.Undefined, true))
- {
- SetToken(JsonToken.Undefined);
- }
- else
- {
- throw new JsonReaderException("Error parsing undefined value.");
- }
- }
-
- private void ParseFalse()
- {
- if (MatchValue(JavaScriptConvert.False, true))
- {
- SetToken(JsonToken.Boolean, false);
- }
- else
- {
- throw new JsonReaderException("Error parsing boolean value.");
- }
- }
-
void IDisposable.Dispose()
{
Dispose(true);
}
- private void Dispose(bool disposing)
+ protected virtual void Dispose(bool disposing)
{
if (_currentState != State.Closed && disposing)
Close();
@@ -982,18 +269,12 @@ namespace Newtonsoft.Json
///
/// Changes the to Closed.
///
- public void Close()
+ public virtual void Close()
{
_currentState = State.Closed;
_token = JsonToken.None;
_value = null;
_valueType = null;
-
- if (_reader != null)
- _reader.Close();
-
- if (_buffer != null)
- _buffer.Clear();
}
}
}
diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs
index 1f9d1932..633d00c6 100644
--- a/Src/Newtonsoft.Json/JsonSerializer.cs
+++ b/Src/Newtonsoft.Json/JsonSerializer.cs
@@ -33,6 +33,7 @@ using System.ComponentModel;
using Newtonsoft.Json.Utilities;
using System.Globalization;
using System.Linq;
+using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json
{
@@ -140,64 +141,22 @@ namespace Newtonsoft.Json
if (!reader.Read())
return null;
- return GetObject(reader, objectType);
+ if (objectType != null)
+ return GetObject(reader, objectType);
+ else
+ return CreateJToken(reader);
}
- private JavaScriptArray PopulateJavaScriptArray(JsonReader reader)
+ private JToken CreateJToken(JsonReader reader)
{
- JavaScriptArray jsArray = new JavaScriptArray();
-
- while (reader.Read())
+ JToken token;
+ using (JsonTokenWriter writer = new JsonTokenWriter())
{
- switch (reader.TokenType)
- {
- case JsonToken.EndArray:
- return jsArray;
- case JsonToken.Comment:
- break;
- default:
- object value = GetObject(reader, null);
-
- jsArray.Add(value);
- break;
- }
+ writer.WriteToken(reader);
+ token = writer.Token;
}
- throw new JsonSerializationException("Unexpected end while deserializing array.");
- }
-
- private JavaScriptObject PopulateJavaScriptObject(JsonReader reader)
- {
- JavaScriptObject jsObject = new JavaScriptObject();
-
- while (reader.Read())
- {
- switch (reader.TokenType)
- {
- case JsonToken.PropertyName:
- string memberName = reader.Value.ToString();
-
- // move to the value token. skip comments
- do
- {
- if (!reader.Read())
- throw new JsonSerializationException("Unexpected end while deserializing object.");
- } while (reader.TokenType == JsonToken.Comment);
-
- object value = GetObject(reader, null);
-
- jsObject[memberName] = value;
- break;
- case JsonToken.EndObject:
- return jsObject;
- case JsonToken.Comment:
- break;
- default:
- throw new JsonSerializationException("Unexpected token while deserializing object: " + reader.TokenType);
- }
- }
-
- throw new JsonSerializationException("Unexpected end while deserializing object.");
+ return token;
}
private object GetObject(JsonReader reader, Type objectType)
@@ -218,10 +177,10 @@ namespace Newtonsoft.Json
// populate a typed object or generic dictionary/array
// depending upon whether an objectType was supplied
case JsonToken.StartObject:
- value = (objectType != null) ? PopulateObject(reader, objectType) : PopulateJavaScriptObject(reader);
+ value = (objectType != null) ? PopulateObject(reader, objectType) : CreateJToken(reader);
break;
case JsonToken.StartArray:
- value = (objectType != null) ? PopulateList(reader, objectType) : PopulateJavaScriptArray(reader);
+ value = (objectType != null) ? PopulateList(reader, objectType) : CreateJToken(reader);
break;
case JsonToken.Integer:
case JsonToken.Float:
@@ -517,7 +476,7 @@ namespace Newtonsoft.Json
/// The to serialize.
public void Serialize(TextWriter textWriter, object value)
{
- Serialize(new JsonWriter(textWriter), value);
+ Serialize(new JsonTextWriter(textWriter), value);
}
///
@@ -531,7 +490,10 @@ namespace Newtonsoft.Json
if (jsonWriter == null)
throw new ArgumentNullException("jsonWriter");
- SerializeValue(jsonWriter, value);
+ if (value is JToken)
+ ((JToken)value).WriteTo(jsonWriter, (_converters != null) ? _converters.ToArray() : null);
+ else
+ SerializeValue(jsonWriter, value);
}
@@ -619,6 +581,10 @@ namespace Newtonsoft.Json
{
SerializeCollection(writer, (ICollection)value);
}
+ else if (value is IEnumerable)
+ {
+ SerializeEnumerable(writer, (IEnumerable)value);
+ }
else if (value is Identifier)
{
writer.WriteRaw(value.ToString());
@@ -631,11 +597,16 @@ namespace Newtonsoft.Json
private bool HasMatchingConverter(Type type, out JsonConverter matchingConverter)
{
- if (_converters != null)
+ return HasMatchingConverter(_converters, type, out matchingConverter);
+ }
+
+ internal static bool HasMatchingConverter(IList converters, Type type, out JsonConverter matchingConverter)
+ {
+ if (converters != null)
{
- for (int i = 0; i < _converters.Count; i++)
+ for (int i = 0; i < converters.Count; i++)
{
- JsonConverter converter = _converters[i];
+ JsonConverter converter = converters[i];
if (converter.CanConvert(type))
{
@@ -713,6 +684,11 @@ namespace Newtonsoft.Json
writer.SerializeStack.Remove(value);
}
+ private void SerializeEnumerable(JsonWriter writer, IEnumerable values)
+ {
+ SerializeList(writer, values.Cast().ToList());
+ }
+
private void SerializeCollection(JsonWriter writer, ICollection values)
{
object[] collectionValues = new object[values.Count];
diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs
new file mode 100644
index 00000000..1a8d9f35
--- /dev/null
+++ b/Src/Newtonsoft.Json/JsonTextReader.cs
@@ -0,0 +1,755 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using System.Xml;
+using System.Globalization;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
+ ///
+ public class JsonTextReader : JsonReader
+ {
+ private TextReader _reader;
+ private char _currentChar;
+
+ // current Token data
+ private StringBuffer _buffer;
+
+ ///
+ /// Initializes a new instance of the class with the specified .
+ ///
+ /// The TextReader containing the XML data to read.
+ public JsonTextReader(TextReader reader)
+ {
+ if (reader == null)
+ throw new ArgumentNullException("reader");
+
+ _reader = reader;
+ _buffer = new StringBuffer(4096);
+ }
+
+ private void ParseString(char quote)
+ {
+ bool stringTerminated = false;
+ bool hexNumber = false;
+ int hexCount = 0;
+
+ while (!stringTerminated && MoveNext())
+ {
+ if (hexNumber)
+ hexCount++;
+
+ switch (_currentChar)
+ {
+ case '\\':
+ if (MoveNext())
+ {
+ switch (_currentChar)
+ {
+ case 'b':
+ _buffer.Append('\b');
+ break;
+ case 't':
+ _buffer.Append('\t');
+ break;
+ case 'n':
+ _buffer.Append('\n');
+ break;
+ case 'f':
+ _buffer.Append('\f');
+ break;
+ case 'r':
+ _buffer.Append('\r');
+ break;
+ case 'u':
+ // note the start of a hex character
+ hexNumber = true;
+ break;
+ default:
+ _buffer.Append(_currentChar);
+ break;
+ }
+ }
+ else
+ {
+ throw new JsonReaderException("Unterminated string. Expected delimiter: " + quote);
+ }
+ break;
+ case '"':
+ case '\'':
+ if (_currentChar == quote)
+ stringTerminated = true;
+ else
+ goto default;
+ break;
+ default:
+ _buffer.Append(_currentChar);
+ break;
+ }
+
+ if (hexCount == 4)
+ {
+ // remove hex characters from buffer, convert to char and then add
+ string hexString = _buffer.ToString(_buffer.Position - 4, 4);
+ char hexChar = Convert.ToChar(int.Parse(hexString, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo));
+
+ _buffer.Position = _buffer.Position - 4;
+ _buffer.Append(hexChar);
+
+ hexNumber = false;
+ hexCount = 0;
+ }
+ }
+
+ if (!stringTerminated)
+ throw new JsonReaderException("Unterminated string. Expected delimiter: " + quote);
+
+ ClearCurrentChar();
+ string text = _buffer.ToString();
+ _buffer.Position = 0;
+
+ if (text.StartsWith("/Date(", StringComparison.Ordinal) && text.EndsWith(")/", StringComparison.Ordinal))
+ {
+ ParseDate(text);
+ }
+ else
+ {
+ SetToken(JsonToken.String, text);
+ QuoteChar = quote;
+ }
+ }
+
+ protected override void SetToken(JsonToken newToken, object value)
+ {
+ base.SetToken(newToken, value);
+
+ switch (newToken)
+ {
+ case JsonToken.StartObject:
+ ClearCurrentChar();
+ break;
+ case JsonToken.StartArray:
+ ClearCurrentChar();
+ break;
+ case JsonToken.StartConstructor:
+ ClearCurrentChar();
+ break;
+ case JsonToken.EndObject:
+ ClearCurrentChar();
+ break;
+ case JsonToken.EndArray:
+ ClearCurrentChar();
+ break;
+ case JsonToken.EndConstructor:
+ ClearCurrentChar();
+ break;
+ case JsonToken.PropertyName:
+ ClearCurrentChar();
+ break;
+ }
+ }
+
+ private void ParseDate(string text)
+ {
+ string value = text.Substring(6, text.Length - 8);
+ DateTimeKind kind = DateTimeKind.Utc;
+
+ int index = value.IndexOf('+', 1);
+
+ if (index == -1)
+ index = value.IndexOf('-', 1);
+
+ if (index != -1)
+ {
+ kind = DateTimeKind.Local;
+ value = value.Substring(0, index);
+ }
+
+ long javaScriptTicks = long.Parse(value);
+ DateTime utcDateTime = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
+ DateTime dateTime;
+
+ switch (kind)
+ {
+ case DateTimeKind.Unspecified:
+ dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
+ break;
+ case DateTimeKind.Local:
+ dateTime = utcDateTime.ToLocalTime();
+ break;
+ default:
+ dateTime = utcDateTime;
+ break;
+ }
+
+ SetToken(JsonToken.Date, dateTime);
+ }
+
+ private bool MoveNext()
+ {
+ int value = _reader.Read();
+
+ if (value != -1)
+ {
+ _currentChar = (char)value;
+ //_testBuffer.Append(_currentChar);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private bool HasNext()
+ {
+ return (_reader.Peek() != -1);
+ }
+
+ private char PeekNext()
+ {
+ return (char)_reader.Peek();
+ }
+
+ private void ClearCurrentChar()
+ {
+ _currentChar = '\0';
+ }
+
+ private bool MoveTo(char value)
+ {
+ while (MoveNext())
+ {
+ if (_currentChar == value)
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Reads the next Json token from the stream.
+ ///
+ ///
+ public override bool Read()
+ {
+ while (true)
+ {
+ if (_currentChar == '\0')
+ {
+ if (!MoveNext())
+ return false;
+ }
+
+ switch (CurrentState)
+ {
+ case State.Start:
+ case State.Property:
+ case State.Array:
+ case State.ArrayStart:
+ case State.Constructor:
+ case State.ConstructorStart:
+ return ParseValue();
+ case State.Complete:
+ break;
+ case State.Object:
+ case State.ObjectStart:
+ return ParseObject();
+ case State.PostValue:
+ // returns true if it hits
+ // end of object or array
+ if (ParsePostValue())
+ return true;
+ break;
+ case State.Closed:
+ break;
+ case State.Error:
+ break;
+ default:
+ throw new JsonReaderException("Unexpected state: " + CurrentState);
+ }
+ }
+ }
+
+ private bool ParsePostValue()
+ {
+ do
+ {
+ switch (_currentChar)
+ {
+ case '}':
+ SetToken(JsonToken.EndObject);
+ ClearCurrentChar();
+ return true;
+ case ']':
+ SetToken(JsonToken.EndArray);
+ ClearCurrentChar();
+ return true;
+ case ')':
+ SetToken(JsonToken.EndConstructor);
+ ClearCurrentChar();
+ return true;
+ case '/':
+ ParseComment();
+ return true;
+ case ',':
+ // finished paring
+ SetStateBasedOnCurrent();
+ ClearCurrentChar();
+ return false;
+ default:
+ if (char.IsWhiteSpace(_currentChar))
+ {
+ // eat whitespace
+ ClearCurrentChar();
+ }
+ else
+ {
+ throw new JsonReaderException("After parsing a value an unexpected character was encoutered: " + _currentChar);
+ }
+ break;
+ }
+ } while (MoveNext());
+
+ return false;
+ }
+
+ private bool ParseObject()
+ {
+ do
+ {
+ switch (_currentChar)
+ {
+ case '}':
+ SetToken(JsonToken.EndObject);
+ return true;
+ case '/':
+ ParseComment();
+ return true;
+ case ',':
+ SetToken(JsonToken.Undefined);
+ return true;
+ default:
+ if (char.IsWhiteSpace(_currentChar))
+ {
+ // eat
+ }
+ else
+ {
+ return ParseProperty();
+ }
+ break;
+ }
+ } while (MoveNext());
+
+ return false;
+ }
+
+ private bool ParseProperty()
+ {
+ if (ValidIdentifierChar(_currentChar))
+ {
+ ParseUnquotedProperty();
+ }
+ else if (_currentChar == '"' || _currentChar == '\'')
+ {
+ ParseQuotedProperty(_currentChar);
+ }
+ else
+ {
+ throw new JsonReaderException("Invalid property identifier character: " + _currentChar);
+ }
+
+ // finished property. move to colon
+ if (_currentChar != ':')
+ {
+ MoveTo(':');
+ }
+
+ SetToken(JsonToken.PropertyName, _buffer.ToString());
+ _buffer.Position = 0;
+
+ return true;
+ }
+
+ private void ParseQuotedProperty(char quoteChar)
+ {
+ // parse property name until quoted char is hit
+ while (MoveNext())
+ {
+ if (_currentChar == quoteChar)
+ {
+ return;
+ }
+ else
+ {
+ _buffer.Append(_currentChar);
+ }
+ }
+
+ throw new JsonReaderException("Unclosed quoted property. Expected: " + quoteChar);
+ }
+
+ private bool ValidIdentifierChar(char value)
+ {
+ return (char.IsLetterOrDigit(_currentChar) || _currentChar == '_' || _currentChar == '$');
+ }
+
+ private void ParseUnquotedProperty()
+ {
+ // parse unquoted property name until whitespace or colon
+ _buffer.Append(_currentChar);
+
+ while (MoveNext())
+ {
+ if (char.IsWhiteSpace(_currentChar) || _currentChar == ':')
+ {
+ break;
+ }
+ else if (ValidIdentifierChar(_currentChar))
+ {
+ _buffer.Append(_currentChar);
+ }
+ else
+ {
+ throw new JsonReaderException("Invalid JavaScript property identifier character: " + _currentChar);
+ }
+ }
+ }
+
+ private bool ParseValue()
+ {
+ do
+ {
+ switch (_currentChar)
+ {
+ case '"':
+ case '\'':
+ ParseString(_currentChar);
+ return true;
+ case 't':
+ ParseTrue();
+ return true;
+ case 'f':
+ ParseFalse();
+ return true;
+ case 'n':
+ if (HasNext())
+ {
+ char next = PeekNext();
+
+ if (next == 'u')
+ ParseNull();
+ else if (next == 'e')
+ ParseConstructor();
+ else
+ throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
+ }
+ else
+ {
+ throw new JsonReaderException("Unexpected end");
+ }
+ return true;
+ case '/':
+ ParseComment();
+ return true;
+ case 'u':
+ ParseUndefined();
+ return true;
+ case '{':
+ SetToken(JsonToken.StartObject);
+ return true;
+ case '[':
+ SetToken(JsonToken.StartArray);
+ return true;
+ case '}':
+ SetToken(JsonToken.EndObject);
+ return true;
+ case ']':
+ SetToken(JsonToken.EndArray);
+ return true;
+ case ',':
+ SetToken(JsonToken.Undefined);
+ //ClearCurrentChar();
+ return true;
+ case ')':
+ SetToken(JsonToken.EndConstructor);
+ return true;
+ default:
+ if (char.IsWhiteSpace(_currentChar))
+ {
+ // eat
+ }
+ else if (char.IsNumber(_currentChar) || _currentChar == '-' || _currentChar == '.')
+ {
+ ParseNumber();
+ return true;
+ }
+ else
+ {
+ throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
+ }
+ break;
+ }
+ } while (MoveNext());
+
+ return false;
+ }
+
+ private bool EatWhitespace(bool oneOrMore)
+ {
+ bool whitespace = false;
+ while (char.IsWhiteSpace(_currentChar))
+ {
+ whitespace = true;
+ MoveNext();
+ }
+
+ return (!oneOrMore || whitespace);
+ }
+
+ private void ParseConstructor()
+ {
+ if (MatchValue("new", true))
+ {
+ if (EatWhitespace(true))
+ {
+ while (char.IsLetter(_currentChar))
+ {
+ _buffer.Append(_currentChar);
+ MoveNext();
+ }
+
+ EatWhitespace(false);
+
+ if (_currentChar != '(')
+ throw new JsonReaderException("Unexpected character while parsing constructor: " + _currentChar);
+
+ string constructorName = _buffer.ToString();
+ _buffer.Position = 0;
+
+ SetToken(JsonToken.StartConstructor, constructorName);
+ }
+ }
+ }
+
+ private void ParseNumber()
+ {
+ // parse until seperator character or end
+ bool end = false;
+ do
+ {
+ if (CurrentIsSeperator())
+ end = true;
+ else
+ _buffer.Append(_currentChar);
+
+ } while (!end && MoveNext());
+
+ string number = _buffer.ToString();
+ object numberValue;
+ JsonToken numberType;
+
+ if (number.IndexOf('.') == -1)
+ {
+ numberValue = Convert.ToInt64(_buffer.ToString(), CultureInfo.InvariantCulture);
+ numberType = JsonToken.Integer;
+ }
+ else
+ {
+ numberValue = Convert.ToDouble(_buffer.ToString(), CultureInfo.InvariantCulture);
+ numberType = JsonToken.Float;
+ }
+
+ _buffer.Position = 0;
+
+ SetToken(numberType, numberValue);
+ }
+
+ private void ParseComment()
+ {
+ // should have already parsed / character before reaching this method
+
+ MoveNext();
+
+ if (_currentChar == '*')
+ {
+ while (MoveNext())
+ {
+ if (_currentChar == '*')
+ {
+ if (MoveNext())
+ {
+ if (_currentChar == '/')
+ {
+ break;
+ }
+ else
+ {
+ _buffer.Append('*');
+ _buffer.Append(_currentChar);
+ }
+ }
+ }
+ else
+ {
+ _buffer.Append(_currentChar);
+ }
+ }
+ }
+ else
+ {
+ throw new JsonReaderException("Error parsing comment. Expected: *");
+ }
+
+ SetToken(JsonToken.Comment, _buffer.ToString());
+
+ _buffer.Position = 0;
+
+ ClearCurrentChar();
+ }
+
+ private bool MatchValue(string value)
+ {
+ int i = 0;
+ do
+ {
+ if (_currentChar != value[i])
+ {
+ break;
+ }
+ i++;
+ }
+ while (i < value.Length && MoveNext());
+
+ return (i == value.Length);
+ }
+
+ private bool MatchValue(string value, bool noTrailingNonSeperatorCharacters)
+ {
+ // will match value and then move to the next character, checking that it is a seperator character
+ bool match = MatchValue(value);
+
+ if (!noTrailingNonSeperatorCharacters)
+ return match;
+ else
+ return (match && (!MoveNext() || CurrentIsSeperator()));
+ }
+
+ private bool CurrentIsSeperator()
+ {
+ switch (_currentChar)
+ {
+ case '}':
+ case ']':
+ case ',':
+ return true;
+ case '/':
+ // check next character to see if start of a comment
+ return (HasNext() && PeekNext() == '*');
+ case ')':
+ if (CurrentState == State.Constructor || CurrentState == State.ConstructorStart)
+ return true;
+ break;
+ default:
+ if (char.IsWhiteSpace(_currentChar))
+ return true;
+ break;
+ }
+
+ return false;
+ }
+
+ private void ParseTrue()
+ {
+ // check characters equal 'true'
+ // and that it is followed by either a seperator character
+ // or the text ends
+ if (MatchValue(JavaScriptConvert.True, true))
+ {
+ SetToken(JsonToken.Boolean, true);
+ }
+ else
+ {
+ throw new JsonReaderException("Error parsing boolean value.");
+ }
+ }
+
+ private void ParseNull()
+ {
+ if (MatchValue(JavaScriptConvert.Null, true))
+ {
+ SetToken(JsonToken.Null);
+ }
+ else
+ {
+ throw new JsonReaderException("Error parsing null value.");
+ }
+ }
+
+ private void ParseUndefined()
+ {
+ if (MatchValue(JavaScriptConvert.Undefined, true))
+ {
+ SetToken(JsonToken.Undefined);
+ }
+ else
+ {
+ throw new JsonReaderException("Error parsing undefined value.");
+ }
+ }
+
+ private void ParseFalse()
+ {
+ if (MatchValue(JavaScriptConvert.False, true))
+ {
+ SetToken(JsonToken.Boolean, false);
+ }
+ else
+ {
+ throw new JsonReaderException("Error parsing boolean value.");
+ }
+ }
+
+ ///
+ /// Changes the to Closed.
+ ///
+ public void Close()
+ {
+ base.Close();
+
+ if (_reader != null)
+ _reader.Close();
+
+ if (_buffer != null)
+ _buffer.Clear();
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs
new file mode 100644
index 00000000..d7ff55f0
--- /dev/null
+++ b/Src/Newtonsoft.Json/JsonTextWriter.cs
@@ -0,0 +1,441 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using System.Xml;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
+ ///
+ public class JsonTextWriter : JsonWriter
+ {
+ private TextWriter _writer;
+ private char _indentChar;
+ private int _indentation;
+ private char _quoteChar;
+ private bool _quoteName;
+
+ ///
+ /// Gets or sets how many IndentChars to write for each level in the hierarchy when is set to Formatting.Indented .
+ ///
+ public int Indentation
+ {
+ get { return _indentation; }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException("Indentation value must be greater than 0.");
+
+ _indentation = value;
+ }
+ }
+
+ ///
+ /// Gets or sets which character to use to quote attribute values.
+ ///
+ public char QuoteChar
+ {
+ get { return _quoteChar; }
+ set
+ {
+ if (value != '"' && value != '\'')
+ throw new ArgumentException(@"Invalid JavaScript string quote character. Valid quote characters are ' and "".");
+
+ _quoteChar = value;
+ }
+ }
+
+ ///
+ /// Gets or sets which character to use for indenting when is set to Formatting.Indented .
+ ///
+ public char IndentChar
+ {
+ get { return _indentChar; }
+ set { _indentChar = value; }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether object names will be surrounded with quotes.
+ ///
+ public bool QuoteName
+ {
+ get { return _quoteName; }
+ set { _quoteName = value; }
+ }
+
+ ///
+ /// Creates an instance of the JsonWriter class using the specified .
+ ///
+ /// The TextWriter to write to.
+ public JsonTextWriter(TextWriter textWriter)
+ {
+ if (textWriter == null)
+ throw new ArgumentNullException("textWriter");
+
+ _writer = textWriter;
+ _quoteChar = '"';
+ _quoteName = true;
+ _indentChar = ' ';
+ _indentation = 2;
+ }
+
+ ///
+ /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+ ///
+ public override void Flush()
+ {
+ _writer.Flush();
+ }
+
+ ///
+ /// Closes this stream and the underlying stream.
+ ///
+ public override void Close()
+ {
+ base.Close();
+
+ _writer.Close();
+ }
+
+ ///
+ /// Writes the beginning of a Json object.
+ ///
+ public override void WriteStartObject()
+ {
+ base.WriteStartObject();
+
+ _writer.Write("{");
+ }
+
+ ///
+ /// Writes the beginning of a Json array.
+ ///
+ public override void WriteStartArray()
+ {
+ base.WriteStartArray();
+
+ _writer.Write("[");
+ }
+
+ public override void WriteStartConstructor(string name)
+ {
+ base.WriteStartConstructor(name);
+
+ _writer.Write("new ");
+ _writer.Write(name);
+ _writer.Write("(");
+ }
+
+ protected override void WriteEnd(JsonToken token)
+ {
+ switch (token)
+ {
+ case JsonToken.EndObject:
+ _writer.Write("}");
+ break;
+ case JsonToken.EndArray:
+ _writer.Write("]");
+ break;
+ case JsonToken.EndConstructor:
+ _writer.Write(")");
+ break;
+ default:
+ throw new JsonWriterException("Invalid JsonToken: " + token);
+ }
+ }
+
+ ///
+ /// Writes the property name of a name/value pair on a Json object.
+ ///
+ ///
+ public override void WritePropertyName(string name)
+ {
+ base.WritePropertyName(name);
+
+ if (_quoteName)
+ _writer.Write(_quoteChar);
+
+ _writer.Write(name);
+
+ if (_quoteName)
+ _writer.Write(_quoteChar);
+
+ _writer.Write(':');
+ }
+
+ protected override void WriteIndent()
+ {
+ if (Formatting == Formatting.Indented)
+ {
+ _writer.Write(Environment.NewLine);
+ // for each level of object...
+ for (int i = 0; i < Top; i++)
+ {
+ // ...write the indent char the specified number of times
+ for (int j = 0; j < _indentation; j++)
+ {
+ _writer.Write(_indentChar);
+ }
+ }
+ }
+ }
+
+ protected override void WriteValueDelimiter()
+ {
+ _writer.Write(',');
+ }
+
+ protected override void WriteIndentSpace()
+ {
+ _writer.Write(' ');
+ }
+
+ private void WriteValueInternal(string value, JsonToken token)
+ {
+ _writer.Write(value);
+ }
+
+ #region WriteValue methods
+ ///
+ /// Writes a null value.
+ ///
+ public override void WriteNull()
+ {
+ base.WriteNull();
+ WriteValueInternal(JavaScriptConvert.Null, JsonToken.Null);
+ }
+
+ ///
+ /// Writes an undefined value.
+ ///
+ public override void WriteUndefined()
+ {
+ base.WriteUndefined();
+ WriteValueInternal(JavaScriptConvert.Undefined, JsonToken.Undefined);
+ }
+
+ ///
+ /// Writes raw JavaScript manually.
+ ///
+ /// The raw JavaScript to write.
+ public override void WriteRaw(string javaScript)
+ {
+ base.WriteRaw(javaScript);
+ // hack. some 'raw' or 'other' token perhaps?
+ WriteValueInternal(javaScript, JsonToken.Undefined);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(string value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value, _quoteChar), JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(int value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(uint value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(long value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(ulong value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(float value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(double value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(bool value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Boolean);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(short value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(ushort value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(char value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(byte value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(sbyte value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(decimal value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(DateTime value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(DateTimeOffset value)
+ {
+ base.WriteValue(value);
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
+ }
+ #endregion
+
+ ///
+ /// Writes out a comment /*...*/ containing the specified text.
+ ///
+ /// Text to place inside the comment.
+ public override void WriteComment(string text)
+ {
+ base.WriteComment(text);
+
+ _writer.Write("/*");
+ _writer.Write(text);
+ _writer.Write("*/");
+ }
+
+ ///
+ /// Writes out the given white space.
+ ///
+ /// The string of white space characters.
+ public override void WriteWhitespace(string ws)
+ {
+ base.WriteWhitespace(ws);
+
+ _writer.Write(ws);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs
index f488e6bf..69e3f282 100644
--- a/Src/Newtonsoft.Json/JsonWriter.cs
+++ b/Src/Newtonsoft.Json/JsonWriter.cs
@@ -29,17 +29,10 @@ using System.Text;
using System.IO;
using System.Xml;
using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json
{
- internal enum JsonType
- {
- Object,
- Array,
- Constructor,
- None
- }
-
///
/// Specifies the state of the .
///
@@ -95,7 +88,7 @@ namespace Newtonsoft.Json
///
/// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
///
- public class JsonWriter : IDisposable
+ public abstract class JsonWriter : IDisposable
{
private enum State
{
@@ -125,15 +118,11 @@ namespace Newtonsoft.Json
};
private int _top;
- private List _stack;
+
+ private List _stack;
private List _serializeStack;
- private TextWriter _writer;
- private Formatting _formatting;
- private char _indentChar;
- private int _indentation;
- private char _quoteChar;
- private bool _quoteName;
private State _currentState;
+ private Formatting _formatting;
internal List SerializeStack
{
@@ -146,6 +135,11 @@ namespace Newtonsoft.Json
}
}
+ protected int Top
+ {
+ get { return _top; }
+ }
+
///
/// Gets the state of the writer.
///
@@ -187,75 +181,19 @@ namespace Newtonsoft.Json
set { _formatting = value; }
}
- ///
- /// Gets or sets how many IndentChars to write for each level in the hierarchy when is set to Formatting.Indented .
- ///
- public int Indentation
- {
- get { return _indentation; }
- set
- {
- if (value < 0)
- throw new ArgumentException("Indentation value must be greater than 0.");
-
- _indentation = value;
- }
- }
-
- ///
- /// Gets or sets which character to use to quote attribute values.
- ///
- public char QuoteChar
- {
- get { return _quoteChar; }
- set
- {
- if (value != '"' && value != '\'')
- throw new ArgumentException(@"Invalid JavaScript string quote character. Valid quote characters are ' and "".");
-
- _quoteChar = value;
- }
- }
-
- ///
- /// Gets or sets which character to use for indenting when is set to Formatting.Indented .
- ///
- public char IndentChar
- {
- get { return _indentChar; }
- set { _indentChar = value; }
- }
-
- ///
- /// Gets or sets a value indicating whether object names will be surrounded with quotes.
- ///
- public bool QuoteName
- {
- get { return _quoteName; }
- set { _quoteName = value; }
- }
-
///
/// Creates an instance of the JsonWriter class using the specified .
///
/// The TextWriter to write to.
- public JsonWriter(TextWriter textWriter)
+ public JsonWriter()
{
- if (textWriter == null)
- throw new ArgumentNullException("textWriter");
-
- _writer = textWriter;
- _quoteChar = '"';
- _quoteName = true;
- _indentChar = ' ';
- _indentation = 2;
- _formatting = Formatting.None;
- _stack = new List(1);
- _stack.Add(JsonType.None);
+ _stack = new List(1);
+ _stack.Add(JsonTokenType.None);
_currentState = State.Start;
+ _formatting = Formatting.None;
}
- private void Push(JsonType value)
+ private void Push(JsonTokenType value)
{
_top++;
if (_stack.Count <= _top)
@@ -264,15 +202,15 @@ namespace Newtonsoft.Json
_stack[_top] = value;
}
- private JsonType Pop()
+ private JsonTokenType Pop()
{
- JsonType value = Peek();
+ JsonTokenType value = Peek();
_top--;
return value;
}
- private JsonType Peek()
+ private JsonTokenType Peek()
{
return _stack[_top];
}
@@ -280,31 +218,23 @@ namespace Newtonsoft.Json
///
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
///
- public void Flush()
- {
- _writer.Flush();
- }
+ public abstract void Flush();
///
/// Closes this stream and the underlying stream.
///
- public void Close()
+ public virtual void Close()
{
AutoCompleteAll();
-
- _writer.Close();
}
///
/// Writes the beginning of a Json object.
///
- public void WriteStartObject()
+ public virtual void WriteStartObject()
{
AutoComplete(JsonToken.StartObject);
-
- Push(JsonType.Object);
-
- _writer.Write("{");
+ Push(JsonTokenType.Object);
}
///
@@ -318,11 +248,10 @@ namespace Newtonsoft.Json
///
/// Writes the beginning of a Json array.
///
- public void WriteStartArray()
+ public virtual void WriteStartArray()
{
AutoComplete(JsonToken.StartArray);
- Push(JsonType.Array);
- _writer.Write("[");
+ Push(JsonTokenType.Array);
}
///
@@ -333,13 +262,10 @@ namespace Newtonsoft.Json
AutoCompleteClose(JsonToken.EndArray);
}
- public void WriteStartConstructor(string name)
+ public virtual void WriteStartConstructor(string name)
{
AutoComplete(JsonToken.StartConstructor);
- Push(JsonType.Constructor);
- _writer.Write("new ");
- _writer.Write(name);
- _writer.Write("(");
+ Push(JsonTokenType.Constructor);
}
public void WriteEndConstructor()
@@ -351,20 +277,9 @@ namespace Newtonsoft.Json
/// Writes the property name of a name/value pair on a Json object.
///
///
- public void WritePropertyName(string name)
+ public virtual void WritePropertyName(string name)
{
- //_objectStack.Push(new JsonObjectInfo(JsonType.Property));
AutoComplete(JsonToken.PropertyName);
-
- if (_quoteName)
- _writer.Write(_quoteChar);
-
- _writer.Write(name);
-
- if (_quoteName)
- _writer.Write(_quoteChar);
-
- _writer.Write(':');
}
///
@@ -375,17 +290,95 @@ namespace Newtonsoft.Json
WriteEnd(Peek());
}
- private void WriteEnd(JsonType type)
+ public void WriteToken(JsonReader reader)
+ {
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+
+ int currentDepth = (reader.TokenType == JsonToken.None) ? -1 : reader.Depth;
+ bool continue1;
+ do
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.None:
+ // read to next
+ break;
+ case JsonToken.StartObject:
+ WriteStartObject();
+ break;
+ case JsonToken.StartArray:
+ WriteStartArray();
+ break;
+ case JsonToken.StartConstructor:
+ WriteStartConstructor(reader.Value.ToString());
+ break;
+ case JsonToken.PropertyName:
+ WritePropertyName(reader.Value.ToString());
+ break;
+ case JsonToken.Comment:
+ WriteComment(reader.Value.ToString());
+ break;
+ case JsonToken.Integer:
+ WriteValue((long)reader.Value);
+ break;
+ case JsonToken.Float:
+ WriteValue((double)reader.Value);
+ break;
+ case JsonToken.String:
+ WriteValue(reader.Value.ToString());
+ break;
+ case JsonToken.Boolean:
+ WriteValue((bool)reader.Value);
+ break;
+ case JsonToken.Null:
+ WriteNull();
+ break;
+ case JsonToken.Undefined:
+ WriteUndefined();
+ break;
+ case JsonToken.EndObject:
+ WriteEndObject();
+ break;
+ case JsonToken.EndArray:
+ WriteEndArray();
+ break;
+ case JsonToken.EndConstructor:
+ WriteEndConstructor();
+ break;
+ case JsonToken.Date:
+ WriteValue((DateTime)reader.Value);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("TokenType", reader.TokenType, "Unexpected token type.");
+ }
+ }
+ while (reader.Read() && (currentDepth - 1 < reader.Depth || (currentDepth == reader.Depth && !IsEndToken(reader.TokenType))));
+ }
+
+ private bool IsEndToken(JsonToken token)
+ {
+ switch (token)
+ {
+ case JsonToken.EndObject:
+ case JsonToken.EndArray:
+ case JsonToken.EndConstructor:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void WriteEnd(JsonTokenType type)
{
switch (type)
{
- case JsonType.Object:
+ case JsonTokenType.Object:
WriteEndObject();
break;
- case JsonType.Array:
+ case JsonTokenType.Array:
WriteEndArray();
break;
- case JsonType.Constructor:
+ case JsonTokenType.Constructor:
WriteEndConstructor();
break;
default:
@@ -401,30 +394,30 @@ namespace Newtonsoft.Json
}
}
- private JsonType GetTypeForCloseToken(JsonToken token)
+ private JsonTokenType GetTypeForCloseToken(JsonToken token)
{
switch (token)
{
case JsonToken.EndObject:
- return JsonType.Object;
+ return JsonTokenType.Object;
case JsonToken.EndArray:
- return JsonType.Array;
+ return JsonTokenType.Array;
case JsonToken.EndConstructor:
- return JsonType.Constructor;
+ return JsonTokenType.Constructor;
default:
throw new JsonWriterException("No type for token: " + token);
}
}
- private JsonToken GetCloseTokenForType(JsonType type)
+ private JsonToken GetCloseTokenForType(JsonTokenType type)
{
switch (type)
{
- case JsonType.Object:
+ case JsonTokenType.Object:
return JsonToken.EndObject;
- case JsonType.Array:
+ case JsonTokenType.Array:
return JsonToken.EndArray;
- case JsonType.Constructor:
+ case JsonTokenType.Constructor:
return JsonToken.EndConstructor;
default:
throw new JsonWriterException("No close token for type: " + type);
@@ -458,33 +451,20 @@ namespace Newtonsoft.Json
if (_currentState != State.ObjectStart && _currentState != State.ArrayStart)
WriteIndent();
- switch (token)
- {
- case JsonToken.EndObject:
- _writer.Write("}");
- break;
- case JsonToken.EndArray:
- _writer.Write("]");
- break;
- case JsonToken.EndConstructor:
- _writer.Write(")");
- break;
- default:
- throw new JsonWriterException("Invalid JsonToken: " + token);
- }
+ WriteEnd(token);
}
- JsonType currentLevelType = Peek();
+ JsonTokenType currentLevelType = Peek();
switch (currentLevelType)
{
- case JsonType.Object:
+ case JsonTokenType.Object:
_currentState = State.Object;
break;
- case JsonType.Array:
+ case JsonTokenType.Array:
_currentState = State.Array;
break;
- case JsonType.None:
+ case JsonTokenType.None:
_currentState = State.Start;
break;
default:
@@ -492,21 +472,20 @@ namespace Newtonsoft.Json
}
}
- private void WriteIndent()
+ protected virtual void WriteEnd(JsonToken token)
+ {
+ }
+
+ protected virtual void WriteIndent()
+ {
+ }
+
+ protected virtual void WriteValueDelimiter()
+ {
+ }
+
+ protected virtual void WriteIndentSpace()
{
- if (_formatting == Formatting.Indented)
- {
- _writer.Write(Environment.NewLine);
- // for each level of object...
- for (int i = 0; i < _top; i++)
- {
- // ...write the indent char the specified number of times
- for (int j = 0; j < _indentation; j++)
- {
- _writer.Write(_indentChar);
- }
- }
- }
}
private void AutoComplete(JsonToken tokenBeingWritten)
@@ -538,12 +517,12 @@ namespace Newtonsoft.Json
if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment)
{
- _writer.Write(',');
+ WriteValueDelimiter();
}
else if (_currentState == State.Property)
{
if (_formatting == Formatting.Indented)
- _writer.Write(' ');
+ WriteIndentSpace();
}
// don't indent a property when it is the first token to be written (i.e. at the start)
@@ -556,182 +535,175 @@ namespace Newtonsoft.Json
_currentState = newState;
}
- private void WriteValueInternal(string value, JsonToken token)
- {
- AutoComplete(token);
-
- _writer.Write(value);
- }
-
#region WriteValue methods
///
/// Writes a null value.
///
- public void WriteNull()
+ public virtual void WriteNull()
{
- WriteValueInternal(JavaScriptConvert.Null, JsonToken.Null);
+ AutoComplete(JsonToken.Null);
}
///
/// Writes an undefined value.
///
- public void WriteUndefined()
+ public virtual void WriteUndefined()
{
- WriteValueInternal(JavaScriptConvert.Undefined, JsonToken.Undefined);
+ AutoComplete(JsonToken.Undefined);
}
///
/// Writes raw JavaScript manually.
///
/// The raw JavaScript to write.
- public void WriteRaw(string javaScript)
+ public virtual void WriteRaw(string javaScript)
{
// hack. some 'raw' or 'other' token perhaps?
- WriteValueInternal(javaScript, JsonToken.Undefined);
+ AutoComplete(JsonToken.Undefined);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(string value)
+ public virtual void WriteValue(string value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value, _quoteChar), JsonToken.String);
+ AutoComplete(JsonToken.String);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(int value)
+ public virtual void WriteValue(int value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.Integer);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(uint value)
+ public virtual void WriteValue(uint value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.Integer);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(long value)
+ public virtual void WriteValue(long value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.Integer);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(ulong value)
+ public virtual void WriteValue(ulong value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.Integer);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(float value)
+ public virtual void WriteValue(float value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
+ AutoComplete(JsonToken.Float);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(double value)
+ public virtual void WriteValue(double value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
+ AutoComplete(JsonToken.Float);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(bool value)
+ public virtual void WriteValue(bool value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Boolean);
+ AutoComplete(JsonToken.Boolean);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(short value)
+ public virtual void WriteValue(short value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.Integer);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(ushort value)
+ public virtual void WriteValue(ushort value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.Integer);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(char value)
+ public virtual void WriteValue(char value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.String);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(byte value)
+ public virtual void WriteValue(byte value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.Integer);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(sbyte value)
+ public virtual void WriteValue(sbyte value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
+ AutoComplete(JsonToken.Integer);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(decimal value)
+ public virtual void WriteValue(decimal value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
+ AutoComplete(JsonToken.Float);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(DateTime value)
+ public virtual void WriteValue(DateTime value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
+ AutoComplete(JsonToken.Date);
}
///
/// Writes a value.
///
/// The value to write.
- public void WriteValue(DateTimeOffset value)
+ public virtual void WriteValue(DateTimeOffset value)
{
- WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
+ AutoComplete(JsonToken.Date);
}
#endregion
@@ -739,30 +711,25 @@ namespace Newtonsoft.Json
/// Writes out a comment /*...*/ containing the specified text.
///
/// Text to place inside the comment.
- public void WriteComment(string text)
+ public virtual void WriteComment(string text)
{
AutoComplete(JsonToken.Comment);
-
- _writer.Write("/*");
- _writer.Write(text);
- _writer.Write("*/");
}
///
/// Writes out the given white space.
///
/// The string of white space characters.
- public void WriteWhitespace(string ws)
+ public virtual void WriteWhitespace(string ws)
{
if (ws != null)
{
if (!StringUtils.IsWhiteSpace(ws))
throw new JsonWriterException("Only white space characters should be used.");
-
- _writer.Write(ws);
}
}
+
void IDisposable.Dispose()
{
Dispose(true);
diff --git a/Src/Newtonsoft.Json/Linq/Extensions.cs b/Src/Newtonsoft.Json/Linq/Extensions.cs
index 0c7e7482..09e7ff2e 100644
--- a/Src/Newtonsoft.Json/Linq/Extensions.cs
+++ b/Src/Newtonsoft.Json/Linq/Extensions.cs
@@ -71,25 +71,75 @@ namespace Newtonsoft.Json.Linq
return source.SelectMany(d => d.Properties());
}
- public static IEnumerable PropertyValues(this IEnumerable source, string name)
+ public static IEnumerable Values(this IEnumerable source, object key)
+ {
+ return Values(source, key);
+ }
+
+ public static IEnumerable Values(this IEnumerable source)
+ {
+ return Values(source, null);
+ }
+
+ public static IEnumerable Values(this IEnumerable source, object key)
+ {
+ return Values(source, key);
+ }
+
+ public static IEnumerable Values(this IEnumerable source)
+ {
+ return Values(source, null);
+ }
+
+ //public static IEnumerable Values(this IEnumerable source, object key)
+ //{
+ // return Values(source, null);
+ //}
+
+ internal static IEnumerable Values(this IEnumerable source, object key) where T : JToken
{
ValidationUtils.ArgumentNotNull(source, "source");
- return source.SelectMany(d => d.Properties())
- .Where(p => string.Compare(p.Name, name, StringComparison.Ordinal) == 0)
- .Select(p => p.Value)
- .Convert();
+ foreach (JToken token in source)
+ {
+ if (key == null)
+ {
+ foreach (JToken t in token.Children())
+ {
+ yield return t.Convert(); ;
+ }
+ }
+ else
+ {
+ JToken value = token[key];
+ if (value != null)
+ yield return value.Convert();
+ }
+ }
+
+ yield break;
+
+ //IEnumerable allChildren = source.SelectMany(d => d.Children());
+ //IEnumerable childrenValues = (key != null) ? allChildren.Select(p => p[key]) : allChildren.SelectMany(p => p.Children());
+
+ //List s = childrenValues.Convert().ToList();
+ //return childrenValues.Convert();
+
+ // return source.SelectMany(d => d.Properties())
+ //.Where(p => string.Compare(p.Name, name, StringComparison.Ordinal) == 0)
+ //.Select(p => p.Value)
+ //.Convert();
}
//TODO
//public static IEnumerable InDocumentOrder(this IEnumerable source) where T : JObject;
- public static IEnumerable Children(this IEnumerable source) where T : JContainer
- {
- ValidationUtils.ArgumentNotNull(source, "source");
+ //public static IEnumerable Children(this IEnumerable source) where T : JToken
+ //{
+ // ValidationUtils.ArgumentNotNull(source, "source");
- return source.SelectMany(c => c.Children());
- }
+ // return source.SelectMany(c => c.Children());
+ //}
public static IEnumerable Children(this IEnumerable source)
{
@@ -126,6 +176,9 @@ namespace Newtonsoft.Json.Linq
}
else
{
+ if (token == null)
+ return default(U);
+
JValue value = token as JValue;
if (value == null)
throw new InvalidCastException(string.Format("Cannot cast {0} to {1}.", token.GetType(), typeof(T)));
diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs
index 34800436..aa679eb5 100644
--- a/Src/Newtonsoft.Json/Linq/JArray.cs
+++ b/Src/Newtonsoft.Json/Linq/JArray.cs
@@ -39,7 +39,12 @@ namespace Newtonsoft.Json.Linq
get { return JsonTokenType.Array; }
}
- public JArray(params object[] content) : this((object)content)
+ public JArray()
+ {
+ }
+
+ public JArray(params object[] content)
+ : this((object)content)
{
}
@@ -78,7 +83,7 @@ namespace Newtonsoft.Json.Linq
public static JArray Parse(string json)
{
- JsonReader jsonReader = new JsonReader(new StringReader(json));
+ JsonReader jsonReader = new JsonTextReader(new StringReader(json));
return Load(jsonReader);
}
@@ -91,16 +96,39 @@ namespace Newtonsoft.Json.Linq
throw new ArgumentException(string.Format("An item of type {0} cannot be added to content.", o.Type));
}
- public override void WriteTo(JsonWriter writer)
+ public static JArray FromObject(object o)
+ {
+ JToken token = FromObjectInternal(o);
+
+ if (token.Type != JsonTokenType.Array)
+ throw new ArgumentException(string.Format("Object serialized to {0}. JArray instance expected.", token.Type));
+
+ return (JArray)token;
+ }
+
+ public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
{
writer.WriteStartArray();
foreach (JToken token in Children())
{
- token.WriteTo(writer);
+ token.WriteTo(writer, converters);
}
writer.WriteEndArray();
}
+
+ public override JToken this[object key]
+ {
+ get
+ {
+ ValidationUtils.ArgumentNotNull(key, "o");
+
+ if (!(key is int))
+ throw new ArgumentException(string.Format("Accessed JArray values with invalid key value: {0}. Array position index expected.", MiscellaneousUtils.ToString(key)));
+
+ return GetIndex(this, (int)key);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/JConstructor.cs b/Src/Newtonsoft.Json/Linq/JConstructor.cs
index 7ab72d87..561ea255 100644
--- a/Src/Newtonsoft.Json/Linq/JConstructor.cs
+++ b/Src/Newtonsoft.Json/Linq/JConstructor.cs
@@ -77,16 +77,29 @@ namespace Newtonsoft.Json.Linq
}
}
- public override void WriteTo(JsonWriter writer)
+ public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
{
writer.WriteStartConstructor(_name);
foreach (JToken token in Children())
{
- token.WriteTo(writer);
+ token.WriteTo(writer, converters);
}
writer.WriteEndConstructor();
}
+
+ public override JToken this[object key]
+ {
+ get
+ {
+ ValidationUtils.ArgumentNotNull(key, "o");
+
+ if (!(key is int))
+ throw new ArgumentException(string.Format("Accessed JConstructor values with invalid key value: {0}. Argument position index expected.", MiscellaneousUtils.ToString(key)));
+
+ return GetIndex(this, (int)key);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs
index 11c1b3f1..d6319c64 100644
--- a/Src/Newtonsoft.Json/Linq/JContainer.cs
+++ b/Src/Newtonsoft.Json/Linq/JContainer.cs
@@ -42,7 +42,7 @@ namespace Newtonsoft.Json.Linq
set { _content = value; }
}
- public JToken First
+ public override JToken First
{
get
{
@@ -53,12 +53,17 @@ namespace Newtonsoft.Json.Linq
}
}
- public JToken Last
+ public override JToken Last
{
get { return _content; }
}
- public IEnumerable Children()
+ public override JEnumerable Children()
+ {
+ return new JEnumerable(ChildrenInternal());
+ }
+
+ private IEnumerable ChildrenInternal()
{
JToken first = First;
JToken current = first;
@@ -71,11 +76,18 @@ namespace Newtonsoft.Json.Linq
} while ((current = current.Next) != first);
}
- public IEnumerable Children()
+ public override IEnumerable Children()
{
return Children().Convert();
}
+ public override T Value(object key)
+ {
+ JToken token = this[key];
+
+ return Extensions.Convert(token);
+ }
+
public IEnumerable Descendants()
{
foreach (JToken o in Children())
@@ -92,9 +104,35 @@ namespace Newtonsoft.Json.Linq
}
}
+ internal static JToken FromObjectInternal(object o)
+ {
+ ValidationUtils.ArgumentNotNull(o, "o");
+
+ JsonSerializer jsonSerializer = new JsonSerializer();
+
+ JToken token;
+ using (JsonTokenWriter jsonWriter = new JsonTokenWriter())
+ {
+ jsonSerializer.Serialize(jsonWriter, o);
+ token = jsonWriter.Token;
+ }
+
+ return token;
+ }
+
+ internal static JToken GetIndex(JContainer c, object o)
+ {
+ return c.Children().ElementAt((int)o);
+ }
+
+ internal bool IsMultiContent(object content)
+ {
+ return (content is IEnumerable && !(content is string));
+ }
+
public virtual void Add(object content)
{
- if (content is IEnumerable && !(content is string))
+ if (IsMultiContent(content))
{
IEnumerable enumerable = content as IEnumerable;
foreach (object c in enumerable)
diff --git a/Src/Newtonsoft.Json/Linq/JEnumerable.cs b/Src/Newtonsoft.Json/Linq/JEnumerable.cs
new file mode 100644
index 00000000..8e549289
--- /dev/null
+++ b/Src/Newtonsoft.Json/Linq/JEnumerable.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+
+namespace Newtonsoft.Json.Linq
+{
+ public struct JEnumerable : IEnumerable where T : JToken
+ {
+ public static readonly JEnumerable Empty = new JEnumerable(Enumerable.Empty());
+
+ private IEnumerable _enumerable;
+
+ public JEnumerable(IEnumerable enumerable)
+ {
+ ValidationUtils.ArgumentNotNull(enumerable, "enumerable");
+
+ _enumerable = enumerable;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _enumerable.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerable this[object key]
+ {
+ get { return Extensions.Values(_enumerable, key); }
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs
index 5bcd9079..b639a44c 100644
--- a/Src/Newtonsoft.Json/Linq/JObject.cs
+++ b/Src/Newtonsoft.Json/Linq/JObject.cs
@@ -64,24 +64,41 @@ namespace Newtonsoft.Json.Linq
.SingleOrDefault();
}
- public IEnumerable PropertyValues()
+ public JEnumerable PropertyValues()
{
- return Properties().Select(p => p.Value);
+ return new JEnumerable(Properties().Select(p => p.Value));
}
- public T PropertyValue(string name)
+ public override void Add(object content)
{
- JProperty property = Property(name);
+ ValidationUtils.ArgumentNotNull(content, "content");
- if (property == null)
- throw new Exception(string.Format("Property '{0}' does not exist in JSON object.", name));
+ if (!(content is JProperty) && !IsMultiContent(content))
+ throw new ArgumentException(string.Format("Error adding {0} to JObject. JObject only supports JProperty content.", content.GetType().Name));
- // HACK
- return Extensions.Convert(property.Value);
+ base.Add(content);
+ }
+
+ public override JToken this[object key]
+ {
+ get
+ {
+ ValidationUtils.ArgumentNotNull(key, "o");
+
+ string propertyName = key as string;
+ if (propertyName == null)
+ throw new ArgumentException(string.Format("Accessed JObject values with invalid key value: {0}. Object property name expected.", MiscellaneousUtils.ToString(key)));
+
+ JProperty property = Property(propertyName);
+
+ return (property != null) ? property.Value : null;
+ }
}
public static JObject Load(JsonReader reader)
{
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+
if (reader.TokenType == JsonToken.None)
{
if (!reader.Read())
@@ -105,11 +122,21 @@ namespace Newtonsoft.Json.Linq
public static JObject Parse(string json)
{
- JsonReader jsonReader = new JsonReader(new StringReader(json));
+ JsonReader jsonReader = new JsonTextReader(new StringReader(json));
return Load(jsonReader);
}
+ public static JObject FromObject(object o)
+ {
+ JToken token = FromObjectInternal(o);
+
+ if (token.Type != JsonTokenType.Object)
+ throw new ArgumentException(string.Format("Object serialized to {0}. JObject instance expected.", token.Type));
+
+ return (JObject)token;
+ }
+
internal override void ValidateObject(JToken o, JToken previous)
{
ValidationUtils.ArgumentNotNull(o, "o");
@@ -118,13 +145,13 @@ namespace Newtonsoft.Json.Linq
throw new ArgumentException(string.Format("An item of type {0} cannot be added to content.", o.Type));
}
- public override void WriteTo(JsonWriter writer)
+ public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
{
writer.WriteStartObject();
foreach (JProperty property in Properties())
{
- property.WriteTo(writer);
+ property.WriteTo(writer, converters);
}
writer.WriteEndObject();
diff --git a/Src/Newtonsoft.Json/Linq/JProperty.cs b/Src/Newtonsoft.Json/Linq/JProperty.cs
index ed1080b5..aba52709 100644
--- a/Src/Newtonsoft.Json/Linq/JProperty.cs
+++ b/Src/Newtonsoft.Json/Linq/JProperty.cs
@@ -56,7 +56,7 @@ namespace Newtonsoft.Json.Linq
public JProperty(string name)
{
- ValidationUtils.ArgumentNotNullOrEmpty(name, "name");
+ ValidationUtils.ArgumentNotNull(name, "name");
_name = name;
}
@@ -77,10 +77,10 @@ namespace Newtonsoft.Json.Linq
throw new ArgumentException(string.Format("An item of type {0} cannot be added to content.", o.Type));
}
- public override void WriteTo(JsonWriter writer)
+ public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
{
writer.WritePropertyName(_name);
- Value.WriteTo(writer);
+ Value.WriteTo(writer, converters);
}
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs
index 9dd5f1fb..e3669a3b 100644
--- a/Src/Newtonsoft.Json/Linq/JToken.cs
+++ b/Src/Newtonsoft.Json/Linq/JToken.cs
@@ -107,15 +107,35 @@ namespace Newtonsoft.Json.Linq
yield return o;
}
- //public IEnumerable ObjectsAfterSelf()
- //{
- // return null;
- //}
+ public virtual JToken this[object key]
+ {
+ get { return null; }
+ }
- //public IEnumerable ObjectsBeforeSelf()
- //{
- // return null;
- //}
+ public virtual T Value(object key)
+ {
+ return default(T);
+ }
+
+ public virtual JToken First
+ {
+ get { return null; }
+ }
+
+ public virtual JToken Last
+ {
+ get { return null; }
+ }
+
+ public virtual JEnumerable Children()
+ {
+ return JEnumerable.Empty;
+ }
+
+ public virtual IEnumerable Children()
+ {
+ return Enumerable.Empty();
+ }
public void Remove()
{
@@ -129,13 +149,18 @@ namespace Newtonsoft.Json.Linq
{
}
- public abstract void WriteTo(JsonWriter writer);
+ public abstract void WriteTo(JsonWriter writer, params JsonConverter[] converters);
public override string ToString()
+ {
+ return ToString(null);
+ }
+
+ private string ToString(params JsonConverter[] converters)
{
using (StringWriter sw = new StringWriter())
{
- JsonWriter jw = new JsonWriter(sw);
+ JsonTextWriter jw = new JsonTextWriter(sw);
jw.Formatting = Formatting.Indented;
WriteTo(jw);
@@ -410,6 +435,5 @@ namespace Newtonsoft.Json.Linq
return (ulong)v.Value;
}
#endregion
-
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs
index e5cbce05..e33e20ef 100644
--- a/Src/Newtonsoft.Json/Linq/JValue.cs
+++ b/Src/Newtonsoft.Json/Linq/JValue.cs
@@ -84,12 +84,12 @@ namespace Newtonsoft.Json.Linq
return JsonTokenType.Null;
else if (value is string)
return JsonTokenType.String;
- else if (value is long || value is int || value is short
- || value is ulong || value is uint || value is ushort)
+ else if (value is long || value is int || value is short || value is sbyte
+ || value is ulong || value is uint || value is ushort || value is byte)
return JsonTokenType.Integer;
- else if (value is double || value is float)
+ else if (value is double || value is float || value is decimal)
return JsonTokenType.Float;
- else if (value is DateTime)
+ else if (value is DateTime || value is DateTimeOffset)
return JsonTokenType.Date;
else if (value is bool)
return JsonTokenType.Boolean;
@@ -113,7 +113,18 @@ namespace Newtonsoft.Json.Linq
return new JValue(value, JsonTokenType.String);
}
- public override void WriteTo(JsonWriter writer)
+ private static void WriteConvertableValue(JsonWriter writer, IList converters, Action _defaultWrite, object value)
+ {
+ JsonConverter matchingConverter;
+
+ JsonSerializer.HasMatchingConverter(converters, value.GetType(), out matchingConverter);
+ if (matchingConverter != null)
+ matchingConverter.WriteJson(writer, value);
+ else
+ _defaultWrite(value);
+ }
+
+ public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
{
switch (_valueType)
{
@@ -121,16 +132,25 @@ namespace Newtonsoft.Json.Linq
writer.WriteComment(_value.ToString());
break;
case JsonTokenType.Integer:
- writer.WriteValue(Convert.ToInt64(_value));
+ WriteConvertableValue(writer, converters, v => writer.WriteValue(Convert.ToInt64(v)), _value);
break;
case JsonTokenType.Float:
- writer.WriteValue(Convert.ToDouble(_value));
+ WriteConvertableValue(writer, converters, v => writer.WriteValue(Convert.ToDouble(v)), _value);
break;
case JsonTokenType.String:
- writer.WriteValue(_value.ToString());
+ WriteConvertableValue(writer, converters, v => writer.WriteValue(v.ToString()), _value);
break;
case JsonTokenType.Boolean:
- writer.WriteValue(Convert.ToBoolean(_value));
+ WriteConvertableValue(writer, converters, v => writer.WriteValue(Convert.ToBoolean(v)), _value);
+ break;
+ case JsonTokenType.Date:
+ WriteConvertableValue(writer, converters, v =>
+ {
+ if (v is DateTimeOffset)
+ writer.WriteValue((DateTimeOffset)v);
+ else
+ writer.WriteValue(Convert.ToDateTime(v));
+ }, _value);
break;
case JsonTokenType.Null:
writer.WriteNull();
@@ -138,9 +158,6 @@ namespace Newtonsoft.Json.Linq
case JsonTokenType.Undefined:
writer.WriteUndefined();
break;
- case JsonTokenType.Date:
- writer.WriteValue(Convert.ToDateTime(_value));
- break;
default:
throw new ArgumentOutOfRangeException("TokenType", _valueType, "Unexpected token type.");
}
diff --git a/Src/Newtonsoft.Json/Linq/JsonTokenReader.cs b/Src/Newtonsoft.Json/Linq/JsonTokenReader.cs
new file mode 100644
index 00000000..216a0d25
--- /dev/null
+++ b/Src/Newtonsoft.Json/Linq/JsonTokenReader.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq
+{
+ public class JsonTokenReader : JsonReader
+ {
+ private JToken _root;
+ private JToken _parent;
+ private JToken _current;
+
+ public JsonTokenReader(JToken token)
+ {
+ ValidationUtils.ArgumentNotNull(token, "token");
+
+ _root = token;
+ _current = token;
+ }
+
+ public override bool Read()
+ {
+ if (CurrentState != State.Start)
+ {
+ JContainer container = _current as JContainer;
+ if (container != null && _parent != container)
+ return ReadInto(container);
+ else
+ return ReadOver(_current);
+ }
+
+ SetToken(_current);
+ return true;
+ }
+
+ private bool ReadOver(JToken t)
+ {
+ if (t == _root)
+ return ReadToEnd();
+
+ JToken next = t.Next;
+ if ((next == null || next == t) || t == t.Parent.Last)
+ {
+ if (t.Parent == null)
+ return ReadToEnd();
+
+ return SetEnd(t.Parent);
+ }
+ else
+ {
+ _current = next;
+ SetToken(_current);
+ return true;
+ }
+ }
+
+ private bool ReadToEnd()
+ {
+ //CurrentState = State.Finished;
+ return false;
+ }
+
+ private JsonToken? GetEndToken(JContainer c)
+ {
+ switch (c.Type)
+ {
+ case JsonTokenType.Object:
+ return JsonToken.EndObject;
+ case JsonTokenType.Array:
+ return JsonToken.EndArray;
+ case JsonTokenType.Constructor:
+ return JsonToken.EndConstructor;
+ case JsonTokenType.Property:
+ return null;
+ default:
+ throw new ArgumentOutOfRangeException("Type", c.Type, "Unexpected JContainer type.");
+ }
+ }
+
+ private bool ReadInto(JContainer c)
+ {
+ JToken firstChild = c.First;
+ if (firstChild == null)
+ {
+ return SetEnd(c);
+ }
+ else
+ {
+ SetToken(firstChild);
+ _current = firstChild;
+ _parent = c;
+ return true;
+ }
+ }
+
+ private bool SetEnd(JContainer c)
+ {
+ JsonToken? endToken = GetEndToken(c);
+ if (endToken != null)
+ {
+ SetToken(endToken.Value);
+ _current = c;
+ _parent = c;
+ return true;
+ }
+ else
+ {
+ return ReadOver(c);
+ }
+ }
+
+ private void SetToken(JToken token)
+ {
+ switch (token.Type)
+ {
+ case JsonTokenType.Object:
+ SetToken(JsonToken.StartObject);
+ break;
+ case JsonTokenType.Array:
+ SetToken(JsonToken.StartArray);
+ break;
+ case JsonTokenType.Constructor:
+ SetToken(JsonToken.StartConstructor);
+ break;
+ case JsonTokenType.Property:
+ SetToken(JsonToken.PropertyName, ((JProperty)token).Name);
+ break;
+ case JsonTokenType.Comment:
+ SetToken(JsonToken.Comment, ((JValue)token).Value);
+ break;
+ case JsonTokenType.Integer:
+ SetToken(JsonToken.Integer, ((JValue)token).Value);
+ break;
+ case JsonTokenType.Float:
+ SetToken(JsonToken.Float, ((JValue)token).Value);
+ break;
+ case JsonTokenType.String:
+ SetToken(JsonToken.String, ((JValue)token).Value);
+ break;
+ case JsonTokenType.Boolean:
+ SetToken(JsonToken.Boolean, ((JValue)token).Value);
+ break;
+ case JsonTokenType.Null:
+ SetToken(JsonToken.Null, ((JValue)token).Value);
+ break;
+ case JsonTokenType.Undefined:
+ SetToken(JsonToken.Undefined, ((JValue)token).Value);
+ break;
+ case JsonTokenType.Date:
+ SetToken(JsonToken.Date, ((JValue)token).Value);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("Type", token.Type, "Unexpected JsonTokenType.");
+ }
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json/Linq/JsonTokenType.cs b/Src/Newtonsoft.Json/Linq/JsonTokenType.cs
index 332b711b..05c1d232 100644
--- a/Src/Newtonsoft.Json/Linq/JsonTokenType.cs
+++ b/Src/Newtonsoft.Json/Linq/JsonTokenType.cs
@@ -32,6 +32,7 @@ namespace Newtonsoft.Json.Linq
{
public enum JsonTokenType
{
+ None,
Object,
Array,
Constructor,
diff --git a/Src/Newtonsoft.Json/Linq/JsonTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JsonTokenWriter.cs
new file mode 100644
index 00000000..265b42f8
--- /dev/null
+++ b/Src/Newtonsoft.Json/Linq/JsonTokenWriter.cs
@@ -0,0 +1,306 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq
+{
+ public class JsonTokenWriter : JsonWriter
+ {
+ private JContainer _token;
+ private JContainer _parent;
+
+ public JContainer Token
+ {
+ get { return _token; }
+ }
+
+ public JsonTokenWriter(JContainer container)
+ {
+ ValidationUtils.ArgumentNotNull(container, "container");
+
+ _token = container;
+ _parent = container;
+ }
+
+ public JsonTokenWriter()
+ {
+ }
+
+ ///
+ /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+ ///
+ public override void Flush()
+ {
+ }
+
+ ///
+ /// Closes this stream and the underlying stream.
+ ///
+ public override void Close()
+ {
+ base.Close();
+ }
+
+ ///
+ /// Writes the beginning of a Json object.
+ ///
+ public override void WriteStartObject()
+ {
+ base.WriteStartObject();
+
+ AddParent(new JObject());
+ }
+
+ private void AddParent(JContainer container)
+ {
+ if (_parent == null)
+ _token = container;
+ else
+ _parent.Add(container);
+
+ _parent = container;
+ }
+
+ private void RemoveParent()
+ {
+ _parent = _parent.Parent;
+
+ if (_parent != null && _parent.Type == JsonTokenType.Property)
+ _parent = _parent.Parent;
+ }
+
+ ///
+ /// Writes the beginning of a Json array.
+ ///
+ public override void WriteStartArray()
+ {
+ base.WriteStartArray();
+
+ AddParent(new JArray());
+ }
+
+ public override void WriteStartConstructor(string name)
+ {
+ base.WriteStartConstructor(name);
+
+ AddParent(new JConstructor());
+ }
+
+ protected override void WriteEnd(JsonToken token)
+ {
+ RemoveParent();
+ }
+
+ ///
+ /// Writes the property name of a name/value pair on a Json object.
+ ///
+ ///
+ public override void WritePropertyName(string name)
+ {
+ base.WritePropertyName(name);
+
+ AddParent(new JProperty(name));
+ }
+
+ private void AddValue(object value, JsonToken token)
+ {
+ _parent.Add(new JValue(value));
+
+ if (_parent.Type == JsonTokenType.Property)
+ _parent = _parent.Parent;
+ }
+
+ #region WriteValue methods
+ ///
+ /// Writes a null value.
+ ///
+ public override void WriteNull()
+ {
+ base.WriteNull();
+ AddValue(null, JsonToken.Null);
+ }
+
+ ///
+ /// Writes an undefined value.
+ ///
+ public override void WriteUndefined()
+ {
+ base.WriteUndefined();
+ AddValue(null, JsonToken.Undefined);
+ }
+
+ ///
+ /// Writes raw JavaScript manually.
+ ///
+ /// The raw JavaScript to write.
+ public override void WriteRaw(string javaScript)
+ {
+ base.WriteRaw(javaScript);
+ // hack. some 'raw' or 'other' token perhaps?
+ AddValue(javaScript, JsonToken.Undefined);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(string value)
+ {
+ base.WriteValue(value);
+ AddValue(value ?? string.Empty, JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(int value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(uint value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(long value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(ulong value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(float value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(double value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(bool value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Boolean);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(short value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(ushort value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(char value)
+ {
+ base.WriteValue(value);
+ AddValue(value.ToString(), JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(byte value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(sbyte value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(decimal value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(DateTime value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Date);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(DateTimeOffset value)
+ {
+ base.WriteValue(value);
+ AddValue(value, JsonToken.Date);
+ }
+ #endregion
+ }
+}
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
index 530039ee..5ad7487f 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
@@ -78,15 +78,13 @@
-
-
+
+
-
-
@@ -96,8 +94,11 @@
+
+
+
diff --git a/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs b/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs
index 00d81359..f4fbdc37 100644
--- a/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs
+++ b/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs
@@ -78,7 +78,10 @@ namespace Newtonsoft.Json.Utilities
public static string ToString(object value)
{
- return (value != null) ? value.ToString() : "{null}";
+ if (value == null)
+ return "{null}";
+
+ return (value is string) ? @"""" + value.ToString() + @"""" : value.ToString();
}
}
}