-Added CurrentToken to JTokenWriter

-Added WriteToken(JsonToken, object) to JsonWriter
This commit is contained in:
James Newton-King
2014-12-17 19:38:39 +13:00
parent 9c2a1d853d
commit 55ccac4d92
4 changed files with 235 additions and 91 deletions
@@ -825,6 +825,49 @@ namespace Newtonsoft.Json.Tests
]", 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]
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]
public void WriteComment()
{
+122 -90
View File
@@ -449,6 +449,28 @@ namespace Newtonsoft.Json
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)
{
int initialDepth;
@@ -467,96 +489,11 @@ namespace Newtonsoft.Json
{
do
{
switch (reader.TokenType)
{
case JsonToken.None:
// read to next
break;
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.");
}
// 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))
WriteConstructorDate(reader);
else
WriteTokenInternal(reader.TokenType, reader.Value);
} while (
// stop if we have reached the end of the token being read
initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0)
@@ -564,6 +501,101 @@ namespace Newtonsoft.Json
&& 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)
{
if (!reader.Read())
+14 -1
View File
@@ -33,7 +33,7 @@ using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq
{
/// <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>
public class JTokenWriter : JsonWriter
{
@@ -41,6 +41,15 @@ namespace Newtonsoft.Json.Linq
private JContainer _parent;
// used when writer is writing single value and the value has no containing parent
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>
/// Gets the token being writen.
@@ -109,10 +118,12 @@ namespace Newtonsoft.Json.Linq
_parent.AddAndSkipParentCheck(container);
_parent = container;
_current = container;
}
private void RemoveParent()
{
_current = _parent;
_parent = _parent.Parent;
if (_parent != null && _parent.Type == JTokenType.Property)
@@ -172,6 +183,7 @@ namespace Newtonsoft.Json.Linq
if (_parent != null)
{
_parent.Add(value);
_current = _parent.Last;
if (_parent.Type == JTokenType.Property)
_parent = _parent.Parent;
@@ -179,6 +191,7 @@ namespace Newtonsoft.Json.Linq
else
{
_value = value ?? JValue.CreateNull();
_current = _value;
}
}