From c70eaaa004cb2788f4bc1359d91b78d6d2659d33 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 21 Apr 2013 21:41:04 +1200 Subject: [PATCH] -Added JsonWriter.SetWriteState to support inheriting and override JsonWriters --- .../JsonTextWriterTest.cs | 82 ++++++++++ Src/Newtonsoft.Json/JsonTextWriter.cs | 4 +- Src/Newtonsoft.Json/JsonWriter.cs | 154 +++++++++++------- 3 files changed, 182 insertions(+), 58 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs index 85be33ef..b0e3c52d 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs @@ -26,6 +26,11 @@ using System; using System.Collections.Generic; using System.Globalization; +#if NET20 +using Newtonsoft.Json.Utilities.LinqBridge; +#else +using System.Linq; +#endif using System.Runtime.Serialization; using System.Text; using System.Xml; @@ -1312,6 +1317,83 @@ _____'propertyName': NaN if (appendDelimiters) writer.Write(delimiter); } + + [Test] + public void CustomJsonTextWriterTests() + { + StringWriter sw = new StringWriter(); + CustomJsonTextWriter writer = new CustomJsonTextWriter(sw) { Formatting = Formatting.Indented }; + writer.WriteStartObject(); + Assert.AreEqual(WriteState.Object, writer.WriteState); + writer.WritePropertyName("Property1"); + Assert.AreEqual(WriteState.Property, writer.WriteState); + Assert.AreEqual("Property1", writer.Path); + writer.WriteNull(); + Assert.AreEqual(WriteState.Object, writer.WriteState); + writer.WriteEndObject(); + Assert.AreEqual(WriteState.Start, writer.WriteState); + + Assert.AreEqual(@"{{{ + ""1ytreporP"": NULL!!! +}}}", sw.ToString()); + } + } + + public class CustomJsonTextWriter : JsonTextWriter + { + private readonly TextWriter _writer; + + public CustomJsonTextWriter(TextWriter textWriter) : base(textWriter) + { + _writer = textWriter; + } + + public override void WritePropertyName(string name) + { + WritePropertyName(name, true); + } + + public override void WritePropertyName(string name, bool escape) + { + SetWriteState(JsonToken.PropertyName, name); + + if (QuoteName) + _writer.Write(QuoteChar); + + _writer.Write(new string(name.Reverse().ToArray())); + + if (QuoteName) + _writer.Write(QuoteChar); + + _writer.Write(':'); + } + + public override void WriteNull() + { + SetWriteState(JsonToken.Null, null); + + _writer.Write("NULL!!!"); + } + + public override void WriteStartObject() + { + SetWriteState(JsonToken.StartObject, null); + + _writer.Write("{{{"); + } + + public override void WriteEndObject() + { + SetWriteState(JsonToken.EndObject, null); + } + + protected override void WriteEnd(JsonToken token) + { + if (token == JsonToken.EndObject) + _writer.Write("}}}"); + else + base.WriteEnd(token); + } } #if !(PORTABLE || NETFX_CORE) diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index a14e0960..53287afd 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -329,7 +329,7 @@ namespace Newtonsoft.Json /// public override void WriteNull() { - InternalWriteNull(); + InternalWriteValue(JsonToken.Null); WriteValueInternal(JsonConvert.Null, JsonToken.Null); } @@ -338,7 +338,7 @@ namespace Newtonsoft.Json /// public override void WriteUndefined() { - InternalWriteUndefined(); + InternalWriteValue(JsonToken.Undefined); WriteValueInternal(JsonConvert.Undefined, JsonToken.Undefined); } diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index 49296137..465f9705 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -358,13 +358,6 @@ namespace Newtonsoft.Json InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object); } - internal void InternalWriteStart(JsonToken token, JsonContainerType container) - { - UpdateScopeWithFinishedValue(); - AutoComplete(token); - Push(container); - } - /// /// Writes the end of a Json object. /// @@ -406,11 +399,6 @@ namespace Newtonsoft.Json InternalWriteEnd(JsonContainerType.Constructor); } - internal void InternalWriteEnd(JsonContainerType container) - { - AutoCompleteClose(container); - } - /// /// Writes the property name of a name/value pair on a JSON object. /// @@ -430,12 +418,6 @@ namespace Newtonsoft.Json WritePropertyName(name); } - internal void InternalWritePropertyName(string name) - { - _currentPosition.PropertyName = name; - AutoComplete(JsonToken.PropertyName); - } - /// /// Writes the end of the current Json object or array. /// @@ -775,13 +757,7 @@ namespace Newtonsoft.Json /// public virtual void WriteNull() { - InternalWriteNull(); - } - - internal void InternalWriteNull() - { - UpdateScopeWithFinishedValue(); - AutoComplete(JsonToken.Null); + InternalWriteValue(JsonToken.Null); } /// @@ -789,13 +765,7 @@ namespace Newtonsoft.Json /// public virtual void WriteUndefined() { - InternalWriteUndefined(); - } - - internal void InternalWriteUndefined() - { - UpdateScopeWithFinishedValue(); - AutoComplete(JsonToken.Undefined); + InternalWriteValue(JsonToken.Undefined); } /// @@ -807,10 +777,6 @@ namespace Newtonsoft.Json InternalWriteRaw(); } - internal void InternalWriteRaw() - { - } - /// /// Writes raw JSON where a value is expected and updates the writer's state. /// @@ -832,12 +798,6 @@ namespace Newtonsoft.Json InternalWriteValue(JsonToken.String); } - internal void InternalWriteValue(JsonToken token) - { - UpdateScopeWithFinishedValue(); - AutoComplete(token); - } - /// /// Writes a value. /// @@ -1265,11 +1225,6 @@ namespace Newtonsoft.Json InternalWriteComment(); } - internal void InternalWriteComment() - { - AutoComplete(JsonToken.Comment); - } - /// /// Writes out the given white space. /// @@ -1279,15 +1234,6 @@ namespace Newtonsoft.Json InternalWriteWhitespace(ws); } - internal void InternalWriteWhitespace(string ws) - { - if (ws != null) - { - if (!StringUtils.IsWhiteSpace(ws)) - throw JsonWriterException.Create(this, "Only white space characters should be used.", null); - } - } - void IDisposable.Dispose() { Dispose(true); @@ -1456,5 +1402,101 @@ namespace Newtonsoft.Json { return JsonWriterException.Create(writer, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); } + + /// + /// Sets the state of the JsonWriter, + /// + /// The JsonToken being written. + /// The value being written. + protected void SetWriteState(JsonToken token, object value) + { + switch (token) + { + case JsonToken.StartObject: + InternalWriteStart(token, JsonContainerType.Object); + break; + case JsonToken.StartArray: + InternalWriteStart(token, JsonContainerType.Array); + break; + case JsonToken.StartConstructor: + InternalWriteStart(token, JsonContainerType.Constructor); + break; + case JsonToken.PropertyName: + if (!(value is string)) + throw new ArgumentException("A name is required when setting property name state.", "value"); + + InternalWritePropertyName((string)value); + break; + case JsonToken.Comment: + InternalWriteComment(); + break; + case JsonToken.Raw: + InternalWriteRaw(); + break; + case JsonToken.Integer: + case JsonToken.Float: + case JsonToken.String: + case JsonToken.Boolean: + case JsonToken.Date: + case JsonToken.Bytes: + case JsonToken.Null: + case JsonToken.Undefined: + InternalWriteValue(token); + break; + case JsonToken.EndObject: + InternalWriteEnd(JsonContainerType.Object); + break; + case JsonToken.EndArray: + InternalWriteEnd(JsonContainerType.Array); + break; + case JsonToken.EndConstructor: + InternalWriteEnd(JsonContainerType.Constructor); + break; + default: + throw new ArgumentOutOfRangeException("token"); + } + } + + internal void InternalWriteEnd(JsonContainerType container) + { + AutoCompleteClose(container); + } + + internal void InternalWritePropertyName(string name) + { + _currentPosition.PropertyName = name; + AutoComplete(JsonToken.PropertyName); + } + + internal void InternalWriteRaw() + { + } + + internal void InternalWriteStart(JsonToken token, JsonContainerType container) + { + UpdateScopeWithFinishedValue(); + AutoComplete(token); + Push(container); + } + + internal void InternalWriteValue(JsonToken token) + { + UpdateScopeWithFinishedValue(); + AutoComplete(token); + } + + internal void InternalWriteWhitespace(string ws) + { + if (ws != null) + { + if (!StringUtils.IsWhiteSpace(ws)) + throw JsonWriterException.Create(this, "Only white space characters should be used.", null); + } + } + + internal void InternalWriteComment() + { + AutoComplete(JsonToken.Comment); + } } } \ No newline at end of file