New features

-New, more concise, LINQ to JSON querying syntax.
-Added FromObject to JObject, JArray.
-JToken WriteTo method now supports JsonConverters.
-JsonSerializer supports serializing to and from LINQ to JSON objects.
-JsonSerializer properly serializes IEnumerable objects.
-Added Depth property to JsonReader.

Changes
-Made JsonReader and JsonWriter abstract. Added JsonTextReader/JsonNodeReader and JsonTextWriter/JsonNodeWriter.
-Removed JavaScriptObject, JavaScriptArray. Replaced by LINQ to JSON objects.
This commit is contained in:
JamesNK
2008-03-02 03:25:47 +00:00
parent 82e86cdcc7
commit 8a64988cb6
24 changed files with 2227 additions and 1341 deletions
-64
View File
@@ -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
{
/// <summary>
/// Represents a JavaScript array.
/// </summary>
public class JavaScriptArray : List<object>
{
/// <summary>
/// Initializes a new instance of the <see cref="JavaScriptObject"/> class.
/// </summary>
public JavaScriptArray()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JavaScriptArray"/> class that
/// contains elements copied from the specified collection.
/// </summary>
/// <param name="collection">The collection whose elements are copied to the new array.</param>
public JavaScriptArray(IEnumerable<object> collection)
: base(collection)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JavaScriptArray"/> class that
/// is empty and has the specified initial capacity.
/// </summary>
/// <param name="capacity">The number of elements that the new array can initially store.</param>
public JavaScriptArray(int capacity)
: base(capacity)
{
}
}
}
@@ -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
{
/// <summary>
/// Represents a JavaScript constructor.
/// </summary>
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();
}
}
}
+2 -2
View File
@@ -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);
}
-55
View File
@@ -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
{
/// <summary>
/// Represents a JavaScript object.
/// </summary>
public class JavaScriptObject : Dictionary<string, object>
{
/// <summary>
/// Initializes a new instance of the <see cref="JavaScriptObject"/> class.
/// </summary>
public JavaScriptObject()
: base(EqualityComparer<string>.Default)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JavaScriptObject"/> class that
/// contains values copied from the specified <see cref="JavaScriptObject"/>.
/// </summary>
/// <param name="javaScriptObject">The <see cref="JavaScriptObject"/> whose elements are copied to the new object.</param>
public JavaScriptObject(JavaScriptObject javaScriptObject)
: base(javaScriptObject, EqualityComparer<string>.Default)
{
}
}
}
@@ -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<object>
{
public static readonly JavaScriptParameters Empty = new JavaScriptParameters(new List<object>());
public JavaScriptParameters(IList<object> list)
: base(list)
{
}
}
}
+45 -764
View File
@@ -29,15 +29,16 @@ using System.Text;
using System.IO;
using System.Xml;
using System.Globalization;
using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json
{
/// <summary>
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
/// </summary>
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<JsonType> _stack;
private List<JsonTokenType> _stack;
/// <summary>
/// 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; }
}
/// <summary>
@@ -101,409 +105,55 @@ namespace Newtonsoft.Json
get { return _valueType; }
}
public int Depth
{
get { return _top - 1; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
/// </summary>
/// <param name="reader">The <c>TextReader</c> containing the XML data to read.</param>
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<JsonType>();
_stack = new List<JsonTokenType>();
_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;
}
/// <summary>
/// Reads the next Json token from the stream.
/// </summary>
/// <returns></returns>
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<object> parameters = new List<object>();
// 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
/// <summary>
/// Changes the <see cref="State"/> to Closed.
/// </summary>
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();
}
}
}
+35 -59
View File
@@ -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
/// <param name="value">The <see cref="Object"/> to serialize.</param>
public void Serialize(TextWriter textWriter, object value)
{
Serialize(new JsonWriter(textWriter), value);
Serialize(new JsonTextWriter(textWriter), value);
}
/// <summary>
@@ -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<JsonConverter> 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<object>().ToList());
}
private void SerializeCollection(JsonWriter writer, ICollection values)
{
object[] collectionValues = new object[values.Count];
+755
View File
@@ -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
{
/// <summary>
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
/// </summary>
public class JsonTextReader : JsonReader
{
private TextReader _reader;
private char _currentChar;
// current Token data
private StringBuffer _buffer;
/// <summary>
/// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
/// </summary>
/// <param name="reader">The <c>TextReader</c> containing the XML data to read.</param>
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;
}
/// <summary>
/// Reads the next Json token from the stream.
/// </summary>
/// <returns></returns>
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.");
}
}
/// <summary>
/// Changes the <see cref="State"/> to Closed.
/// </summary>
public void Close()
{
base.Close();
if (_reader != null)
_reader.Close();
if (_buffer != null)
_buffer.Clear();
}
}
}
+441
View File
@@ -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
{
/// <summary>
/// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
/// </summary>
public class JsonTextWriter : JsonWriter
{
private TextWriter _writer;
private char _indentChar;
private int _indentation;
private char _quoteChar;
private bool _quoteName;
/// <summary>
/// Gets or sets how many IndentChars to write for each level in the hierarchy when <paramref name="Formatting"/> is set to <c>Formatting.Indented</c>.
/// </summary>
public int Indentation
{
get { return _indentation; }
set
{
if (value < 0)
throw new ArgumentException("Indentation value must be greater than 0.");
_indentation = value;
}
}
/// <summary>
/// Gets or sets which character to use to quote attribute values.
/// </summary>
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;
}
}
/// <summary>
/// Gets or sets which character to use for indenting when <paramref name="Formatting"/> is set to <c>Formatting.Indented</c>.
/// </summary>
public char IndentChar
{
get { return _indentChar; }
set { _indentChar = value; }
}
/// <summary>
/// Gets or sets a value indicating whether object names will be surrounded with quotes.
/// </summary>
public bool QuoteName
{
get { return _quoteName; }
set { _quoteName = value; }
}
/// <summary>
/// Creates an instance of the <c>JsonWriter</c> class using the specified <see cref="TextWriter"/>.
/// </summary>
/// <param name="textWriter">The <c>TextWriter</c> to write to.</param>
public JsonTextWriter(TextWriter textWriter)
{
if (textWriter == null)
throw new ArgumentNullException("textWriter");
_writer = textWriter;
_quoteChar = '"';
_quoteName = true;
_indentChar = ' ';
_indentation = 2;
}
/// <summary>
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
/// </summary>
public override void Flush()
{
_writer.Flush();
}
/// <summary>
/// Closes this stream and the underlying stream.
/// </summary>
public override void Close()
{
base.Close();
_writer.Close();
}
/// <summary>
/// Writes the beginning of a Json object.
/// </summary>
public override void WriteStartObject()
{
base.WriteStartObject();
_writer.Write("{");
}
/// <summary>
/// Writes the beginning of a Json array.
/// </summary>
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);
}
}
/// <summary>
/// Writes the property name of a name/value pair on a Json object.
/// </summary>
/// <param name="name"></param>
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
/// <summary>
/// Writes a null value.
/// </summary>
public override void WriteNull()
{
base.WriteNull();
WriteValueInternal(JavaScriptConvert.Null, JsonToken.Null);
}
/// <summary>
/// Writes an undefined value.
/// </summary>
public override void WriteUndefined()
{
base.WriteUndefined();
WriteValueInternal(JavaScriptConvert.Undefined, JsonToken.Undefined);
}
/// <summary>
/// Writes raw JavaScript manually.
/// </summary>
/// <param name="javaScript">The raw JavaScript to write.</param>
public override void WriteRaw(string javaScript)
{
base.WriteRaw(javaScript);
// hack. some 'raw' or 'other' token perhaps?
WriteValueInternal(javaScript, JsonToken.Undefined);
}
/// <summary>
/// Writes a <see cref="String"/> value.
/// </summary>
/// <param name="value">The <see cref="String"/> value to write.</param>
public override void WriteValue(string value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value, _quoteChar), JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Int32"/> value.
/// </summary>
/// <param name="value">The <see cref="Int32"/> value to write.</param>
public override void WriteValue(int value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt32"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
public override void WriteValue(uint value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Int64"/> value.
/// </summary>
/// <param name="value">The <see cref="Int64"/> value to write.</param>
public override void WriteValue(long value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt64"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
public override void WriteValue(ulong value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Single"/> value.
/// </summary>
/// <param name="value">The <see cref="Single"/> value to write.</param>
public override void WriteValue(float value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="Double"/> value.
/// </summary>
/// <param name="value">The <see cref="Double"/> value to write.</param>
public override void WriteValue(double value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="Boolean"/> value.
/// </summary>
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
public override void WriteValue(bool value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Boolean);
}
/// <summary>
/// Writes a <see cref="Int16"/> value.
/// </summary>
/// <param name="value">The <see cref="Int16"/> value to write.</param>
public override void WriteValue(short value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt16"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
public override void WriteValue(ushort value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Char"/> value.
/// </summary>
/// <param name="value">The <see cref="Char"/> value to write.</param>
public override void WriteValue(char value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Byte"/> value.
/// </summary>
/// <param name="value">The <see cref="Byte"/> value to write.</param>
public override void WriteValue(byte value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="SByte"/> value.
/// </summary>
/// <param name="value">The <see cref="SByte"/> value to write.</param>
public override void WriteValue(sbyte value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Decimal"/> value.
/// </summary>
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
public override void WriteValue(decimal value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="DateTime"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
public override void WriteValue(DateTime value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
}
/// <summary>
/// Writes a <see cref="DateTimeOffset"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
public override void WriteValue(DateTimeOffset value)
{
base.WriteValue(value);
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
}
#endregion
/// <summary>
/// Writes out a comment <code>/*...*/</code> containing the specified text.
/// </summary>
/// <param name="text">Text to place inside the comment.</param>
public override void WriteComment(string text)
{
base.WriteComment(text);
_writer.Write("/*");
_writer.Write(text);
_writer.Write("*/");
}
/// <summary>
/// Writes out the given white space.
/// </summary>
/// <param name="ws">The string of white space characters.</param>
public override void WriteWhitespace(string ws)
{
base.WriteWhitespace(ws);
_writer.Write(ws);
}
}
}
+178 -211
View File
@@ -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
}
/// <summary>
/// Specifies the state of the <see cref="JsonWriter"/>.
/// </summary>
@@ -95,7 +88,7 @@ namespace Newtonsoft.Json
/// <summary>
/// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
/// </summary>
public class JsonWriter : IDisposable
public abstract class JsonWriter : IDisposable
{
private enum State
{
@@ -125,15 +118,11 @@ namespace Newtonsoft.Json
};
private int _top;
private List<JsonType> _stack;
private List<JsonTokenType> _stack;
private List<object> _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<object> SerializeStack
{
@@ -146,6 +135,11 @@ namespace Newtonsoft.Json
}
}
protected int Top
{
get { return _top; }
}
/// <summary>
/// Gets the state of the writer.
/// </summary>
@@ -187,75 +181,19 @@ namespace Newtonsoft.Json
set { _formatting = value; }
}
/// <summary>
/// Gets or sets how many IndentChars to write for each level in the hierarchy when <paramref name="Formatting"/> is set to <c>Formatting.Indented</c>.
/// </summary>
public int Indentation
{
get { return _indentation; }
set
{
if (value < 0)
throw new ArgumentException("Indentation value must be greater than 0.");
_indentation = value;
}
}
/// <summary>
/// Gets or sets which character to use to quote attribute values.
/// </summary>
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;
}
}
/// <summary>
/// Gets or sets which character to use for indenting when <paramref name="Formatting"/> is set to <c>Formatting.Indented</c>.
/// </summary>
public char IndentChar
{
get { return _indentChar; }
set { _indentChar = value; }
}
/// <summary>
/// Gets or sets a value indicating whether object names will be surrounded with quotes.
/// </summary>
public bool QuoteName
{
get { return _quoteName; }
set { _quoteName = value; }
}
/// <summary>
/// Creates an instance of the <c>JsonWriter</c> class using the specified <see cref="TextWriter"/>.
/// </summary>
/// <param name="textWriter">The <c>TextWriter</c> to write to.</param>
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<JsonType>(1);
_stack.Add(JsonType.None);
_stack = new List<JsonTokenType>(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
/// <summary>
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
/// </summary>
public void Flush()
{
_writer.Flush();
}
public abstract void Flush();
/// <summary>
/// Closes this stream and the underlying stream.
/// </summary>
public void Close()
public virtual void Close()
{
AutoCompleteAll();
_writer.Close();
}
/// <summary>
/// Writes the beginning of a Json object.
/// </summary>
public void WriteStartObject()
public virtual void WriteStartObject()
{
AutoComplete(JsonToken.StartObject);
Push(JsonType.Object);
_writer.Write("{");
Push(JsonTokenType.Object);
}
/// <summary>
@@ -318,11 +248,10 @@ namespace Newtonsoft.Json
/// <summary>
/// Writes the beginning of a Json array.
/// </summary>
public void WriteStartArray()
public virtual void WriteStartArray()
{
AutoComplete(JsonToken.StartArray);
Push(JsonType.Array);
_writer.Write("[");
Push(JsonTokenType.Array);
}
/// <summary>
@@ -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.
/// </summary>
/// <param name="name"></param>
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(':');
}
/// <summary>
@@ -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
/// <summary>
/// Writes a null value.
/// </summary>
public void WriteNull()
public virtual void WriteNull()
{
WriteValueInternal(JavaScriptConvert.Null, JsonToken.Null);
AutoComplete(JsonToken.Null);
}
/// <summary>
/// Writes an undefined value.
/// </summary>
public void WriteUndefined()
public virtual void WriteUndefined()
{
WriteValueInternal(JavaScriptConvert.Undefined, JsonToken.Undefined);
AutoComplete(JsonToken.Undefined);
}
/// <summary>
/// Writes raw JavaScript manually.
/// </summary>
/// <param name="javaScript">The raw JavaScript to write.</param>
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);
}
/// <summary>
/// Writes a <see cref="String"/> value.
/// </summary>
/// <param name="value">The <see cref="String"/> value to write.</param>
public void WriteValue(string value)
public virtual void WriteValue(string value)
{
WriteValueInternal(JavaScriptConvert.ToString(value, _quoteChar), JsonToken.String);
AutoComplete(JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Int32"/> value.
/// </summary>
/// <param name="value">The <see cref="Int32"/> value to write.</param>
public void WriteValue(int value)
public virtual void WriteValue(int value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt32"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
public void WriteValue(uint value)
public virtual void WriteValue(uint value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Int64"/> value.
/// </summary>
/// <param name="value">The <see cref="Int64"/> value to write.</param>
public void WriteValue(long value)
public virtual void WriteValue(long value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt64"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
public void WriteValue(ulong value)
public virtual void WriteValue(ulong value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Single"/> value.
/// </summary>
/// <param name="value">The <see cref="Single"/> value to write.</param>
public void WriteValue(float value)
public virtual void WriteValue(float value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
AutoComplete(JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="Double"/> value.
/// </summary>
/// <param name="value">The <see cref="Double"/> value to write.</param>
public void WriteValue(double value)
public virtual void WriteValue(double value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
AutoComplete(JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="Boolean"/> value.
/// </summary>
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
public void WriteValue(bool value)
public virtual void WriteValue(bool value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Boolean);
AutoComplete(JsonToken.Boolean);
}
/// <summary>
/// Writes a <see cref="Int16"/> value.
/// </summary>
/// <param name="value">The <see cref="Int16"/> value to write.</param>
public void WriteValue(short value)
public virtual void WriteValue(short value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt16"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
public void WriteValue(ushort value)
public virtual void WriteValue(ushort value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Char"/> value.
/// </summary>
/// <param name="value">The <see cref="Char"/> value to write.</param>
public void WriteValue(char value)
public virtual void WriteValue(char value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Byte"/> value.
/// </summary>
/// <param name="value">The <see cref="Byte"/> value to write.</param>
public void WriteValue(byte value)
public virtual void WriteValue(byte value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="SByte"/> value.
/// </summary>
/// <param name="value">The <see cref="SByte"/> value to write.</param>
public void WriteValue(sbyte value)
public virtual void WriteValue(sbyte value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
AutoComplete(JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Decimal"/> value.
/// </summary>
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
public void WriteValue(decimal value)
public virtual void WriteValue(decimal value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
AutoComplete(JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="DateTime"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
public void WriteValue(DateTime value)
public virtual void WriteValue(DateTime value)
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
AutoComplete(JsonToken.Date);
}
/// <summary>
/// Writes a <see cref="DateTimeOffset"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
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 <code>/*...*/</code> containing the specified text.
/// </summary>
/// <param name="text">Text to place inside the comment.</param>
public void WriteComment(string text)
public virtual void WriteComment(string text)
{
AutoComplete(JsonToken.Comment);
_writer.Write("/*");
_writer.Write(text);
_writer.Write("*/");
}
/// <summary>
/// Writes out the given white space.
/// </summary>
/// <param name="ws">The string of white space characters.</param>
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);
+63 -10
View File
@@ -71,25 +71,75 @@ namespace Newtonsoft.Json.Linq
return source.SelectMany(d => d.Properties());
}
public static IEnumerable<T> PropertyValues<T>(this IEnumerable<JObject> source, string name)
public static IEnumerable<JToken> Values(this IEnumerable<JToken> source, object key)
{
return Values<JToken, JToken>(source, key);
}
public static IEnumerable<JToken> Values(this IEnumerable<JToken> source)
{
return Values<JToken, JToken>(source, null);
}
public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source, object key)
{
return Values<JToken, U>(source, key);
}
public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source)
{
return Values<JToken, U>(source, null);
}
//public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source, object key)
//{
// return Values<JToken, U>(source, null);
//}
internal static IEnumerable<U> Values<T, U>(this IEnumerable<T> 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<JToken, T>();
foreach (JToken token in source)
{
if (key == null)
{
foreach (JToken t in token.Children())
{
yield return t.Convert<JToken, U>(); ;
}
}
else
{
JToken value = token[key];
if (value != null)
yield return value.Convert<JToken, U>();
}
}
yield break;
//IEnumerable<JToken> allChildren = source.SelectMany(d => d.Children());
//IEnumerable<JToken> childrenValues = (key != null) ? allChildren.Select(p => p[key]) : allChildren.SelectMany(p => p.Children());
//List<U> s = childrenValues.Convert<JToken, U>().ToList();
//return childrenValues.Convert<JToken, U>();
// return source.SelectMany(d => d.Properties())
//.Where(p => string.Compare(p.Name, name, StringComparison.Ordinal) == 0)
//.Select(p => p.Value)
//.Convert<JToken, T>();
}
//TODO
//public static IEnumerable<T> InDocumentOrder<T>(this IEnumerable<T> source) where T : JObject;
public static IEnumerable<JToken> Children<T>(this IEnumerable<T> source) where T : JContainer
{
ValidationUtils.ArgumentNotNull(source, "source");
//public static IEnumerable<JToken> Children<T>(this IEnumerable<T> source) where T : JToken
//{
// ValidationUtils.ArgumentNotNull(source, "source");
return source.SelectMany(c => c.Children());
}
// return source.SelectMany(c => c.Children());
//}
public static IEnumerable<U> Children<U>(this IEnumerable<JArray> 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)));
+32 -4
View File
@@ -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);
}
}
}
}
+15 -2
View File
@@ -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);
}
}
}
}
+43 -5
View File
@@ -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<JToken> Children()
public override JEnumerable<JToken> Children()
{
return new JEnumerable<JToken>(ChildrenInternal());
}
private IEnumerable<JToken> ChildrenInternal()
{
JToken first = First;
JToken current = first;
@@ -71,11 +76,18 @@ namespace Newtonsoft.Json.Linq
} while ((current = current.Next) != first);
}
public IEnumerable<T> Children<T>()
public override IEnumerable<T> Children<T>()
{
return Children().Convert<JToken, T>();
}
public override T Value<T>(object key)
{
JToken token = this[key];
return Extensions.Convert<JToken, T>(token);
}
public IEnumerable<JToken> 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)
+38
View File
@@ -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<T> : IEnumerable<T> where T : JToken
{
public static readonly JEnumerable<T> Empty = new JEnumerable<T>(Enumerable.Empty<T>());
private IEnumerable<T> _enumerable;
public JEnumerable(IEnumerable<T> enumerable)
{
ValidationUtils.ArgumentNotNull(enumerable, "enumerable");
_enumerable = enumerable;
}
public IEnumerator<T> GetEnumerator()
{
return _enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerable<JToken> this[object key]
{
get { return Extensions.Values<T, JToken>(_enumerable, key); }
}
}
}
+38 -11
View File
@@ -64,24 +64,41 @@ namespace Newtonsoft.Json.Linq
.SingleOrDefault();
}
public IEnumerable<JToken> PropertyValues()
public JEnumerable<JToken> PropertyValues()
{
return Properties().Select(p => p.Value);
return new JEnumerable<JToken>(Properties().Select(p => p.Value));
}
public T PropertyValue<T>(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<JToken, T>(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();
+3 -3
View File
@@ -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);
}
}
}
+35 -11
View File
@@ -107,15 +107,35 @@ namespace Newtonsoft.Json.Linq
yield return o;
}
//public IEnumerable<JObject> ObjectsAfterSelf()
//{
// return null;
//}
public virtual JToken this[object key]
{
get { return null; }
}
//public IEnumerable<JObject> ObjectsBeforeSelf()
//{
// return null;
//}
public virtual T Value<T>(object key)
{
return default(T);
}
public virtual JToken First
{
get { return null; }
}
public virtual JToken Last
{
get { return null; }
}
public virtual JEnumerable<JToken> Children()
{
return JEnumerable<JToken>.Empty;
}
public virtual IEnumerable<T> Children<T>()
{
return Enumerable.Empty<T>();
}
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
}
}
+29 -12
View File
@@ -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<JsonConverter> converters, Action<object> _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.");
}
+159
View File
@@ -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.");
}
}
}
}
@@ -32,6 +32,7 @@ namespace Newtonsoft.Json.Linq
{
public enum JsonTokenType
{
None,
Object,
Array,
Constructor,
+306
View File
@@ -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()
{
}
/// <summary>
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
/// </summary>
public override void Flush()
{
}
/// <summary>
/// Closes this stream and the underlying stream.
/// </summary>
public override void Close()
{
base.Close();
}
/// <summary>
/// Writes the beginning of a Json object.
/// </summary>
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;
}
/// <summary>
/// Writes the beginning of a Json array.
/// </summary>
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();
}
/// <summary>
/// Writes the property name of a name/value pair on a Json object.
/// </summary>
/// <param name="name"></param>
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
/// <summary>
/// Writes a null value.
/// </summary>
public override void WriteNull()
{
base.WriteNull();
AddValue(null, JsonToken.Null);
}
/// <summary>
/// Writes an undefined value.
/// </summary>
public override void WriteUndefined()
{
base.WriteUndefined();
AddValue(null, JsonToken.Undefined);
}
/// <summary>
/// Writes raw JavaScript manually.
/// </summary>
/// <param name="javaScript">The raw JavaScript to write.</param>
public override void WriteRaw(string javaScript)
{
base.WriteRaw(javaScript);
// hack. some 'raw' or 'other' token perhaps?
AddValue(javaScript, JsonToken.Undefined);
}
/// <summary>
/// Writes a <see cref="String"/> value.
/// </summary>
/// <param name="value">The <see cref="String"/> value to write.</param>
public override void WriteValue(string value)
{
base.WriteValue(value);
AddValue(value ?? string.Empty, JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Int32"/> value.
/// </summary>
/// <param name="value">The <see cref="Int32"/> value to write.</param>
public override void WriteValue(int value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt32"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
public override void WriteValue(uint value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Int64"/> value.
/// </summary>
/// <param name="value">The <see cref="Int64"/> value to write.</param>
public override void WriteValue(long value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt64"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
public override void WriteValue(ulong value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Single"/> value.
/// </summary>
/// <param name="value">The <see cref="Single"/> value to write.</param>
public override void WriteValue(float value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="Double"/> value.
/// </summary>
/// <param name="value">The <see cref="Double"/> value to write.</param>
public override void WriteValue(double value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="Boolean"/> value.
/// </summary>
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
public override void WriteValue(bool value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Boolean);
}
/// <summary>
/// Writes a <see cref="Int16"/> value.
/// </summary>
/// <param name="value">The <see cref="Int16"/> value to write.</param>
public override void WriteValue(short value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt16"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
public override void WriteValue(ushort value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Char"/> value.
/// </summary>
/// <param name="value">The <see cref="Char"/> value to write.</param>
public override void WriteValue(char value)
{
base.WriteValue(value);
AddValue(value.ToString(), JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Byte"/> value.
/// </summary>
/// <param name="value">The <see cref="Byte"/> value to write.</param>
public override void WriteValue(byte value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="SByte"/> value.
/// </summary>
/// <param name="value">The <see cref="SByte"/> value to write.</param>
public override void WriteValue(sbyte value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Decimal"/> value.
/// </summary>
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
public override void WriteValue(decimal value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="DateTime"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
public override void WriteValue(DateTime value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Date);
}
/// <summary>
/// Writes a <see cref="DateTimeOffset"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
public override void WriteValue(DateTimeOffset value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Date);
}
#endregion
}
}
+5 -4
View File
@@ -78,15 +78,13 @@
<Compile Include="Converters\JsonDateTimeSerializationMode.cs" />
<Compile Include="Converters\XmlNodeConverter.cs" />
<Compile Include="Converters\HtmlColorConverter.cs" />
<Compile Include="JavaScriptParameters.cs" />
<Compile Include="JavaScriptConstructor.cs" />
<Compile Include="JsonTextReader.cs" />
<Compile Include="JsonPropertyAttribute.cs" />
<Compile Include="JsonIgnoreAttribute.cs" />
<Compile Include="JsonTextWriter.cs" />
<Compile Include="JsonWriterException.cs" />
<Compile Include="JsonReaderException.cs" />
<Compile Include="Identifier.cs" />
<Compile Include="JavaScriptArray.cs" />
<Compile Include="JavaScriptObject.cs" />
<Compile Include="JsonConverter.cs" />
<Compile Include="JsonConverterCollection.cs" />
<Compile Include="JsonReader.cs" />
@@ -96,8 +94,11 @@
<Compile Include="Linq\Extensions.cs" />
<Compile Include="Linq\JConstructor.cs" />
<Compile Include="Linq\JContainer.cs" />
<Compile Include="Linq\JEnumerable.cs" />
<Compile Include="Linq\JObject.cs" />
<Compile Include="Linq\JArray.cs" />
<Compile Include="Linq\JsonTokenReader.cs" />
<Compile Include="Linq\JsonTokenWriter.cs" />
<Compile Include="Linq\JToken.cs" />
<Compile Include="Linq\JProperty.cs" />
<Compile Include="Linq\JsonTokenType.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();
}
}
}