#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.Diagnostics;
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;
#if DNXCORE50
using Xunit;
using Test = Xunit.FactAttribute;
using Assert = Newtonsoft.Json.Tests.XUnitAssert;
#else
using NUnit.Framework;
#endif
using Newtonsoft.Json;
using System.IO;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Tests.TestObjects;
using Newtonsoft.Json.Tests.TestObjects.JsonTextReaderTests;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Tests
{
[TestFixture]
public class JsonTextWriterTest : TestFixtureBase
{
[Test]
public void BufferTest()
{
FakeArrayPool arrayPool = new FakeArrayPool();
string longString = new string('A', 2000);
string longEscapedString = "Hello!" + new string('!', 50) + new string('\n', 1000) + "Good bye!";
string longerEscapedString = "Hello!" + new string('!', 2000) + new string('\n', 1000) + "Good bye!";
for (int i = 0; i < 1000; i++)
{
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
using (JsonTextWriter writer = new JsonTextWriter(sw))
{
writer.ArrayPool = arrayPool;
writer.WriteStartObject();
writer.WritePropertyName("Prop1");
writer.WriteValue(new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc));
writer.WritePropertyName("Prop2");
writer.WriteValue(longString);
writer.WritePropertyName("Prop3");
writer.WriteValue(longEscapedString);
writer.WritePropertyName("Prop4");
writer.WriteValue(longerEscapedString);
writer.WriteEndObject();
}
if ((i + 1) % 100 == 0)
{
Console.WriteLine("Allocated buffers: " + arrayPool.FreeArrays.Count);
}
}
Assert.AreEqual(0, arrayPool.UsedArrays.Count);
Assert.AreEqual(3, arrayPool.FreeArrays.Count);
}
[Test]
public void BufferTest_WithError()
{
FakeArrayPool arrayPool = new FakeArrayPool();
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
try
{
// dispose will free used buffers
using (JsonTextWriter writer = new JsonTextWriter(sw))
{
writer.ArrayPool = arrayPool;
writer.WriteStartObject();
writer.WritePropertyName("Prop1");
writer.WriteValue(new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc));
writer.WritePropertyName("Prop2");
writer.WriteValue("This is an escaped \n string!");
writer.WriteValue("Error!");
}
Assert.Fail();
}
catch
{
}
Assert.AreEqual(0, arrayPool.UsedArrays.Count);
Assert.AreEqual(1, arrayPool.FreeArrays.Count);
}
#if !(NET20 || NET35 || NET40 || PORTABLE || PORTABLE40 || DNXCORE50)
[Test]
public void BufferErroringWithInvalidSize()
{
JObject o = new JObject
{
{"BodyHtml", "
Title!
" + Environment.NewLine + new string(' ', 100) + "Content!
"}
};
JsonArrayPool arrayPool = new JsonArrayPool();
StringWriter sw = new StringWriter();
using (JsonTextWriter writer = new JsonTextWriter(sw))
{
writer.ArrayPool = arrayPool;
o.WriteTo(writer);
}
string result = o.ToString();
Assert.AreEqual(@"{
""BodyHtml"": ""Title!
\r\n Content!
""
}", result);
}
#endif
[Test]
public void NewLine()
{
MemoryStream ms = new MemoryStream();
using (var streamWriter = new StreamWriter(ms, new UTF8Encoding(false)) { NewLine = "\n" })
using (var jsonWriter = new JsonTextWriter(streamWriter)
{
CloseOutput = true,
Indentation = 2,
Formatting = Formatting.Indented
})
{
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("prop");
jsonWriter.WriteValue(true);
jsonWriter.WriteEndObject();
}
byte[] data = ms.ToArray();
string json = Encoding.UTF8.GetString(data, 0, data.Length);
Assert.AreEqual(@"{" + '\n' + @" ""prop"": true" + '\n' + "}", json);
}
[Test]
public void QuoteNameAndStrings()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
JsonTextWriter writer = new JsonTextWriter(sw) { QuoteName = false };
writer.WriteStartObject();
writer.WritePropertyName("name");
writer.WriteValue("value");
writer.WriteEndObject();
writer.Flush();
Assert.AreEqual(@"{name:""value""}", sb.ToString());
}
[Test]
public void CloseOutput()
{
MemoryStream ms = new MemoryStream();
JsonTextWriter writer = new JsonTextWriter(new StreamWriter(ms));
Assert.IsTrue(ms.CanRead);
writer.Close();
Assert.IsFalse(ms.CanRead);
ms = new MemoryStream();
writer = new JsonTextWriter(new StreamWriter(ms)) { CloseOutput = false };
Assert.IsTrue(ms.CanRead);
writer.Close();
Assert.IsTrue(ms.CanRead);
}
#if !(PORTABLE)
[Test]
public void WriteIConvertable()
{
var sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.WriteValue(new ConvertibleInt(1));
Assert.AreEqual("1", sw.ToString());
}
#endif
[Test]
public void ValueFormatting()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartArray();
jsonWriter.WriteValue('@');
jsonWriter.WriteValue("\r\n\t\f\b?{\\r\\n\"\'");
jsonWriter.WriteValue(true);
jsonWriter.WriteValue(10);
jsonWriter.WriteValue(10.99);
jsonWriter.WriteValue(0.99);
jsonWriter.WriteValue(0.000000000000000001d);
jsonWriter.WriteValue(0.000000000000000001m);
jsonWriter.WriteValue((string)null);
jsonWriter.WriteValue((object)null);
jsonWriter.WriteValue("This is a string.");
jsonWriter.WriteNull();
jsonWriter.WriteUndefined();
jsonWriter.WriteEndArray();
}
string expected = @"[""@"",""\r\n\t\f\b?{\\r\\n\""'"",true,10,10.99,0.99,1E-18,0.000000000000000001,null,null,""This is a string."",null,undefined]";
string result = sb.ToString();
Assert.AreEqual(expected, result);
}
[Test]
public void NullableValueFormatting()
{
StringWriter sw = new StringWriter();
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartArray();
jsonWriter.WriteValue((char?)null);
jsonWriter.WriteValue((char?)'c');
jsonWriter.WriteValue((bool?)null);
jsonWriter.WriteValue((bool?)true);
jsonWriter.WriteValue((byte?)null);
jsonWriter.WriteValue((byte?)1);
jsonWriter.WriteValue((sbyte?)null);
jsonWriter.WriteValue((sbyte?)1);
jsonWriter.WriteValue((short?)null);
jsonWriter.WriteValue((short?)1);
jsonWriter.WriteValue((ushort?)null);
jsonWriter.WriteValue((ushort?)1);
jsonWriter.WriteValue((int?)null);
jsonWriter.WriteValue((int?)1);
jsonWriter.WriteValue((uint?)null);
jsonWriter.WriteValue((uint?)1);
jsonWriter.WriteValue((long?)null);
jsonWriter.WriteValue((long?)1);
jsonWriter.WriteValue((ulong?)null);
jsonWriter.WriteValue((ulong?)1);
jsonWriter.WriteValue((double?)null);
jsonWriter.WriteValue((double?)1.1);
jsonWriter.WriteValue((float?)null);
jsonWriter.WriteValue((float?)1.1);
jsonWriter.WriteValue((decimal?)null);
jsonWriter.WriteValue((decimal?)1.1m);
jsonWriter.WriteValue((DateTime?)null);
jsonWriter.WriteValue((DateTime?)new DateTime(DateTimeUtils.InitialJavaScriptDateTicks, DateTimeKind.Utc));
#if !NET20
jsonWriter.WriteValue((DateTimeOffset?)null);
jsonWriter.WriteValue((DateTimeOffset?)new DateTimeOffset(DateTimeUtils.InitialJavaScriptDateTicks, TimeSpan.Zero));
#endif
jsonWriter.WriteEndArray();
}
string json = sw.ToString();
string expected;
#if !NET20
expected = @"[null,""c"",null,true,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1.1,null,1.1,null,1.1,null,""1970-01-01T00:00:00Z"",null,""1970-01-01T00:00:00+00:00""]";
#else
expected = @"[null,""c"",null,true,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1.1,null,1.1,null,1.1,null,""1970-01-01T00:00:00Z""]";
#endif
Assert.AreEqual(expected, json);
}
[Test]
public void WriteValueObjectWithNullable()
{
StringWriter sw = new StringWriter();
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
char? value = 'c';
jsonWriter.WriteStartArray();
jsonWriter.WriteValue((object)value);
jsonWriter.WriteEndArray();
}
string json = sw.ToString();
string expected = @"[""c""]";
Assert.AreEqual(expected, json);
}
[Test]
public void WriteValueObjectWithUnsupportedValue()
{
ExceptionAssert.Throws(() =>
{
StringWriter sw = new StringWriter();
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(new Version(1, 1, 1, 1));
jsonWriter.WriteEndArray();
}
}, @"Unsupported type: System.Version. Use the JsonSerializer class to get the object's JSON representation. Path ''.");
}
[Test]
public void StringEscaping()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(@"""These pretzels are making me thirsty!""");
jsonWriter.WriteValue("Jeff's house was burninated.");
jsonWriter.WriteValue("1. You don't talk about fight club.\r\n2. You don't talk about fight club.");
jsonWriter.WriteValue("35% of\t statistics\n are made\r up.");
jsonWriter.WriteEndArray();
}
string expected = @"[""\""These pretzels are making me thirsty!\"""",""Jeff's house was burninated."",""1. You don't talk about fight club.\r\n2. You don't talk about fight club."",""35% of\t statistics\n are made\r up.""]";
string result = sb.ToString();
Assert.AreEqual(expected, result);
}
[Test]
public void WriteEnd()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("CPU");
jsonWriter.WriteValue("Intel");
jsonWriter.WritePropertyName("PSU");
jsonWriter.WriteValue("500W");
jsonWriter.WritePropertyName("Drives");
jsonWriter.WriteStartArray();
jsonWriter.WriteValue("DVD read/writer");
jsonWriter.WriteComment("(broken)");
jsonWriter.WriteValue("500 gigabyte hard drive");
jsonWriter.WriteValue("200 gigabype hard drive");
jsonWriter.WriteEndObject();
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
}
string expected = @"{
""CPU"": ""Intel"",
""PSU"": ""500W"",
""Drives"": [
""DVD read/writer""
/*(broken)*/,
""500 gigabyte hard drive"",
""200 gigabype hard drive""
]
}";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void CloseWithRemainingContent()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("CPU");
jsonWriter.WriteValue("Intel");
jsonWriter.WritePropertyName("PSU");
jsonWriter.WriteValue("500W");
jsonWriter.WritePropertyName("Drives");
jsonWriter.WriteStartArray();
jsonWriter.WriteValue("DVD read/writer");
jsonWriter.WriteComment("(broken)");
jsonWriter.WriteValue("500 gigabyte hard drive");
jsonWriter.WriteValue("200 gigabype hard drive");
jsonWriter.Close();
}
string expected = @"{
""CPU"": ""Intel"",
""PSU"": ""500W"",
""Drives"": [
""DVD read/writer""
/*(broken)*/,
""500 gigabyte hard drive"",
""200 gigabype hard drive""
]
}";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void Indenting()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("CPU");
jsonWriter.WriteValue("Intel");
jsonWriter.WritePropertyName("PSU");
jsonWriter.WriteValue("500W");
jsonWriter.WritePropertyName("Drives");
jsonWriter.WriteStartArray();
jsonWriter.WriteValue("DVD read/writer");
jsonWriter.WriteComment("(broken)");
jsonWriter.WriteValue("500 gigabyte hard drive");
jsonWriter.WriteValue("200 gigabype hard drive");
jsonWriter.WriteEnd();
jsonWriter.WriteEndObject();
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
}
// {
// "CPU": "Intel",
// "PSU": "500W",
// "Drives": [
// "DVD read/writer"
// /*(broken)*/,
// "500 gigabyte hard drive",
// "200 gigabype hard drive"
// ]
// }
string expected = @"{
""CPU"": ""Intel"",
""PSU"": ""500W"",
""Drives"": [
""DVD read/writer""
/*(broken)*/,
""500 gigabyte hard drive"",
""200 gigabype hard drive""
]
}";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void State()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
jsonWriter.WriteStartObject();
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
Assert.AreEqual("", jsonWriter.Path);
jsonWriter.WritePropertyName("CPU");
Assert.AreEqual(WriteState.Property, jsonWriter.WriteState);
Assert.AreEqual("CPU", jsonWriter.Path);
jsonWriter.WriteValue("Intel");
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
Assert.AreEqual("CPU", jsonWriter.Path);
jsonWriter.WritePropertyName("Drives");
Assert.AreEqual(WriteState.Property, jsonWriter.WriteState);
Assert.AreEqual("Drives", jsonWriter.Path);
jsonWriter.WriteStartArray();
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
jsonWriter.WriteValue("DVD read/writer");
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
Assert.AreEqual("Drives[0]", jsonWriter.Path);
jsonWriter.WriteEnd();
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
Assert.AreEqual("Drives", jsonWriter.Path);
jsonWriter.WriteEndObject();
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
Assert.AreEqual("", jsonWriter.Path);
}
}
[Test]
public void FloatingPointNonFiniteNumbers_Symbol()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.FloatFormatHandling = FloatFormatHandling.Symbol;
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(double.NaN);
jsonWriter.WriteValue(double.PositiveInfinity);
jsonWriter.WriteValue(double.NegativeInfinity);
jsonWriter.WriteValue(float.NaN);
jsonWriter.WriteValue(float.PositiveInfinity);
jsonWriter.WriteValue(float.NegativeInfinity);
jsonWriter.WriteEndArray();
jsonWriter.Flush();
}
string expected = @"[
NaN,
Infinity,
-Infinity,
NaN,
Infinity,
-Infinity
]";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void FloatingPointNonFiniteNumbers_Zero()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.FloatFormatHandling = FloatFormatHandling.DefaultValue;
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(double.NaN);
jsonWriter.WriteValue(double.PositiveInfinity);
jsonWriter.WriteValue(double.NegativeInfinity);
jsonWriter.WriteValue(float.NaN);
jsonWriter.WriteValue(float.PositiveInfinity);
jsonWriter.WriteValue(float.NegativeInfinity);
jsonWriter.WriteValue((double?)double.NaN);
jsonWriter.WriteValue((double?)double.PositiveInfinity);
jsonWriter.WriteValue((double?)double.NegativeInfinity);
jsonWriter.WriteValue((float?)float.NaN);
jsonWriter.WriteValue((float?)float.PositiveInfinity);
jsonWriter.WriteValue((float?)float.NegativeInfinity);
jsonWriter.WriteEndArray();
jsonWriter.Flush();
}
string expected = @"[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
null,
null,
null,
null,
null,
null
]";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void FloatingPointNonFiniteNumbers_String()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.FloatFormatHandling = FloatFormatHandling.String;
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(double.NaN);
jsonWriter.WriteValue(double.PositiveInfinity);
jsonWriter.WriteValue(double.NegativeInfinity);
jsonWriter.WriteValue(float.NaN);
jsonWriter.WriteValue(float.PositiveInfinity);
jsonWriter.WriteValue(float.NegativeInfinity);
jsonWriter.WriteEndArray();
jsonWriter.Flush();
}
string expected = @"[
""NaN"",
""Infinity"",
""-Infinity"",
""NaN"",
""Infinity"",
""-Infinity""
]";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void FloatingPointNonFiniteNumbers_QuoteChar()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.FloatFormatHandling = FloatFormatHandling.String;
jsonWriter.QuoteChar = '\'';
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(double.NaN);
jsonWriter.WriteValue(double.PositiveInfinity);
jsonWriter.WriteValue(double.NegativeInfinity);
jsonWriter.WriteValue(float.NaN);
jsonWriter.WriteValue(float.PositiveInfinity);
jsonWriter.WriteValue(float.NegativeInfinity);
jsonWriter.WriteEndArray();
jsonWriter.Flush();
}
string expected = @"[
'NaN',
'Infinity',
'-Infinity',
'NaN',
'Infinity',
'-Infinity'
]";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void WriteRawInStart()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.FloatFormatHandling = FloatFormatHandling.Symbol;
jsonWriter.WriteRaw("[1,2,3,4,5]");
jsonWriter.WriteWhitespace(" ");
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(double.NaN);
jsonWriter.WriteEndArray();
}
string expected = @"[1,2,3,4,5] [
NaN
]";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void WriteRawInArray()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.FloatFormatHandling = FloatFormatHandling.Symbol;
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(double.NaN);
jsonWriter.WriteRaw(",[1,2,3,4,5]");
jsonWriter.WriteRaw(",[1,2,3,4,5]");
jsonWriter.WriteValue(float.NaN);
jsonWriter.WriteEndArray();
}
string expected = @"[
NaN,[1,2,3,4,5],[1,2,3,4,5],
NaN
]";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void WriteRawInObject()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartObject();
jsonWriter.WriteRaw(@"""PropertyName"":[1,2,3,4,5]");
jsonWriter.WriteEnd();
}
string expected = @"{""PropertyName"":[1,2,3,4,5]}";
string result = sb.ToString();
Assert.AreEqual(expected, result);
}
[Test]
public void WriteToken()
{
JsonTextReader reader = new JsonTextReader(new StringReader("[1,2,3,4,5]"));
reader.Read();
reader.Read();
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.WriteToken(reader);
Assert.AreEqual("1", sw.ToString());
}
[Test]
public void WriteRawValue()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
int i = 0;
string rawJson = "[1,2]";
jsonWriter.WriteStartObject();
while (i < 3)
{
jsonWriter.WritePropertyName("d" + i);
jsonWriter.WriteRawValue(rawJson);
i++;
}
jsonWriter.WriteEndObject();
}
Assert.AreEqual(@"{""d0"":[1,2],""d1"":[1,2],""d2"":[1,2]}", sb.ToString());
}
[Test]
public void WriteObjectNestedInConstructor()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("con");
jsonWriter.WriteStartConstructor("Ext.data.JsonStore");
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("aa");
jsonWriter.WriteValue("aa");
jsonWriter.WriteEndObject();
jsonWriter.WriteEndConstructor();
jsonWriter.WriteEndObject();
}
Assert.AreEqual(@"{""con"":new Ext.data.JsonStore({""aa"":""aa""})}", sb.ToString());
}
[Test]
public void WriteFloatingPointNumber()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.FloatFormatHandling = FloatFormatHandling.Symbol;
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(0.0);
jsonWriter.WriteValue(0f);
jsonWriter.WriteValue(0.1);
jsonWriter.WriteValue(1.0);
jsonWriter.WriteValue(1.000001);
jsonWriter.WriteValue(0.000001);
jsonWriter.WriteValue(double.Epsilon);
jsonWriter.WriteValue(double.PositiveInfinity);
jsonWriter.WriteValue(double.NegativeInfinity);
jsonWriter.WriteValue(double.NaN);
jsonWriter.WriteValue(double.MaxValue);
jsonWriter.WriteValue(double.MinValue);
jsonWriter.WriteValue(float.PositiveInfinity);
jsonWriter.WriteValue(float.NegativeInfinity);
jsonWriter.WriteValue(float.NaN);
jsonWriter.WriteEndArray();
}
Assert.AreEqual(@"[0.0,0.0,0.1,1.0,1.000001,1E-06,4.94065645841247E-324,Infinity,-Infinity,NaN,1.7976931348623157E+308,-1.7976931348623157E+308,Infinity,-Infinity,NaN]", sb.ToString());
}
[Test]
public void WriteIntegerNumber()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
{
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(int.MaxValue);
jsonWriter.WriteValue(int.MinValue);
jsonWriter.WriteValue(0);
jsonWriter.WriteValue(-0);
jsonWriter.WriteValue(9L);
jsonWriter.WriteValue(9UL);
jsonWriter.WriteValue(long.MaxValue);
jsonWriter.WriteValue(long.MinValue);
jsonWriter.WriteValue(ulong.MaxValue);
jsonWriter.WriteValue(ulong.MinValue);
jsonWriter.WriteEndArray();
}
Console.WriteLine(sb.ToString());
StringAssert.AreEqual(@"[
2147483647,
-2147483648,
0,
0,
9,
9,
9223372036854775807,
-9223372036854775808,
18446744073709551615,
0
]", 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(() => { jsonWriter.WriteToken(JsonToken.Integer, "three"); }, "Input string was not in a correct format.");
ExceptionAssert.Throws(() => { jsonWriter.WriteToken(JsonToken.Integer); }, @"Value cannot be null.
Parameter name: value");
}
}
[Test]
public void WriteTokenNullCheck()
{
using (JsonWriter jsonWriter = new JsonTextWriter(new StringWriter()))
{
ExceptionAssert.Throws(() => { jsonWriter.WriteToken(null); });
ExceptionAssert.Throws(() => { jsonWriter.WriteToken(null, true); });
}
}
[Test]
public void TokenTypeOutOfRange()
{
using (JsonWriter jsonWriter = new JsonTextWriter(new StringWriter()))
{
ArgumentOutOfRangeException ex = ExceptionAssert.Throws(() => jsonWriter.WriteToken((JsonToken)int.MinValue));
Assert.AreEqual("token", ex.ParamName);
ex = ExceptionAssert.Throws(() => jsonWriter.WriteToken((JsonToken)int.MinValue, "test"));
Assert.AreEqual("token", ex.ParamName);
}
}
[Test]
public void BadWriteEndArray()
{
ExceptionAssert.Throws(() =>
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(0.0);
jsonWriter.WriteEndArray();
jsonWriter.WriteEndArray();
}
}, "No token to close. Path ''.");
}
[Test]
public void InvalidQuoteChar()
{
ExceptionAssert.Throws(() =>
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.QuoteChar = '*';
}
}, @"Invalid JavaScript string quote character. Valid quote characters are ' and "".");
}
[Test]
public void Indentation()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.FloatFormatHandling = FloatFormatHandling.Symbol;
Assert.AreEqual(Formatting.Indented, jsonWriter.Formatting);
jsonWriter.Indentation = 5;
Assert.AreEqual(5, jsonWriter.Indentation);
jsonWriter.IndentChar = '_';
Assert.AreEqual('_', jsonWriter.IndentChar);
jsonWriter.QuoteName = true;
Assert.AreEqual(true, jsonWriter.QuoteName);
jsonWriter.QuoteChar = '\'';
Assert.AreEqual('\'', jsonWriter.QuoteChar);
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("propertyName");
jsonWriter.WriteValue(double.NaN);
jsonWriter.IndentChar = '?';
Assert.AreEqual('?', jsonWriter.IndentChar);
jsonWriter.Indentation = 6;
Assert.AreEqual(6, jsonWriter.Indentation);
jsonWriter.WritePropertyName("prop2");
jsonWriter.WriteValue(123);
jsonWriter.WriteEndObject();
}
string expected = @"{
_____'propertyName': NaN,
??????'prop2': 123
}";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void WriteSingleBytes()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
string text = "Hello world.";
byte[] data = Encoding.UTF8.GetBytes(text);
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
Assert.AreEqual(Formatting.Indented, jsonWriter.Formatting);
jsonWriter.WriteValue(data);
}
string expected = @"""SGVsbG8gd29ybGQu""";
string result = sb.ToString();
Assert.AreEqual(expected, result);
byte[] d2 = Convert.FromBase64String(result.Trim('"'));
Assert.AreEqual(text, Encoding.UTF8.GetString(d2, 0, d2.Length));
}
[Test]
public void WriteBytesInArray()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
string text = "Hello world.";
byte[] data = Encoding.UTF8.GetBytes(text);
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
Assert.AreEqual(Formatting.Indented, jsonWriter.Formatting);
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(data);
jsonWriter.WriteValue(data);
jsonWriter.WriteValue((object)data);
jsonWriter.WriteValue((byte[])null);
jsonWriter.WriteValue((Uri)null);
jsonWriter.WriteEndArray();
}
string expected = @"[
""SGVsbG8gd29ybGQu"",
""SGVsbG8gd29ybGQu"",
""SGVsbG8gd29ybGQu"",
null,
null
]";
string result = sb.ToString();
StringAssert.AreEqual(expected, result);
}
[Test]
public void Path()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
string text = "Hello world.";
byte[] data = Encoding.UTF8.GetBytes(text);
using (JsonTextWriter writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
writer.WriteStartArray();
Assert.AreEqual("", writer.Path);
writer.WriteStartObject();
Assert.AreEqual("[0]", writer.Path);
writer.WritePropertyName("Property1");
Assert.AreEqual("[0].Property1", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[0].Property1", writer.Path);
writer.WriteValue(1);
Assert.AreEqual("[0].Property1[0]", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[0].Property1[1]", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[0].Property1[1][0]", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[0].Property1[1][0][0]", writer.Path);
writer.WriteEndObject();
Assert.AreEqual("[0]", writer.Path);
writer.WriteStartObject();
Assert.AreEqual("[1]", writer.Path);
writer.WritePropertyName("Property2");
Assert.AreEqual("[1].Property2", writer.Path);
writer.WriteStartConstructor("Constructor1");
Assert.AreEqual("[1].Property2", writer.Path);
writer.WriteNull();
Assert.AreEqual("[1].Property2[0]", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[1].Property2[1]", writer.Path);
writer.WriteValue(1);
Assert.AreEqual("[1].Property2[1][0]", writer.Path);
writer.WriteEnd();
Assert.AreEqual("[1].Property2[1]", writer.Path);
writer.WriteEndObject();
Assert.AreEqual("[1]", writer.Path);
writer.WriteEndArray();
Assert.AreEqual("", writer.Path);
}
StringAssert.AreEqual(@"[
{
""Property1"": [
1,
[
[
[]
]
]
]
},
{
""Property2"": new Constructor1(
null,
[
1
]
)
}
]", sb.ToString());
}
[Test]
public void BuildStateArray()
{
JsonWriter.State[][] stateArray = JsonWriter.BuildStateArray();
var valueStates = JsonWriter.StateArrayTempate[7];
foreach (JsonToken valueToken in EnumUtils.GetValues(typeof(JsonToken)))
{
switch (valueToken)
{
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.String:
case JsonToken.Boolean:
case JsonToken.Null:
case JsonToken.Undefined:
case JsonToken.Date:
case JsonToken.Bytes:
Assert.AreEqual(valueStates, stateArray[(int)valueToken], "Error for " + valueToken + " states.");
break;
}
}
}
[Test]
public void DateTimeZoneHandling()
{
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw)
{
DateTimeZoneHandling = Json.DateTimeZoneHandling.Utc
};
writer.WriteValue(new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Unspecified));
Assert.AreEqual(@"""2000-01-01T01:01:01Z""", sw.ToString());
}
[Test]
public void HtmlStringEscapeHandling()
{
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw)
{
StringEscapeHandling = StringEscapeHandling.EscapeHtml
};
string script = @"";
writer.WriteValue(script);
string json = sw.ToString();
Assert.AreEqual(@"""\u003cscript type=\u0022text/javascript\u0022\u003ealert(\u0027hi\u0027);\u003c/script\u003e""", json);
JsonTextReader reader = new JsonTextReader(new StringReader(json));
Assert.AreEqual(script, reader.ReadAsString());
}
[Test]
public void NonAsciiStringEscapeHandling()
{
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw)
{
StringEscapeHandling = StringEscapeHandling.EscapeNonAscii
};
string unicode = "\u5f20";
writer.WriteValue(unicode);
string json = sw.ToString();
Assert.AreEqual(8, json.Length);
Assert.AreEqual(@"""\u5f20""", json);
JsonTextReader reader = new JsonTextReader(new StringReader(json));
Assert.AreEqual(unicode, reader.ReadAsString());
sw = new StringWriter();
writer = new JsonTextWriter(sw)
{
StringEscapeHandling = StringEscapeHandling.Default
};
writer.WriteValue(unicode);
json = sw.ToString();
Assert.AreEqual(3, json.Length);
Assert.AreEqual("\"\u5f20\"", json);
}
[Test]
public void WriteEndOnProperty()
{
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.QuoteChar = '\'';
writer.WriteStartObject();
writer.WritePropertyName("Blah");
writer.WriteEnd();
Assert.AreEqual("{'Blah':null}", sw.ToString());
}
[Test]
public void WriteEndOnProperty_Close()
{
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.QuoteChar = '\'';
writer.WriteStartObject();
writer.WritePropertyName("Blah");
writer.Close();
Assert.AreEqual("{'Blah':null}", sw.ToString());
}
[Test]
public void WriteEndOnProperty_Dispose()
{
StringWriter sw = new StringWriter();
using (JsonTextWriter writer = new JsonTextWriter(sw))
{
writer.QuoteChar = '\'';
writer.WriteStartObject();
writer.WritePropertyName("Blah");
}
Assert.AreEqual("{'Blah':null}", sw.ToString());
}
[Test]
public void AutoCompleteOnClose_False()
{
StringWriter sw = new StringWriter();
using (JsonTextWriter writer = new JsonTextWriter(sw))
{
writer.AutoCompleteOnClose = false;
writer.QuoteChar = '\'';
writer.WriteStartObject();
writer.WritePropertyName("Blah");
}
Assert.AreEqual("{'Blah':", sw.ToString());
}
#if !NET20
[Test]
public void QuoteChar()
{
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.Formatting = Formatting.Indented;
writer.QuoteChar = '\'';
writer.WriteStartArray();
writer.WriteValue(new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc));
writer.WriteValue(new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero));
writer.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
writer.WriteValue(new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc));
writer.WriteValue(new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero));
writer.DateFormatString = "yyyy gg";
writer.WriteValue(new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc));
writer.WriteValue(new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero));
writer.WriteValue(new byte[] { 1, 2, 3 });
writer.WriteValue(TimeSpan.Zero);
writer.WriteValue(new Uri("http://www.google.com/"));
writer.WriteValue(Guid.Empty);
writer.WriteEnd();
StringAssert.AreEqual(@"[
'2000-01-01T01:01:01Z',
'2000-01-01T01:01:01+00:00',
'\/Date(946688461000)\/',
'\/Date(946688461000+0000)\/',
'2000 A.D.',
'2000 A.D.',
'AQID',
'00:00:00',
'http://www.google.com/',
'00000000-0000-0000-0000-000000000000'
]", sw.ToString());
}
[Test]
public void Culture()
{
CultureInfo culture = new CultureInfo("en-NZ");
culture.DateTimeFormat.AMDesignator = "a.m.";
culture.DateTimeFormat.PMDesignator = "p.m.";
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.Formatting = Formatting.Indented;
writer.DateFormatString = "yyyy tt";
writer.Culture = culture;
writer.QuoteChar = '\'';
writer.WriteStartArray();
writer.WriteValue(new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc));
writer.WriteValue(new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero));
writer.WriteEnd();
StringAssert.AreEqual(@"[
'2000 a.m.',
'2000 a.m.'
]", sw.ToString());
}
#endif
[Test]
public void CompareNewStringEscapingWithOld()
{
char c = (char)0;
do
{
StringWriter swNew = new StringWriter();
char[] buffer = null;
JavaScriptUtils.WriteEscapedJavaScriptString(swNew, c.ToString(), '"', true, JavaScriptUtils.DoubleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer);
StringWriter swOld = new StringWriter();
WriteEscapedJavaScriptStringOld(swOld, c.ToString(), '"', true);
string newText = swNew.ToString();
string oldText = swOld.ToString();
if (newText != oldText)
{
throw new Exception("Difference for char '{0}' (value {1}). Old text: {2}, New text: {3}".FormatWith(CultureInfo.InvariantCulture, c, (int)c, oldText, newText));
}
c++;
} while (c != char.MaxValue);
}
private const string EscapedUnicodeText = "!";
private static void WriteEscapedJavaScriptStringOld(TextWriter writer, string s, char delimiter, bool appendDelimiters)
{
// leading delimiter
if (appendDelimiters)
{
writer.Write(delimiter);
}
if (s != null)
{
char[] chars = null;
char[] unicodeBuffer = null;
int lastWritePosition = 0;
for (int i = 0; i < s.Length; i++)
{
var c = s[i];
// don't escape standard text/numbers except '\' and the text delimiter
if (c >= ' ' && c < 128 && c != '\\' && c != delimiter)
{
continue;
}
string escapedValue;
switch (c)
{
case '\t':
escapedValue = @"\t";
break;
case '\n':
escapedValue = @"\n";
break;
case '\r':
escapedValue = @"\r";
break;
case '\f':
escapedValue = @"\f";
break;
case '\b':
escapedValue = @"\b";
break;
case '\\':
escapedValue = @"\\";
break;
case '\u0085': // Next Line
escapedValue = @"\u0085";
break;
case '\u2028': // Line Separator
escapedValue = @"\u2028";
break;
case '\u2029': // Paragraph Separator
escapedValue = @"\u2029";
break;
case '\'':
// this charater is being used as the delimiter
escapedValue = @"\'";
break;
case '"':
// this charater is being used as the delimiter
escapedValue = "\\\"";
break;
default:
if (c <= '\u001f')
{
if (unicodeBuffer == null)
{
unicodeBuffer = new char[6];
}
StringUtils.ToCharAsUnicode(c, unicodeBuffer);
// slightly hacky but it saves multiple conditions in if test
escapedValue = EscapedUnicodeText;
}
else
{
escapedValue = null;
}
break;
}
if (escapedValue == null)
{
continue;
}
if (i > lastWritePosition)
{
if (chars == null)
{
chars = s.ToCharArray();
}
// write unchanged chars before writing escaped text
writer.Write(chars, lastWritePosition, i - lastWritePosition);
}
lastWritePosition = i + 1;
if (!string.Equals(escapedValue, EscapedUnicodeText))
{
writer.Write(escapedValue);
}
else
{
writer.Write(unicodeBuffer);
}
}
if (lastWritePosition == 0)
{
// no escaped text, write entire string
writer.Write(s);
}
else
{
if (chars == null)
{
chars = s.ToCharArray();
}
// write remaining text
writer.Write(chars, lastWritePosition, s.Length - lastWritePosition);
}
}
// trailing delimiter
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);
StringAssert.AreEqual(@"{{{
""1ytreporP"": NULL!!!
}}}", sw.ToString());
}
[Test]
public void QuoteDictionaryNames()
{
var d = new Dictionary
{
{ "a", 1 },
};
var jsonSerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
};
var serializer = JsonSerializer.Create(jsonSerializerSettings);
using (var stringWriter = new StringWriter())
{
using (var writer = new JsonTextWriter(stringWriter) { QuoteName = false })
{
serializer.Serialize(writer, d);
writer.Close();
}
StringAssert.AreEqual(@"{
a: 1
}", stringWriter.ToString());
}
}
[Test]
public void WriteComments()
{
string json = @"//comment*//*hi*/
{//comment
Name://comment
true//comment after true" + StringUtils.CarriageReturn + @"
,//comment after comma" + StringUtils.CarriageReturnLineFeed + @"
""ExpiryDate""://comment" + StringUtils.LineFeed + @"
new
" + StringUtils.LineFeed +
@"Constructor
(//comment
null//comment
),
""Price"": 3.99,
""Sizes"": //comment
[//comment
""Small""//comment
]//comment
}//comment
//comment 1 ";
JsonTextReader r = new JsonTextReader(new StringReader(json));
StringWriter sw = new StringWriter();
JsonTextWriter w = new JsonTextWriter(sw);
w.Formatting = Formatting.Indented;
w.WriteToken(r, true);
StringAssert.AreEqual(@"/*comment*//*hi*/*/{/*comment*/
""Name"": /*comment*/ true/*comment after true*//*comment after comma*/,
""ExpiryDate"": /*comment*/ new Constructor(
/*comment*/,
null
/*comment*/
),
""Price"": 3.99,
""Sizes"": /*comment*/ [
/*comment*/
""Small""
/*comment*/
]/*comment*/
}/*comment *//*comment 1 */", sw.ToString());
}
[Test]
public void DisposeSupressesFinalization()
{
UnmanagedResourceFakingJsonWriter.CreateAndDispose();
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.AreEqual(1, UnmanagedResourceFakingJsonWriter.DisposalCalls);
}
}
public class CustomJsonTextWriter : JsonTextWriter
{
protected 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.ToCharArray().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);
}
}
}
public class UnmanagedResourceFakingJsonWriter : JsonWriter
{
public static int DisposalCalls;
public static void CreateAndDispose()
{
((IDisposable)new UnmanagedResourceFakingJsonWriter()).Dispose();
}
public UnmanagedResourceFakingJsonWriter()
{
DisposalCalls = 0;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
++DisposalCalls;
}
~UnmanagedResourceFakingJsonWriter()
{
Dispose(false);
}
public override void Flush()
{
throw new NotImplementedException();
}
}
}