-Added CurrentToken to JTokenWriter
-Added WriteToken(JsonToken, object) to JsonWriter
This commit is contained in:
@@ -825,6 +825,49 @@ namespace Newtonsoft.Json.Tests
|
|||||||
]", sb.ToString());
|
]", sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteTokenDirect()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
StringWriter sw = new StringWriter(sb);
|
||||||
|
|
||||||
|
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
|
||||||
|
{
|
||||||
|
jsonWriter.WriteToken(JsonToken.StartArray);
|
||||||
|
jsonWriter.WriteToken(JsonToken.Integer, 1);
|
||||||
|
jsonWriter.WriteToken(JsonToken.StartObject);
|
||||||
|
jsonWriter.WriteToken(JsonToken.PropertyName, "string");
|
||||||
|
jsonWriter.WriteToken(JsonToken.Integer, int.MaxValue);
|
||||||
|
jsonWriter.WriteToken(JsonToken.EndObject);
|
||||||
|
jsonWriter.WriteToken(JsonToken.EndArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.AreEqual(@"[1,{""string"":2147483647}]", sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteTokenDirect_BadValue()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
StringWriter sw = new StringWriter(sb);
|
||||||
|
|
||||||
|
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
|
||||||
|
{
|
||||||
|
jsonWriter.WriteToken(JsonToken.StartArray);
|
||||||
|
|
||||||
|
ExceptionAssert.Throws<FormatException>(() =>
|
||||||
|
{
|
||||||
|
jsonWriter.WriteToken(JsonToken.Integer, "three");
|
||||||
|
}, "Input string was not in a correct format.");
|
||||||
|
|
||||||
|
ExceptionAssert.Throws<ArgumentNullException>(() =>
|
||||||
|
{
|
||||||
|
jsonWriter.WriteToken(JsonToken.Integer);
|
||||||
|
}, @"Value cannot be null.
|
||||||
|
Parameter name: value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void BadWriteEndArray()
|
public void BadWriteEndArray()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -140,6 +140,62 @@ namespace Newtonsoft.Json.Tests.Linq
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CurrentToken()
|
||||||
|
{
|
||||||
|
using (JTokenWriter jsonWriter = new JTokenWriter())
|
||||||
|
{
|
||||||
|
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(null, jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
jsonWriter.WriteStartObject();
|
||||||
|
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(jsonWriter.Token, jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
JObject o = (JObject)jsonWriter.Token;
|
||||||
|
|
||||||
|
jsonWriter.WritePropertyName("CPU");
|
||||||
|
Assert.AreEqual(WriteState.Property, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(o.Property("CPU"), jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
jsonWriter.WriteValue("Intel");
|
||||||
|
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(o["CPU"], jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
jsonWriter.WritePropertyName("Drives");
|
||||||
|
Assert.AreEqual(WriteState.Property, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(o.Property("Drives"), jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
jsonWriter.WriteStartArray();
|
||||||
|
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(o["Drives"], jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
JArray a = (JArray)jsonWriter.CurrentToken;
|
||||||
|
|
||||||
|
jsonWriter.WriteValue("DVD read/writer");
|
||||||
|
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(a[a.Count - 1], jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
#if !(NET20 || NET35 || PORTABLE || ASPNETCORE50 || PORTABLE40)
|
||||||
|
jsonWriter.WriteValue(new BigInteger(123));
|
||||||
|
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(a[a.Count - 1], jsonWriter.CurrentToken);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
jsonWriter.WriteValue(new byte[0]);
|
||||||
|
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(a[a.Count - 1], jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
jsonWriter.WriteEnd();
|
||||||
|
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(a, jsonWriter.CurrentToken);
|
||||||
|
|
||||||
|
jsonWriter.WriteEndObject();
|
||||||
|
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
|
||||||
|
Assert.AreEqual(o, jsonWriter.CurrentToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void WriteComment()
|
public void WriteComment()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -449,6 +449,28 @@ namespace Newtonsoft.Json
|
|||||||
WriteToken(reader, writeChildren, true);
|
WriteToken(reader, writeChildren, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the <see cref="JsonToken"/> token and its value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token">The <see cref="JsonToken"/> to write.</param>
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to write.
|
||||||
|
/// A value is only required for tokens that have an associated value, e.g. the <see cref="String"/> property name for <see cref="JsonToken.PropertyName"/>.
|
||||||
|
/// A null value can be passed to the method for token's that don't have a value, e.g. <see cref="JsonToken.StartObject"/>.</param>
|
||||||
|
public void WriteToken(JsonToken token, object value)
|
||||||
|
{
|
||||||
|
WriteTokenInternal(token, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the <see cref="JsonToken"/> token.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token">The <see cref="JsonToken"/> to write.</param>
|
||||||
|
public void WriteToken(JsonToken token)
|
||||||
|
{
|
||||||
|
WriteTokenInternal(token, null);
|
||||||
|
}
|
||||||
|
|
||||||
internal void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate)
|
internal void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate)
|
||||||
{
|
{
|
||||||
int initialDepth;
|
int initialDepth;
|
||||||
@@ -467,96 +489,11 @@ namespace Newtonsoft.Json
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
switch (reader.TokenType)
|
// write a JValue date when the constructor is for a date
|
||||||
{
|
if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal))
|
||||||
case JsonToken.None:
|
WriteConstructorDate(reader);
|
||||||
// read to next
|
else
|
||||||
break;
|
WriteTokenInternal(reader.TokenType, reader.Value);
|
||||||
case JsonToken.StartObject:
|
|
||||||
WriteStartObject();
|
|
||||||
break;
|
|
||||||
case JsonToken.StartArray:
|
|
||||||
WriteStartArray();
|
|
||||||
break;
|
|
||||||
case JsonToken.StartConstructor:
|
|
||||||
string constructorName = reader.Value.ToString();
|
|
||||||
// write a JValue date when the constructor is for a date
|
|
||||||
if (writeDateConstructorAsDate && string.Equals(constructorName, "Date", StringComparison.Ordinal))
|
|
||||||
WriteConstructorDate(reader);
|
|
||||||
else
|
|
||||||
WriteStartConstructor(reader.Value.ToString());
|
|
||||||
break;
|
|
||||||
case JsonToken.PropertyName:
|
|
||||||
WritePropertyName(reader.Value.ToString());
|
|
||||||
break;
|
|
||||||
case JsonToken.Comment:
|
|
||||||
WriteComment((reader.Value != null) ? reader.Value.ToString() : null);
|
|
||||||
break;
|
|
||||||
case JsonToken.Integer:
|
|
||||||
#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
|
|
||||||
if (reader.Value is BigInteger)
|
|
||||||
{
|
|
||||||
WriteValue((BigInteger)reader.Value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
WriteValue(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case JsonToken.Float:
|
|
||||||
object value = reader.Value;
|
|
||||||
|
|
||||||
if (value is decimal)
|
|
||||||
WriteValue((decimal)value);
|
|
||||||
else if (value is double)
|
|
||||||
WriteValue((double)value);
|
|
||||||
else if (value is float)
|
|
||||||
WriteValue((float)value);
|
|
||||||
else
|
|
||||||
WriteValue(Convert.ToDouble(value, CultureInfo.InvariantCulture));
|
|
||||||
break;
|
|
||||||
case JsonToken.String:
|
|
||||||
WriteValue(reader.Value.ToString());
|
|
||||||
break;
|
|
||||||
case JsonToken.Boolean:
|
|
||||||
WriteValue(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
|
|
||||||
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:
|
|
||||||
#if !NET20
|
|
||||||
if (reader.Value is DateTimeOffset)
|
|
||||||
WriteValue((DateTimeOffset)reader.Value);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
WriteValue(Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture));
|
|
||||||
break;
|
|
||||||
case JsonToken.Raw:
|
|
||||||
WriteRawValue((reader.Value != null) ? reader.Value.ToString() : null);
|
|
||||||
break;
|
|
||||||
case JsonToken.Bytes:
|
|
||||||
if (reader.Value is Guid)
|
|
||||||
WriteValue((Guid)reader.Value);
|
|
||||||
else
|
|
||||||
WriteValue((byte[])reader.Value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", reader.TokenType, "Unexpected token type.");
|
|
||||||
}
|
|
||||||
} while (
|
} while (
|
||||||
// stop if we have reached the end of the token being read
|
// stop if we have reached the end of the token being read
|
||||||
initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0)
|
initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0)
|
||||||
@@ -564,6 +501,101 @@ namespace Newtonsoft.Json
|
|||||||
&& reader.Read());
|
&& reader.Read());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WriteTokenInternal(JsonToken tokenType, object value)
|
||||||
|
{
|
||||||
|
switch (tokenType)
|
||||||
|
{
|
||||||
|
case JsonToken.None:
|
||||||
|
// read to next
|
||||||
|
break;
|
||||||
|
case JsonToken.StartObject:
|
||||||
|
WriteStartObject();
|
||||||
|
break;
|
||||||
|
case JsonToken.StartArray:
|
||||||
|
WriteStartArray();
|
||||||
|
break;
|
||||||
|
case JsonToken.StartConstructor:
|
||||||
|
ValidationUtils.ArgumentNotNull(value, "value");
|
||||||
|
WriteStartConstructor(value.ToString());
|
||||||
|
break;
|
||||||
|
case JsonToken.PropertyName:
|
||||||
|
ValidationUtils.ArgumentNotNull(value, "value");
|
||||||
|
WritePropertyName(value.ToString());
|
||||||
|
break;
|
||||||
|
case JsonToken.Comment:
|
||||||
|
WriteComment((value != null) ? value.ToString() : null);
|
||||||
|
break;
|
||||||
|
case JsonToken.Integer:
|
||||||
|
ValidationUtils.ArgumentNotNull(value, "value");
|
||||||
|
#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
|
||||||
|
if (value is BigInteger)
|
||||||
|
{
|
||||||
|
WriteValue((BigInteger)value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
WriteValue(Convert.ToInt64(value, CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JsonToken.Float:
|
||||||
|
ValidationUtils.ArgumentNotNull(value, "value");
|
||||||
|
if (value is decimal)
|
||||||
|
WriteValue((decimal)value);
|
||||||
|
else if (value is double)
|
||||||
|
WriteValue((double)value);
|
||||||
|
else if (value is float)
|
||||||
|
WriteValue((float)value);
|
||||||
|
else
|
||||||
|
WriteValue(Convert.ToDouble(value, CultureInfo.InvariantCulture));
|
||||||
|
break;
|
||||||
|
case JsonToken.String:
|
||||||
|
ValidationUtils.ArgumentNotNull(value, "value");
|
||||||
|
WriteValue(value.ToString());
|
||||||
|
break;
|
||||||
|
case JsonToken.Boolean:
|
||||||
|
ValidationUtils.ArgumentNotNull(value, "value");
|
||||||
|
WriteValue(Convert.ToBoolean(value, CultureInfo.InvariantCulture));
|
||||||
|
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:
|
||||||
|
ValidationUtils.ArgumentNotNull(value, "value");
|
||||||
|
#if !NET20
|
||||||
|
if (value is DateTimeOffset)
|
||||||
|
WriteValue((DateTimeOffset)value);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
WriteValue(Convert.ToDateTime(value, CultureInfo.InvariantCulture));
|
||||||
|
break;
|
||||||
|
case JsonToken.Raw:
|
||||||
|
WriteRawValue((value != null) ? value.ToString() : null);
|
||||||
|
break;
|
||||||
|
case JsonToken.Bytes:
|
||||||
|
ValidationUtils.ArgumentNotNull(value, "value");
|
||||||
|
if (value is Guid)
|
||||||
|
WriteValue((Guid)value);
|
||||||
|
else
|
||||||
|
WriteValue((byte[])value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", tokenType, "Unexpected token type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void WriteConstructorDate(JsonReader reader)
|
private void WriteConstructorDate(JsonReader reader)
|
||||||
{
|
{
|
||||||
if (!reader.Read())
|
if (!reader.Read())
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ using Newtonsoft.Json.Utilities;
|
|||||||
namespace Newtonsoft.Json.Linq
|
namespace Newtonsoft.Json.Linq
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
|
/// Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class JTokenWriter : JsonWriter
|
public class JTokenWriter : JsonWriter
|
||||||
{
|
{
|
||||||
@@ -41,6 +41,15 @@ namespace Newtonsoft.Json.Linq
|
|||||||
private JContainer _parent;
|
private JContainer _parent;
|
||||||
// used when writer is writing single value and the value has no containing parent
|
// used when writer is writing single value and the value has no containing parent
|
||||||
private JValue _value;
|
private JValue _value;
|
||||||
|
private JToken _current;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="JToken"/> at the writer's current position.
|
||||||
|
/// </summary>
|
||||||
|
public JToken CurrentToken
|
||||||
|
{
|
||||||
|
get { return _current; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the token being writen.
|
/// Gets the token being writen.
|
||||||
@@ -109,10 +118,12 @@ namespace Newtonsoft.Json.Linq
|
|||||||
_parent.AddAndSkipParentCheck(container);
|
_parent.AddAndSkipParentCheck(container);
|
||||||
|
|
||||||
_parent = container;
|
_parent = container;
|
||||||
|
_current = container;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveParent()
|
private void RemoveParent()
|
||||||
{
|
{
|
||||||
|
_current = _parent;
|
||||||
_parent = _parent.Parent;
|
_parent = _parent.Parent;
|
||||||
|
|
||||||
if (_parent != null && _parent.Type == JTokenType.Property)
|
if (_parent != null && _parent.Type == JTokenType.Property)
|
||||||
@@ -172,6 +183,7 @@ namespace Newtonsoft.Json.Linq
|
|||||||
if (_parent != null)
|
if (_parent != null)
|
||||||
{
|
{
|
||||||
_parent.Add(value);
|
_parent.Add(value);
|
||||||
|
_current = _parent.Last;
|
||||||
|
|
||||||
if (_parent.Type == JTokenType.Property)
|
if (_parent.Type == JTokenType.Property)
|
||||||
_parent = _parent.Parent;
|
_parent = _parent.Parent;
|
||||||
@@ -179,6 +191,7 @@ namespace Newtonsoft.Json.Linq
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_value = value ?? JValue.CreateNull();
|
_value = value ?? JValue.CreateNull();
|
||||||
|
_current = _value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user