diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs
index 73aa7d34..636ad239 100644
--- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs
@@ -55,6 +55,19 @@ namespace Newtonsoft.Json.Tests.Bson
{
private const char Euro = '\u20ac';
+ [Test]
+ public void DeserializeLargeBsonObject()
+ {
+ byte[] data = System.IO.File.ReadAllBytes(@"SpaceShipV2.baemf");
+
+ MemoryStream ms = new MemoryStream(data);
+ BsonReader reader = new BsonReader(ms);
+
+ JObject o = (JObject)JToken.ReadFrom(reader);
+
+ Assert.AreEqual("1", (string)o["$id"]);
+ }
+
[Test]
public void CloseInput()
{
diff --git a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Json/CustomJsonReader.cs b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Json/CustomJsonReader.cs
new file mode 100644
index 00000000..3257ea26
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Json/CustomJsonReader.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml;
+
+namespace Newtonsoft.Json.Tests.Documentation.Samples.Json
+{
+ public class XmlJsonReader : JsonReader
+ {
+ private readonly XmlReader _reader;
+
+ public XmlJsonReader(XmlReader reader)
+ {
+ _reader = reader;
+ }
+
+ public override bool Read()
+ {
+ if (!_reader.Read())
+ return false;
+
+ switch (_reader.NodeType)
+ {
+ case XmlNodeType.Element:
+ if (CurrentState == State.ObjectStart || CurrentState == State.Object)
+ {
+ SetToken(JsonToken.PropertyName, _reader.LocalName);
+ }
+ else
+ {
+ SetToken(JsonToken.StartObject);
+ }
+ break;
+ case XmlNodeType.Text:
+ case XmlNodeType.CDATA:
+ SetToken(JsonToken.String, _reader.Value);
+ break;
+ case XmlNodeType.Comment:
+ SetToken(JsonToken.Comment, _reader.Value);
+ break;
+ case XmlNodeType.Document:
+ break;
+ case XmlNodeType.Whitespace:
+ case XmlNodeType.SignificantWhitespace:
+ break;
+ case XmlNodeType.EndElement:
+ break;
+ case XmlNodeType.EndEntity:
+ break;
+ case XmlNodeType.XmlDeclaration:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ return true;
+ }
+
+ public override int? ReadAsInt32()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string ReadAsString()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override byte[] ReadAsBytes()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override decimal? ReadAsDecimal()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override DateTime? ReadAsDateTime()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override DateTimeOffset? ReadAsDateTimeOffset()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class CustomJsonReader
+ {
+ public void Example()
+ {
+ #region Usage
+ StringBuilder sb = new StringBuilder();
+ StringWriter sw = new StringWriter(sb);
+
+ using (JsonWriter writer = new JsonTextWriter(sw))
+ {
+ writer.Formatting = Formatting.Indented;
+
+ writer.WriteStartObject();
+ writer.WritePropertyName("CPU");
+ writer.WriteValue("Intel");
+ writer.WritePropertyName("PSU");
+ writer.WriteValue("500W");
+ writer.WritePropertyName("Drives");
+ writer.WriteStartArray();
+ writer.WriteValue("DVD read/writer");
+ writer.WriteComment("(broken)");
+ writer.WriteValue("500 gigabyte hard drive");
+ writer.WriteValue("200 gigabype hard drive");
+ writer.WriteEnd();
+ writer.WriteEndObject();
+ }
+
+ Console.WriteLine(sb.ToString());
+ // {
+ // "CPU": "Intel",
+ // "PSU": "500W",
+ // "Drives": [
+ // "DVD read/writer"
+ // /*(broken)*/,
+ // "500 gigabyte hard drive",
+ // "200 gigabype hard drive"
+ // ]
+ // }
+ #endregion
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Json/CustomJsonWriter.cs b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Json/CustomJsonWriter.cs
new file mode 100644
index 00000000..b36cb37b
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Json/CustomJsonWriter.cs
@@ -0,0 +1,380 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml;
+using Newtonsoft.Json.Linq;
+
+namespace Newtonsoft.Json.Tests.Documentation.Samples.Json
+{
+ public class XmlJsonWriter : JsonWriter
+ {
+ private readonly XmlWriter _writer;
+ private string _propertyName;
+
+ public XmlJsonWriter(XmlWriter writer)
+ {
+ _writer = writer;
+ }
+
+ public override void WriteComment(string text)
+ {
+ base.WriteComment(text);
+ _writer.WriteComment(text);
+ }
+
+ public override void WritePropertyName(string name)
+ {
+ base.WritePropertyName(name);
+ _propertyName = name;
+ }
+
+ public override void WriteNull()
+ {
+ base.WriteNull();
+
+ WriteValueElement(JTokenType.Null);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(DateTime value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Date);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(DateTimeOffset value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Date);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(Guid value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Guid);
+ _writer.WriteValue(value.ToString());
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(TimeSpan value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.TimeSpan);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(Uri value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Uri);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(string value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.String);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(int value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Integer);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(long value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Integer);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(short value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Integer);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(byte value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Integer);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(bool value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Boolean);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(char value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.String);
+ _writer.WriteValue(value.ToString(CultureInfo.InvariantCulture));
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(decimal value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Float);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(double value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Float);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteValue(float value)
+ {
+ base.WriteValue(value);
+
+ WriteValueElement(JTokenType.Float);
+ _writer.WriteValue(value);
+ _writer.WriteEndElement();
+ }
+
+ private void WriteValueElement(JTokenType type)
+ {
+ if (_propertyName != null)
+ {
+ WriteValueElement(_propertyName, type);
+ _propertyName = null;
+ }
+ else
+ {
+ WriteValueElement("Item", type);
+ }
+ }
+
+ private void WriteValueElement(string elementName, JTokenType type)
+ {
+ _writer.WriteStartElement(elementName);
+ _writer.WriteAttributeString("type", type.ToString());
+ }
+
+ public override void WriteStartArray()
+ {
+ bool isStart = (WriteState == WriteState.Start);
+
+ base.WriteStartArray();
+
+ if (isStart)
+ WriteValueElement("Root", JTokenType.Array);
+ else
+ WriteValueElement(JTokenType.Array);
+ }
+
+ public override void WriteStartObject()
+ {
+ bool isStart = (WriteState == WriteState.Start);
+
+ base.WriteStartObject();
+
+ if (isStart)
+ WriteValueElement("Root", JTokenType.Object);
+ else
+ WriteValueElement(JTokenType.Object);
+ }
+
+ public override void WriteStartConstructor(string name)
+ {
+ bool isStart = (WriteState == WriteState.Start);
+
+ base.WriteStartConstructor(name);
+
+ if (isStart)
+ WriteValueElement("Root", JTokenType.Constructor);
+ else
+ WriteValueElement(JTokenType.Constructor);
+
+ _writer.WriteAttributeString("name", name);
+ }
+
+ public override void WriteEndArray()
+ {
+ base.WriteEndArray();
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteEndObject()
+ {
+ base.WriteEndObject();
+ _writer.WriteEndElement();
+ }
+
+ public override void WriteEndConstructor()
+ {
+ base.WriteEndConstructor();
+ _writer.WriteEndElement();
+ }
+
+ public override void Flush()
+ {
+ _writer.Flush();
+ }
+
+ protected override void WriteIndent()
+ {
+ _writer.WriteWhitespace(Environment.NewLine);
+
+ // levels of indentation multiplied by the indent count
+ int currentIndentCount = Top * 2;
+
+ while (currentIndentCount > 0)
+ {
+ // write up to a max of 10 characters at once to avoid creating too many new strings
+ int writeCount = Math.Min(currentIndentCount, 10);
+
+ _writer.WriteWhitespace(new string(' ', writeCount));
+
+ currentIndentCount -= writeCount;
+ }
+ }
+ }
+
+ public class CustomJsonWriter
+ {
+ public void Example()
+ {
+ StringWriter sw = new StringWriter();
+
+ using (XmlWriter xmlWriter = XmlWriter.Create(sw, new XmlWriterSettings { OmitXmlDeclaration = true }))
+ using (XmlJsonWriter writer = new XmlJsonWriter(xmlWriter))
+ {
+ writer.Formatting = Formatting.Indented;
+
+ writer.WriteStartObject();
+
+ writer.WritePropertyName("Null");
+ writer.WriteNull();
+
+ writer.WritePropertyName("String");
+ writer.WriteValue("This is a string!");
+
+ writer.WritePropertyName("Char");
+ writer.WriteValue('!');
+
+ writer.WritePropertyName("Integer");
+ writer.WriteValue(123);
+
+ writer.WritePropertyName("DateTime");
+ writer.WriteValue(new DateTime(2001, 2, 22, 20, 59, 59, DateTimeKind.Utc));
+
+ writer.WritePropertyName("DateTimeOffset");
+ writer.WriteValue(new DateTimeOffset(2001, 2, 22, 20, 59, 59, TimeSpan.FromHours(12)));
+
+ writer.WritePropertyName("Float");
+ writer.WriteValue(1.1f);
+
+ writer.WritePropertyName("Double");
+ writer.WriteValue(3.14d);
+
+ writer.WritePropertyName("Decimal");
+ writer.WriteValue(19.95m);
+
+ writer.WritePropertyName("Guid");
+ writer.WriteValue(Guid.NewGuid());
+
+ writer.WritePropertyName("Uri");
+ writer.WriteValue(new Uri("http://james.newtonking.com"));
+
+ writer.WritePropertyName("Array");
+ writer.WriteStartArray();
+ writer.WriteValue(1);
+ writer.WriteValue(2);
+ writer.WriteValue(3);
+ writer.WriteEndArray();
+
+ writer.WritePropertyName("Object");
+ writer.WriteStartObject();
+ writer.WritePropertyName("String");
+ writer.WriteValue("This is a string!");
+ writer.WritePropertyName("Null");
+ writer.WriteNull();
+ writer.WriteEndObject();
+
+ writer.WritePropertyName("Constructor");
+ writer.WriteStartConstructor("Date");
+ writer.WriteValue(2000);
+ writer.WriteValue(12);
+ writer.WriteValue(30);
+ writer.WriteEndConstructor();
+
+ writer.WriteEndObject();
+
+ writer.Flush();
+ }
+
+ Console.WriteLine(sw.ToString());
+
+ //
+ //
+ // This is a string!
+ // !
+ // 123
+ // 2001-02-22T20:59:59Z
+ // 2001-02-22T20:59:59+12:00
+ // 1.1
+ // 3.14
+ // 19.95
+ // d66eab59-3715-4b35-9e06-fa61c1216eaa
+ // http://james.newtonking.com
+ //
+ // - 1
+ // - 2
+ // - 3
+ //
+ //
+ //
+ // - 2000
+ // - 12
+ // - 30
+ //
+ //
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
index afa3071f..580a7a9f 100644
--- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
@@ -48,6 +48,19 @@ namespace Newtonsoft.Json.Tests
[TestFixture]
public class JsonTextReaderTest : TestFixtureBase
{
+ [Test]
+ public void ReadSingleQuoteInsideDoubleQuoteString()
+ {
+ string json = @"{""NameOfStore"":""Forest's Bakery And Cafe""}";
+
+ JsonTextReader jsonTextReader = new JsonTextReader(new StringReader(json));
+ jsonTextReader.Read();
+ jsonTextReader.Read();
+ jsonTextReader.Read();
+
+ Assert.AreEqual(@"Forest's Bakery And Cafe", jsonTextReader.Value);
+ }
+
[Test]
public void ReadMultilineString()
{
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
index e22624f8..f6263a68 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
@@ -90,7 +90,9 @@
+
+
@@ -484,6 +486,9 @@
Always
+
+ PreserveNewest
+
diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
index 68c52478..8911670b 100644
--- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
+++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
@@ -7466,6 +7466,44 @@ Parameter name: value",
}
#endif
+ [Serializable]
+ [DataContract]
+ public struct Pair
+ {
+ public Pair(TFirst first, TSecond second)
+ : this()
+ {
+ this.First = first;
+ this.Second = second;
+ }
+
+ [DataMember]
+ public TFirst First { get; set; }
+
+ [DataMember]
+ public TSecond Second { get; set; }
+ }
+
+ [Test]
+ public void SerializeStructWithSerializableAndDataContract()
+ {
+ Pair p = new Pair("One", 2);
+
+ DefaultContractResolver r = new DefaultContractResolver();
+ r.IgnoreSerializableAttribute = false;
+
+ string json = JsonConvert.SerializeObject(p, new JsonSerializerSettings
+ {
+ ContractResolver = r
+ });
+
+ Assert.AreEqual(@"{""First"":""One"",""Second"":2}", json);
+
+ json = JsonConvert.SerializeObject(p);
+
+ Assert.AreEqual(@"{""First"":""One"",""Second"":2}", json);
+ }
+
[Test]
public void ReadStringFloatingPointSymbols()
{
diff --git a/Src/Newtonsoft.Json.Tests/SpaceShipV2.baemf b/Src/Newtonsoft.Json.Tests/SpaceShipV2.baemf
new file mode 100644
index 00000000..6c3e64e8
Binary files /dev/null and b/Src/Newtonsoft.Json.Tests/SpaceShipV2.baemf differ