diff --git a/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs
index 3b2558a7..092a14e7 100644
--- a/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs
@@ -97,7 +97,11 @@ namespace Newtonsoft.Json.Tests.Converters
[Test]
public void SerializeCustomFormattedDateTime()
{
- IsoDateTimeConverter converter = new IsoDateTimeConverter() { DateTimeFormat = "dd/MM/yyyy" };
+ IsoDateTimeConverter converter = new IsoDateTimeConverter
+ {
+ DateTimeFormat = "dd/MM/yyyy",
+ Culture = CultureInfo.InvariantCulture
+ };
string json = @"""09/12/2006""";
diff --git a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
index 3e0982f4..c4078950 100644
--- a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
@@ -152,6 +152,9 @@ now brown cow?", '"', true);
result = JavaScriptUtils.ToEscapedJavaScriptString(@"Fred's ""cat"".", '\'', true);
Assert.AreEqual(result, @"'Fred\'s ""cat"".'");
+
+ result = JavaScriptUtils.ToEscapedJavaScriptString("\u001farray\u003caddress");
+ Assert.AreEqual(result, @"""\u001farray
2010-01-21T11:12:16.0809174+13:00(503) 814-6335fff Street2009-12-31T11:12:16.0809174+13:00(503) 814-6335array<address2009-12-30T11:12:16.0809174+13:00(503) 814-6335array 2 address34123123123.121Rick2010-01-01T12:12:16.0809174+13:00Val & asd11Val2 & asd13Val3 & asd14Markus egger ]><[, (2nd)";
+
private const string JsonText =
- @"{
- ""strings"": [
- ""Rick"",
- ""Markus egger ][, (2nd)"",
- ""Kevin McNeish""
- ],
- ""dictionary"": {
- ""Val asd1"": 1,
- ""Val2"": 3,
- ""Val3"": 4
- },
- ""Name"": ""Rick"",
- ""Now"": ""\/Date(1220867547892+1200)\/"",
- ""BigNumber"": 34123123123.121,
- ""Address1"": {
- ""Address"": ""fff Street"",
- ""Phone"": ""(503) 814-6335"",
- ""Entered"": ""\/Date(1222588347892+1300)\/""
- },
- ""Addresses"": [
- {
- ""Address"": ""array address"",
- ""Phone"": ""(503) 814-6335"",
- ""Entered"": ""\/Date(1220777547892+1200)\/""
- },
- {
- ""Address"": ""array 2 address"",
- ""Phone"": ""(503) 814-6335"",
- ""Entered"": ""\/Date(1220691147893+1200)\/""
- }
- ]
-}";
+ @"{""strings"":[null,""Markus egger ]><[, (2nd)"",null],""dictionary"":{""Val & asd1"":1,""Val2 & asd1"":3,""Val3 & asd1"":4},""Name"":""Rick"",""Now"":""\/Date(1262301136080+1300)\/"",""BigNumber"":34123123123.121,""Address1"":{""Street"":""fff Street"",""Phone"":""(503) 814-6335"",""Entered"":""\/Date(1264025536080+1300)\/""},""Addresses"":[{""Street"":""\u001farray(SerializeMethod.JsonNet, JsonText);
- BenchmarkDeserializeMethod(SerializeMethod.JsonNetBinary, MiscellaneousUtils.HexToBytes(BsonHex));
+ BenchmarkDeserializeMethod(SerializeMethod.DataContractSerializer, XmlText);
+ BenchmarkDeserializeMethod(SerializeMethod.BinaryFormatter, MiscellaneousUtils.HexToBytes(BinaryFormatterHex));
BenchmarkDeserializeMethod(SerializeMethod.JavaScriptSerializer, JsonText);
BenchmarkDeserializeMethod(SerializeMethod.DataContractJsonSerializer, JsonText);
+ BenchmarkDeserializeMethod(SerializeMethod.JsonNet, JsonText);
+ BenchmarkDeserializeMethod(SerializeMethod.JsonNetBinary, MiscellaneousUtils.HexToBytes(BsonHex));
}
[Test]
- public void SerializeDataSize()
+ public void SerializeSizeNormal()
+ {
+ SerializeSize(CreateSerializationObject());
+ }
+
+ [Test]
+ public void SerializeSizeData()
{
Image image = new Image();
image.Data = System.IO.File.ReadAllBytes(@"..\..\bunny_pancake.jpg");
image.FileName = "bunny_pancake.jpg";
image.Title = "I have no idea what you are talking about so here's a bunny with a pancake on its head";
- string json = JsonConvert.SerializeObject(image, Formatting.None);
+ SerializeSize(image);
+ }
+
+ private void SerializeSize(object value)
+ {
+ string json = JsonConvert.SerializeObject(value, Formatting.None);
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
MemoryStream ms = new MemoryStream();
JsonSerializer serializer = new JsonSerializer();
BsonWriter writer = new BsonWriter(ms);
- serializer.Serialize(writer, image);
+ serializer.Serialize(writer, value);
writer.Flush();
byte[] bsonBytes = ms.ToArray();
- Console.WriteLine("Image size: {0} bytes", image.Data.Length);
+ DataContractSerializer dataContractSerializer = new DataContractSerializer(value.GetType());
+
+ ms = new MemoryStream();
+ dataContractSerializer.WriteObject(ms, value);
+
+ byte[] xmlBytes = ms.ToArray();
+
+ ms = new MemoryStream();
+ BinaryFormatter formatter = new BinaryFormatter();
+ formatter.Serialize(ms, value);
+
+ byte[] binaryFormatterBytes = ms.ToArray();
+
+ Console.WriteLine("BinaryFormatter size: {0} bytes", binaryFormatterBytes.Length);
Console.WriteLine("JSON size: {0} bytes", jsonBytes.Length);
Console.WriteLine("BSON size: {0} bytes", bsonBytes.Length);
+ Console.WriteLine("XML size: {0} bytes", xmlBytes.Length);
+ }
+
+ #region Serialize
+ private static readonly byte[] Buffer = new byte[4096];
+
+ public void BenchmarkSerializeMethod(SerializeMethod method, object value)
+ {
+ Serialize(method, value);
+
+ Stopwatch timed = new Stopwatch();
+ timed.Start();
+
+ string json = null;
+ for (int x = 0; x < Iterations; x++)
+ {
+ json = Serialize(method, value);
+ }
+
+ timed.Stop();
+
+ Console.WriteLine("Serialize method: {0}", method);
+ Console.WriteLine("{0} ms", timed.ElapsedMilliseconds);
+ Console.WriteLine(json);
+ Console.WriteLine();
}
private TestClass CreateSerializationObject()
{
TestClass test = new TestClass();
- test.Address1.Address = "fff Street";
+ test.dictionary = new Dictionary { { "Val & asd1", 1 }, { "Val2 & asd1", 3 }, { "Val3 & asd1", 4 } };
+
+
+ test.Address1.Street = "fff Street";
test.Address1.Entered = DateTime.Now.AddDays(20);
test.BigNumber = 34123123123.121M;
test.Now = DateTime.Now.AddHours(1);
- test.strings = new List() { "Rick", "Markus egger ][, (2nd)", "Kevin McNeish" };
+ test.strings = new List() { null, "Markus egger ]><[, (2nd)", null };
- cAddress address = new cAddress();
+ Address address = new Address();
address.Entered = DateTime.Now.AddDays(-1);
- address.Address = "array address";
+ address.Street = "\u001farray\u003caddress";
test.Addresses.Add(address);
- address = new cAddress();
+ address = new Address();
address.Entered = DateTime.Now.AddDays(-2);
- address.Address = "array 2 address";
+ address.Street = "array 2 address";
test.Addresses.Add(address);
return test;
}
@@ -169,36 +210,6 @@ namespace Newtonsoft.Json.Tests
return output;
}
- public object DeserializeJsonNet(string json)
- {
- Type type = typeof(T);
-
- JsonSerializer serializer = new JsonSerializer();
-
- serializer.NullValueHandling = NullValueHandling.Ignore;
-
- serializer.ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace;
- serializer.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore;
- serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
-
- return serializer.Deserialize(new StringReader(json), type);
- }
-
- public object DeserializeJsonNetBinary(byte[] bson)
- {
- Type type = typeof(T);
-
- JsonSerializer serializer = new JsonSerializer();
-
- serializer.NullValueHandling = NullValueHandling.Ignore;
-
- serializer.ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace;
- serializer.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore;
- serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
-
- return serializer.Deserialize(new BsonReader(new MemoryStream(bson)), type);
- }
-
public string SerializeWebExtensions(object value)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
@@ -206,18 +217,11 @@ namespace Newtonsoft.Json.Tests
return ser.Serialize(value);
}
- public object DeserializeWebExtensions(string json)
- {
- JavaScriptSerializer ser = new JavaScriptSerializer();
-
- return ser.Deserialize(json);
- }
-
- public string SerializeDataContract(object value)
+ public string SerializeDataContractJson(object value)
{
DataContractJsonSerializer dataContractSerializer
= new DataContractJsonSerializer(value.GetType());
-
+
MemoryStream ms = new MemoryStream();
dataContractSerializer.WriteObject(ms, value);
@@ -229,18 +233,22 @@ namespace Newtonsoft.Json.Tests
}
}
- public object DeserializeDataContract(string json)
+ public string SerializeDataContract(object value)
{
- DataContractJsonSerializer dataContractSerializer
- = new DataContractJsonSerializer(typeof(T));
+ DataContractSerializer dataContractSerializer
+ = new DataContractSerializer(value.GetType());
- MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
+ MemoryStream ms = new MemoryStream();
+ dataContractSerializer.WriteObject(ms, value);
- return dataContractSerializer.ReadObject(ms);
+ ms.Seek(0, SeekOrigin.Begin);
+
+ using (StreamReader sr = new StreamReader(ms))
+ {
+ return sr.ReadToEnd();
+ }
}
- private static readonly byte[] Buffer = new byte[4096];
-
private string Serialize(SerializeMethod method, object value)
{
string json;
@@ -251,19 +259,27 @@ namespace Newtonsoft.Json.Tests
json = JsonConvert.SerializeObject(value);
break;
case SerializeMethod.JsonNetBinary:
- MemoryStream ms = new MemoryStream(Buffer);
- JsonSerializer serializer = new JsonSerializer();
- BsonWriter writer = new BsonWriter(ms);
- serializer.Serialize(writer, value);
+ {
+ MemoryStream ms = new MemoryStream(Buffer);
+ JsonSerializer serializer = new JsonSerializer();
+ BsonWriter writer = new BsonWriter(ms);
+ serializer.Serialize(writer, value);
- json = "Bytes = " + ms.Length;
- break;
+ json = "Bytes = " + ms.Position;
+ break;
+ }
case SerializeMethod.JavaScriptSerializer:
json = SerializeWebExtensions(value);
break;
case SerializeMethod.DataContractJsonSerializer:
+ json = SerializeDataContractJson(value);
+ break;
+ case SerializeMethod.DataContractSerializer:
json = SerializeDataContract(value);
break;
+ case SerializeMethod.BinaryFormatter:
+ json = SerializeBinaryFormatter(value);
+ break;
default:
throw new ArgumentOutOfRangeException("method");
}
@@ -271,33 +287,28 @@ namespace Newtonsoft.Json.Tests
return json;
}
- public void BenchmarkSerializeMethod(SerializeMethod method, object value)
+ private string SerializeBinaryFormatter(object value)
{
- Serialize(method, value);
+ string json;
+ MemoryStream ms = new MemoryStream(Buffer);
+ BinaryFormatter formatter = new BinaryFormatter();
+ formatter.Serialize(ms, value);
- Stopwatch timed = new Stopwatch();
- timed.Start();
-
- string json = null;
- for (int x = 0; x < Iterations; x++)
- {
- json = Serialize(method, value);
- }
-
- timed.Stop();
-
- Console.WriteLine("Serialize method: {0}", method);
- Console.WriteLine("{0} ms", timed.ElapsedMilliseconds);
- Console.WriteLine(json);
- Console.WriteLine();
+ json = "Bytes = " + ms.Position;
+ //json = BitConverter.ToString(ms.ToArray());
+ return json;
}
+ #endregion
+ #region Deserialize
public void BenchmarkDeserializeMethod(SerializeMethod method, object json)
{
+ Deserialize(method, json);
+
Stopwatch timed = new Stopwatch();
timed.Start();
- object value = null;
+ T value = default(T);
for (int x = 0; x < Iterations; x++)
{
value = Deserialize(method, json);
@@ -311,35 +322,97 @@ namespace Newtonsoft.Json.Tests
Console.WriteLine();
}
- private object Deserialize(SerializeMethod method, object json)
+ public T DeserializeJsonNet(string json)
{
- object value;
+ Type type = typeof(T);
+ JsonSerializer serializer = new JsonSerializer();
+ serializer.ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace;
+ serializer.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore;
+ serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+
+ return (T)serializer.Deserialize(new StringReader(json), type);
+
+ //JsonTextReader reader = new JsonTextReader(new StringReader(JsonText));
+ //while (reader.Read())
+ //{
+
+ //}
+ //return default(T);
+ }
+
+ public T DeserializeJsonNetBinary(byte[] bson)
+ {
+ Type type = typeof(T);
+
+ JsonSerializer serializer = new JsonSerializer();
+ serializer.ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace;
+ serializer.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore;
+ serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+
+ return (T)serializer.Deserialize(new BsonReader(new MemoryStream(bson)), type);
+ }
+
+ public T DeserializeWebExtensions(string json)
+ {
+ JavaScriptSerializer ser = new JavaScriptSerializer();
+
+ return ser.Deserialize(json);
+ }
+
+ public T DeserializeDataContractJson(string json)
+ {
+ DataContractJsonSerializer dataContractSerializer
+ = new DataContractJsonSerializer(typeof(T));
+
+ MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
+
+ return (T)dataContractSerializer.ReadObject(ms);
+ }
+
+ private T Deserialize(SerializeMethod method, object json)
+ {
switch (method)
{
case SerializeMethod.JsonNet:
- value = DeserializeJsonNet((string) json);
- break;
+ return DeserializeJsonNet((string) json);
case SerializeMethod.JsonNetBinary:
- value = DeserializeJsonNetBinary((byte[]) json);
- break;
+ return DeserializeJsonNetBinary((byte[]) json);
+ case SerializeMethod.BinaryFormatter:
+ return DeserializeBinaryFormatter((byte[]) json);
case SerializeMethod.JavaScriptSerializer:
- value = DeserializeWebExtensions((string) json);
- break;
+ return DeserializeWebExtensions((string) json);
+ case SerializeMethod.DataContractSerializer:
+ return DeserializeDataContract((string) json);
case SerializeMethod.DataContractJsonSerializer:
- value = DeserializeDataContract((string) json);
- break;
+ return DeserializeDataContractJson((string) json);
default:
throw new ArgumentOutOfRangeException("method");
}
- return value;
}
+
+ private T DeserializeDataContract(string xml)
+ {
+ MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml));
+
+ DataContractSerializer serializer = new DataContractSerializer(typeof (T));
+ return (T) serializer.ReadObject(ms);
+ }
+
+ private T DeserializeBinaryFormatter(byte[] bytes)
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ return (T)formatter.Deserialize(new MemoryStream(bytes));
+ }
+ #endregion
}
-
+ #region Classes
+ [Serializable]
+ [DataContract]
public class TestClass
{
-
+ [DataMember]
public string Name
{
get { return _Name; }
@@ -347,7 +420,7 @@ namespace Newtonsoft.Json.Tests
}
private string _Name = "Rick";
-
+ [DataMember]
public DateTime Now
{
get { return _Now; }
@@ -355,7 +428,7 @@ namespace Newtonsoft.Json.Tests
}
private DateTime _Now = DateTime.Now;
-
+ [DataMember]
public decimal BigNumber
{
get { return _BigNumber; }
@@ -363,42 +436,44 @@ namespace Newtonsoft.Json.Tests
}
private decimal _BigNumber = 1212121.22M;
-
- public cAddress Address1
+ [DataMember]
+ public Address Address1
{
get { return _Address1; }
set { _Address1 = value; }
}
- private cAddress _Address1 = new cAddress();
+ private Address _Address1 = new Address();
-
- public List Addresses
+ [DataMember]
+ public List Addresses
{
get { return _Addresses; }
set { _Addresses = value; }
}
- private List _Addresses = new List();
+ private List _Addresses = new List();
+ [DataMember]
+ public List strings = new List();
- public List strings = new List() { "Rick", "Markus", "Kevin" };
-
-
- public Dictionary dictionary = new Dictionary { { "Val asd1", 1 }, { "Val2", 3 }, { "Val3", 4 } };
+ [DataMember]
+ public Dictionary dictionary = new Dictionary();
}
- public class cAddress
+ [Serializable]
+ [DataContract]
+ public class Address
{
-
- public string Address
+ [DataMember]
+ public string Street
{
- get { return _Address; }
- set { _Address = value; }
+ get { return _street; }
+ set { _street = value; }
}
- private string _Address = "32 Kaiea";
-
+ private string _street = "32 Kaiea";
+ [DataMember]
public string Phone
{
get { return _Phone; }
@@ -406,14 +481,14 @@ namespace Newtonsoft.Json.Tests
}
private string _Phone = "(503) 814-6335";
-
+ [DataMember]
public DateTime Entered
{
get { return _Entered; }
set { _Entered = value; }
}
private DateTime _Entered = DateTime.Parse("01/01/2007", CultureInfo.CurrentCulture.DateTimeFormat);
-
}
+ #endregion
}
#endif
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
index 8e03b585..0d315837 100644
--- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
+++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
@@ -27,6 +27,7 @@ using System;
using System.Collections.Generic;
#if !SILVERLIGHT && !PocketPC && !NET20
using System.ComponentModel.DataAnnotations;
+using System.Web.Script.Serialization;
#endif
using System.Text;
using NUnit.Framework;
@@ -131,12 +132,21 @@ namespace Newtonsoft.Json.Tests.Serialization
[Test]
public void DeserializeJavaScriptDate()
{
- DateTime dateValue = new DateTime(2000, 3, 30);
+ DateTime dateValue = new DateTime(2010, 3, 30);
Dictionary testDictionary = new Dictionary();
testDictionary["date"] = dateValue;
string jsonText = JsonConvert.SerializeObject(testDictionary);
+#if !PocketPC && !NET20
+ MemoryStream ms = new MemoryStream();
+ DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary));
+ serializer.WriteObject(ms, testDictionary);
+
+ byte[] data = ms.ToArray();
+ string output = Encoding.UTF8.GetString(data, 0, data.Length);
+#endif
+
Dictionary deserializedDictionary = (Dictionary)JsonConvert.DeserializeObject(jsonText, typeof(Dictionary));
DateTime deserializedDate = (DateTime)deserializedDictionary["date"];
@@ -403,6 +413,37 @@ keyword such as type of business.""
Assert.AreEqual(dataContractResult[0], jsonNetResult[0]);
}
+ [Test]
+ public void BackslashEqivilence()
+ {
+ string json = @"[""vvv\/vvv\tvvv\""vvv\bvvv\nvvv\rvvv\\vvv\fvvv""]";
+
+#if !SILVERLIGHT
+ JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
+ List javaScriptSerializerResult = javaScriptSerializer.Deserialize>(json);
+#endif
+
+ DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List));
+ List dataContractResult = (List)s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
+
+ List jsonNetResult = JsonConvert.DeserializeObject>(json);
+
+ Assert.AreEqual(1, jsonNetResult.Count);
+ Assert.AreEqual(dataContractResult[0], jsonNetResult[0]);
+#if !SILVERLIGHT
+ Assert.AreEqual(javaScriptSerializerResult[0], jsonNetResult[0]);
+#endif
+ }
+
+ [Test]
+ [ExpectedException(typeof(JsonReaderException), ExpectedMessage = @"Bad JSON escape sequence: \j. Line 1, position 7.")]
+ public void InvalidBackslash()
+ {
+ string json = @"[""vvv\jvvv""]";
+
+ JsonConvert.DeserializeObject>(json);
+ }
+
[Test]
public void DateTimeTest()
{
@@ -1068,9 +1109,6 @@ keyword such as type of business.""
]
}";
- //JavaScriptSerializer serializer = new JavaScriptSerializer();
- //GoogleMapGeocoderStructure jsonGoogleMapGeocoder = serializer.Deserialize(json);
-
GoogleMapGeocoderStructure jsonGoogleMapGeocoder = JsonConvert.DeserializeObject(json);
}
@@ -2051,5 +2089,39 @@ keyword such as type of business.""
PersonPropertyClass newPersonPropertyClass = JsonConvert.DeserializeObject(json);
Assert.AreEqual(wagePerson.HourlyWage, ((WagePerson) newPersonPropertyClass.Person).HourlyWage);
}
+
+ public class ExistingValueClass
+ {
+ public Dictionary Dictionary { get; set; }
+ public List List { get; set; }
+
+ public ExistingValueClass()
+ {
+ Dictionary = new Dictionary
+ {
+ {"existing", "yup"}
+ };
+ List = new List
+ {
+ "existing"
+ };
+ }
+ }
+
+ [Test]
+ public void DeserializePopulateDictionaryAndList()
+ {
+ ExistingValueClass d = JsonConvert.DeserializeObject(@"{'Dictionary':{appended:'appended',existing:'new'}}");
+
+ Assert.IsNotNull(d);
+ Assert.IsNotNull(d.Dictionary);
+ Assert.AreEqual(typeof(Dictionary), d.Dictionary.GetType());
+ Assert.AreEqual(typeof(List), d.List.GetType());
+ Assert.AreEqual(2, d.Dictionary.Count);
+ Assert.AreEqual("new", d.Dictionary["existing"]);
+ Assert.AreEqual("appended", d.Dictionary["appended"]);
+ Assert.AreEqual(1, d.List.Count);
+ Assert.AreEqual("existing", d.List[0]);
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Bson/BsonReader.cs b/Src/Newtonsoft.Json/Bson/BsonReader.cs
index da3525df..7d5ebbe5 100644
--- a/Src/Newtonsoft.Json/Bson/BsonReader.cs
+++ b/Src/Newtonsoft.Json/Bson/BsonReader.cs
@@ -46,6 +46,8 @@ namespace Newtonsoft.Json.Bson
private char[] _charBuffer;
private BsonType _currentElementType;
private BsonReaderState _bsonReaderState;
+ private ContainerContext _currentContext;
+
private const int MaxCharBytesSize = 128;
private enum BsonReaderState
@@ -63,20 +65,9 @@ namespace Newtonsoft.Json.Bson
private class ContainerContext
{
- public JTokenType Type { get; private set; }
- public int Length { get; set; }
- private int _position;
- public int Position
- {
- get { return _position; }
- set
- {
- if (value > Length && Length != 0)
- throw new JsonReaderException("Read past end of current container context.");
-
- _position = value;
- }
- }
+ public readonly JTokenType Type;
+ public int Length;
+ public int Position;
public ContainerContext(JTokenType type)
{
@@ -188,7 +179,7 @@ namespace Newtonsoft.Json.Bson
_bsonReaderState = BsonReaderState.CodeWScopeScopeObject;
ContainerContext newContext = new ContainerContext(JTokenType.Object);
- _stack.Add(newContext);
+ PushContext(newContext);
newContext.Length = ReadInt32();
return true;
@@ -270,7 +261,7 @@ namespace Newtonsoft.Json.Bson
SetToken(token);
ContainerContext newContext = new ContainerContext(type);
- _stack.Add(newContext);
+ PushContext(newContext);
newContext.Length = ReadInt32();
return true;
}
@@ -292,7 +283,7 @@ namespace Newtonsoft.Json.Bson
ReadType(_currentElementType);
return true;
case State.PostValue:
- ContainerContext context = GetCurrentContext();
+ ContainerContext context = _currentContext;
if (context == null)
return false;
@@ -317,8 +308,8 @@ namespace Newtonsoft.Json.Bson
if (ReadByte() != 0)
throw new JsonReaderException("Unexpected end of object byte value.");
- _stack.RemoveAt(_stack.Count - 1);
- if (_stack.Count != 0)
+ PopContext();
+ if (_currentContext != null)
MovePosition(context.Length);
JsonToken endToken = (context.Type == JTokenType.Object) ? JsonToken.EndObject : JsonToken.EndArray;
@@ -344,6 +335,21 @@ namespace Newtonsoft.Json.Bson
return false;
}
+ private void PopContext()
+ {
+ _stack.RemoveAt(_stack.Count - 1);
+ if (_stack.Count == 0)
+ _currentContext = null;
+ else
+ _currentContext = _stack[_stack.Count - 1];
+ }
+
+ private void PushContext(ContainerContext newContext)
+ {
+ _stack.Add(newContext);
+ _currentContext = newContext;
+ }
+
private byte ReadByte()
{
MovePosition(1);
@@ -366,7 +372,7 @@ namespace Newtonsoft.Json.Bson
SetToken(JsonToken.StartObject);
ContainerContext newContext = new ContainerContext(JTokenType.Object);
- _stack.Add(newContext);
+ PushContext(newContext);
newContext.Length = ReadInt32();
break;
}
@@ -375,7 +381,7 @@ namespace Newtonsoft.Json.Bson
SetToken(JsonToken.StartArray);
ContainerContext newContext = new ContainerContext(JTokenType.Array);
- _stack.Add(newContext);
+ PushContext(newContext);
newContext.Length = ReadInt32();
break;
}
@@ -561,19 +567,9 @@ namespace Newtonsoft.Json.Bson
return (BsonType)_reader.ReadSByte();
}
- private ContainerContext GetCurrentContext()
- {
- int count = _stack.Count;
- if (count == 0)
- return null;
-
- return _stack[count - 1];
- }
-
private void MovePosition(int count)
{
- ContainerContext context = GetCurrentContext();
- context.Position += count;
+ _currentContext.Position += count;
}
private byte[] ReadBytes(int count)
diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs
index 0041749d..835dab90 100644
--- a/Src/Newtonsoft.Json/JsonConvert.cs
+++ b/Src/Newtonsoft.Json/JsonConvert.cs
@@ -29,6 +29,7 @@ using System.Globalization;
using Newtonsoft.Json.Utilities;
using System.Xml;
using Newtonsoft.Json.Converters;
+using System.Text;
namespace Newtonsoft.Json
{
@@ -96,14 +97,11 @@ namespace Newtonsoft.Json
/// A JSON string representation of the .
public static string ToString(DateTime value)
{
- TimeSpan utcOffset;
-#if !PocketPC && !NET20
- utcOffset = TimeZoneInfo.Local.GetUtcOffset(value);
-#else
- utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(value);
-#endif
-
- return ToStringInternal(value, utcOffset, value.Kind);
+ using (StringWriter writer = StringUtils.CreateStringWriter(64))
+ {
+ WriteDateTimeString(writer, value, GetUtcOffset(value), value.Kind);
+ return writer.ToString();
+ }
}
#if !PocketPC && !NET20
@@ -114,33 +112,95 @@ namespace Newtonsoft.Json
/// A JSON string representation of the .
public static string ToString(DateTimeOffset value)
{
- return ToStringInternal(value.UtcDateTime, value.Offset, DateTimeKind.Local);
+ using (StringWriter writer = StringUtils.CreateStringWriter(64))
+ {
+ WriteDateTimeString(writer, value.UtcDateTime, value.Offset, DateTimeKind.Local);
+ return writer.ToString();
+ }
}
#endif
- internal static string ToStringInternal(DateTime value, TimeSpan offset, DateTimeKind kind)
+ private static TimeSpan GetUtcOffset(DateTime dateTime)
{
- long javaScriptTicks = ConvertDateTimeToJavaScriptTicks(value);
+#if SILVERLIGHT
+ return TimeZoneInfo.Local.GetUtcOffset(dateTime);
+#else
+ return TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
+#endif
+ }
- string timezoneOffset;
+ internal static void WriteDateTimeString(TextWriter writer, DateTime value)
+ {
+ WriteDateTimeString(writer, value, GetUtcOffset(value), value.Kind);
+ }
+
+ internal static void WriteDateTimeString(TextWriter writer, DateTime value, TimeSpan offset, DateTimeKind kind)
+ {
+ long javaScriptTicks = ConvertDateTimeToJavaScriptTicks(value, offset);
+
+ writer.Write(@"""\/Date(");
+ writer.Write(javaScriptTicks);
+
switch (kind)
{
case DateTimeKind.Local:
case DateTimeKind.Unspecified:
- timezoneOffset = offset.Hours.ToString("+00;-00", CultureInfo.InvariantCulture) + offset.Minutes.ToString("00;00", CultureInfo.InvariantCulture);
- break;
- default:
- timezoneOffset = string.Empty;
+ writer.Write((offset.Ticks >= 0L) ? "+" : "-");
+
+ int absHours = Math.Abs(offset.Hours);
+ if (absHours < 10)
+ writer.Write(0);
+ writer.Write(absHours);
+ int absMinutes = Math.Abs(offset.Minutes);
+ if (absMinutes < 10)
+ writer.Write(0);
+ writer.Write(absMinutes);
break;
}
- return @"""\/Date(" + javaScriptTicks.ToString(CultureInfo.InvariantCulture) + timezoneOffset + @")\/""";
+
+ writer.Write(@")\/""");
+ }
+
+ private static long ToUniversalTicks(DateTime dateTime)
+ {
+ if (dateTime.Kind == DateTimeKind.Utc)
+ return dateTime.Ticks;
+
+ return ToUniversalTicks(dateTime, GetUtcOffset(dateTime));
+ }
+
+ private static long ToUniversalTicks(DateTime dateTime, TimeSpan offset)
+ {
+ if (dateTime.Kind == DateTimeKind.Utc)
+ return dateTime.Ticks;
+
+ long ticks = dateTime.Ticks - offset.Ticks;
+ if (ticks > 3155378975999999999L)
+ return 3155378975999999999L;
+
+ if (ticks < 0L)
+ return 0L;
+
+ return ticks;
+ }
+
+ internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, TimeSpan offset)
+ {
+ long universialTicks = ToUniversalTicks(dateTime, offset);
+
+ return UniversialTicksToJavaScriptTicks(universialTicks);
}
internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime)
{
- DateTime utcDateTime = dateTime.ToUniversalTime();
+ long universialTicks = ToUniversalTicks(dateTime);
- long javaScriptTicks = (utcDateTime.Ticks - InitialJavaScriptDateTicks) / 10000;
+ return UniversialTicksToJavaScriptTicks(universialTicks);
+ }
+
+ private static long UniversialTicksToJavaScriptTicks(long universialTicks)
+ {
+ long javaScriptTicks = (universialTicks - InitialJavaScriptDateTicks) / 10000;
return javaScriptTicks;
}
@@ -524,7 +584,8 @@ namespace Newtonsoft.Json
{
JsonSerializer jsonSerializer = JsonSerializer.Create(settings);
- StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
+ StringBuilder sb = new StringBuilder(128);
+ StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = formatting;
diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs
index c6a3b762..97e1d447 100644
--- a/Src/Newtonsoft.Json/JsonReader.cs
+++ b/Src/Newtonsoft.Json/JsonReader.cs
@@ -102,6 +102,7 @@ namespace Newtonsoft.Json
private Type _valueType;
private char _quoteChar;
private State _currentState;
+ private JTokenType _currentTypeContext;
///
/// Gets the current reader state.
@@ -182,6 +183,7 @@ namespace Newtonsoft.Json
{
_stack.Add(value);
_top++;
+ _currentTypeContext = value;
}
private JTokenType Pop()
@@ -189,13 +191,14 @@ namespace Newtonsoft.Json
JTokenType value = Peek();
_stack.RemoveAt(_stack.Count - 1);
_top--;
+ _currentTypeContext = _stack[_top - 1];
return value;
}
private JTokenType Peek()
{
- return _stack[_top - 1];
+ return _currentTypeContext;
}
///
diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs
index 9f5ba7c0..58255ee5 100644
--- a/Src/Newtonsoft.Json/JsonSerializer.cs
+++ b/Src/Newtonsoft.Json/JsonSerializer.cs
@@ -418,16 +418,6 @@ namespace Newtonsoft.Json
serializerWriter.Serialize(jsonWriter, value);
}
- internal bool HasClassConverter(JsonContract contract, out JsonConverter converter)
- {
- if (contract == null)
- throw new ArgumentNullException("contract");
-
- converter = contract.Converter;
-
- return (converter != null);
- }
-
internal bool HasMatchingConverter(Type type, out JsonConverter matchingConverter)
{
if (HasMatchingConverter(_converters, type, out matchingConverter))
diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs
index 373049d5..74b2f293 100644
--- a/Src/Newtonsoft.Json/JsonTextReader.cs
+++ b/Src/Newtonsoft.Json/JsonTextReader.cs
@@ -40,10 +40,10 @@ namespace Newtonsoft.Json
{
private readonly TextReader _reader;
private readonly StringBuffer _buffer;
- private char _currentChar;
+ private char? _lastChar;
private int _currentLinePosition;
private int _currentLineNumber;
- private bool _currentCharCarriageReturn;
+ private bool _end;
///
/// Initializes a new instance of the class with the specified .
@@ -61,7 +61,7 @@ namespace Newtonsoft.Json
private void ParseString(char quote)
{
- ReadStringIntoBuffer(quote, null);
+ ReadStringIntoBuffer(quote);
string text = _buffer.ToString();
_buffer.Position = 0;
@@ -77,23 +77,24 @@ namespace Newtonsoft.Json
}
}
- private void ReadStringIntoBuffer(char quote, int? untilPosition)
+ private void ReadStringIntoBuffer(char quote)
{
- bool stringTerminated = false;
- bool hexNumber = false;
- int hexCount = 0;
-
- while (!stringTerminated && (untilPosition == null || _buffer.Position < untilPosition) && MoveNext())
+ while (true)
{
- if (hexNumber)
- hexCount++;
+ char currentChar = MoveNext();
- switch (_currentChar)
+ switch (currentChar)
{
+ case '\0':
+ if (_end)
+ throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition);
+
+ _buffer.Append('\0');
+ break;
case '\\':
- if (MoveNext())
+ if ((currentChar = MoveNext()) != '\0' || !_end)
{
- switch (_currentChar)
+ switch (currentChar)
{
case 'b':
_buffer.Append('\b');
@@ -110,13 +111,29 @@ namespace Newtonsoft.Json
case 'r':
_buffer.Append('\r');
break;
+ case '\\':
+ _buffer.Append('\\');
+ break;
+ case '"':
+ case '\'':
+ case '/':
+ _buffer.Append(currentChar);
+ break;
case 'u':
- // note the start of a hex character
- hexNumber = true;
+ char[] hexValues = new char[4];
+ for (int i = 0; i < hexValues.Length; i++)
+ {
+ if ((currentChar = MoveNext()) != '\0' || !_end)
+ hexValues[i] = currentChar;
+ else
+ throw CreateJsonReaderException("Unexpected end while parsing unicode character. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
+ }
+
+ char hexChar = Convert.ToChar(int.Parse(new string(hexValues), NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo));
+ _buffer.Append(hexChar);
break;
default:
- _buffer.Append(_currentChar);
- break;
+ throw CreateJsonReaderException("Bad JSON escape sequence: {0}. Line {1}, position {2}.", @"\" + currentChar, _currentLineNumber, _currentLinePosition);
}
}
else
@@ -126,34 +143,20 @@ namespace Newtonsoft.Json
break;
case '"':
case '\'':
- if (_currentChar == quote)
- stringTerminated = true;
+ if (currentChar == quote)
+ {
+ return;
+ }
else
- goto default;
+ {
+ _buffer.Append(currentChar);
+ }
break;
default:
- _buffer.Append(_currentChar);
+ _buffer.Append(currentChar);
break;
}
-
- if (hexCount == 4)
- {
- // remove hex characters from buffer, convert to char and then add
- string hexString = _buffer.ToString(_buffer.Position - 4, 4);
- char hexChar = Convert.ToChar(int.Parse(hexString, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo));
-
- _buffer.Position = _buffer.Position - 4;
- _buffer.Append(hexChar);
-
- hexNumber = false;
- hexCount = 0;
- }
}
-
- if (!stringTerminated)
- throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition);
-
- ClearCurrentChar();
}
private JsonReaderException CreateJsonReaderException(string format, params object[] args)
@@ -162,41 +165,6 @@ namespace Newtonsoft.Json
return new JsonReaderException(message, null, _currentLineNumber, _currentLinePosition);
}
- ///
- /// Sets the current token and value.
- ///
- /// The new token.
- /// The value.
- protected override void SetToken(JsonToken newToken, object value)
- {
- base.SetToken(newToken, value);
-
- switch (newToken)
- {
- case JsonToken.StartObject:
- ClearCurrentChar();
- break;
- case JsonToken.StartArray:
- ClearCurrentChar();
- break;
- case JsonToken.StartConstructor:
- ClearCurrentChar();
- break;
- case JsonToken.EndObject:
- ClearCurrentChar();
- break;
- case JsonToken.EndArray:
- ClearCurrentChar();
- break;
- case JsonToken.EndConstructor:
- ClearCurrentChar();
- break;
- case JsonToken.PropertyName:
- ClearCurrentChar();
- break;
- }
- }
-
private void ParseDate(string text)
{
string value = text.Substring(6, text.Length - 8);
@@ -236,34 +204,32 @@ namespace Newtonsoft.Json
private const int LineFeedValue = StringUtils.LineFeed;
private const int CarriageReturnValue = StringUtils.CarriageReturn;
- private bool MoveNext()
+ private char MoveNext()
{
int value = _reader.Read();
switch (value)
{
case -1:
- return false;
+ _end = true;
+ return '\0';
case CarriageReturnValue:
+ if (_reader.Peek() == LineFeedValue)
+ _reader.Read();
+
_currentLineNumber++;
_currentLinePosition = 0;
- _currentCharCarriageReturn = true;
break;
case LineFeedValue:
- if (!_currentCharCarriageReturn)
- _currentLineNumber++;
-
+ _currentLineNumber++;
_currentLinePosition = 0;
- _currentCharCarriageReturn = false;
break;
default:
_currentLinePosition++;
- _currentCharCarriageReturn = false;
break;
}
- _currentChar = (char)value;
- return true;
+ return (char)value;
}
private bool HasNext()
@@ -271,14 +237,9 @@ namespace Newtonsoft.Json
return (_reader.Peek() != -1);
}
- private char PeekNext()
+ private int PeekNext()
{
- return (char)_reader.Peek();
- }
-
- private void ClearCurrentChar()
- {
- _currentChar = '\0';
+ return _reader.Peek();
}
///
@@ -291,11 +252,19 @@ namespace Newtonsoft.Json
{
while (true)
{
- if (_currentChar == '\0')
+ char currentChar;
+ if (_lastChar != null)
{
- if (!MoveNext())
- return false;
+ currentChar = _lastChar.Value;
+ _lastChar = null;
}
+ else
+ {
+ currentChar = MoveNext();
+ }
+
+ if (currentChar == '\0' && _end)
+ return false;
switch (CurrentState)
{
@@ -305,16 +274,16 @@ namespace Newtonsoft.Json
case State.ArrayStart:
case State.Constructor:
case State.ConstructorStart:
- return ParseValue();
+ return ParseValue(currentChar);
case State.Complete:
break;
case State.Object:
case State.ObjectStart:
- return ParseObject();
+ return ParseObject(currentChar);
case State.PostValue:
// returns true if it hits
// end of object or array
- if (ParsePostValue())
+ if (ParsePostValue(currentChar))
return true;
break;
case State.Closed:
@@ -337,14 +306,23 @@ namespace Newtonsoft.Json
{
while (true)
{
- if (_currentChar == '\0')
+ char currentChar;
+ if (_lastChar != null)
{
- if (!MoveNext())
- throw CreateJsonReaderException("Unexpected end: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
+ currentChar = _lastChar.Value;
+ _lastChar = null;
}
+ else
+ {
+ currentChar = MoveNext();
+ }
+
+ if (currentChar == '\0' && _end)
+ throw CreateJsonReaderException("Unexpected end when reading bytes: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
switch (CurrentState)
{
+ case State.PostValue:
case State.Start:
case State.Property:
case State.Array:
@@ -353,11 +331,11 @@ namespace Newtonsoft.Json
case State.ConstructorStart:
do
{
- switch (_currentChar)
+ switch (currentChar)
{
case '"':
case '\'':
- ReadStringIntoBuffer(_currentChar, null);
+ ReadStringIntoBuffer(currentChar);
byte[] data = Convert.FromBase64CharArray(_buffer.GetInternalBuffer(), 0, _buffer.Position);
_buffer.Position = 0;
@@ -368,19 +346,27 @@ namespace Newtonsoft.Json
case 'n':
ParseNull();
return null;
+ case ' ':
+ case StringUtils.Tab:
+ case StringUtils.LineFeed:
+ case StringUtils.CarriageReturn:
+ // eat
+ break;
+ case ',':
+ SetStateBasedOnCurrent();
+ break;
default:
- if (char.IsWhiteSpace(_currentChar))
+ if (char.IsWhiteSpace(currentChar))
{
// eat
}
else
{
- throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
+ throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
}
break;
}
- } while (MoveNext());
- ParseValue();
+ } while ((currentChar = MoveNext()) != '\0' || !_end);
break;
default:
throw CreateJsonReaderException("Unexpected state: {0}. Line {1}, position {2}.", CurrentState, _currentLineNumber, _currentLinePosition);
@@ -388,115 +374,114 @@ namespace Newtonsoft.Json
}
}
- private bool ParsePostValue()
+ private bool ParsePostValue(char currentChar)
{
do
{
- switch (_currentChar)
+ switch (currentChar)
{
case '}':
SetToken(JsonToken.EndObject);
- ClearCurrentChar();
return true;
case ']':
SetToken(JsonToken.EndArray);
- ClearCurrentChar();
return true;
case ')':
SetToken(JsonToken.EndConstructor);
- ClearCurrentChar();
return true;
case '/':
ParseComment();
return true;
case ',':
- // finished paring
+ // finished parsing
SetStateBasedOnCurrent();
- ClearCurrentChar();
return false;
case ' ':
- // eat whitespace
- ClearCurrentChar();
- break;
- default:
- if (char.IsWhiteSpace(_currentChar))
- {
- // eat whitespace
- ClearCurrentChar();
- }
- else
- {
- throw CreateJsonReaderException("After parsing a value an unexpected character was encoutered: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
- }
- break;
- }
- } while (MoveNext());
-
- return false;
- }
-
- private bool ParseObject()
- {
- do
- {
- switch (_currentChar)
- {
- case '}':
- SetToken(JsonToken.EndObject);
- return true;
- case '/':
- ParseComment();
- return true;
- case ',':
- SetToken(JsonToken.Undefined);
- return true;
- case ' ':
+ case StringUtils.Tab:
+ case StringUtils.LineFeed:
+ case StringUtils.CarriageReturn:
// eat
break;
default:
- if (char.IsWhiteSpace(_currentChar))
+ if (char.IsWhiteSpace(currentChar))
{
// eat
}
else
{
- return ParseProperty();
+ throw CreateJsonReaderException("After parsing a value an unexpected character was encoutered: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
}
break;
}
- } while (MoveNext());
+ } while ((currentChar = MoveNext()) != '\0' || !_end);
return false;
}
- private bool ParseProperty()
+ private bool ParseObject(char currentChar)
{
+ do
+ {
+ switch (currentChar)
+ {
+ case '}':
+ SetToken(JsonToken.EndObject);
+ return true;
+ case '/':
+ ParseComment();
+ return true;
+ case ' ':
+ case StringUtils.Tab:
+ case StringUtils.LineFeed:
+ case StringUtils.CarriageReturn:
+ // eat
+ break;
+ default:
+ if (char.IsWhiteSpace(currentChar))
+ {
+ // eat
+ }
+ else
+ {
+ return ParseProperty(currentChar);
+ }
+ break;
+ }
+ } while ((currentChar = MoveNext()) != '\0' || !_end);
+
+ return false;
+ }
+
+ private bool ParseProperty(char firstChar)
+ {
+ char currentChar = firstChar;
char quoteChar;
- if (ValidIdentifierChar(_currentChar))
+ if (ValidIdentifierChar(currentChar))
{
quoteChar = '\0';
- ParseUnquotedProperty();
+ currentChar = ParseUnquotedProperty(currentChar);
}
- else if (_currentChar == '"' || _currentChar == '\'')
+ else if (currentChar == '"' || currentChar == '\'')
{
- quoteChar = _currentChar;
- ParseQuotedProperty(_currentChar);
+ quoteChar = currentChar;
+ ReadStringIntoBuffer(quoteChar);
+ currentChar = MoveNext();
}
else
{
- throw CreateJsonReaderException("Invalid property identifier character: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
+ throw CreateJsonReaderException("Invalid property identifier character: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
}
- if (_currentChar != ':')
+ if (currentChar != ':')
{
- MoveNext();
+ currentChar = MoveNext();
// finished property. skip any whitespace and move to colon
- EatWhitespace(false);
+ EatWhitespace(currentChar, false, out currentChar);
- if (_currentChar != ':')
- throw CreateJsonReaderException("Invalid character after parsing property name. Expected ':' but got: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
+ if (currentChar != ':')
+ throw CreateJsonReaderException("Invalid character after parsing property name. Expected ':' but got: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
}
SetToken(JsonToken.PropertyName, _buffer.ToString());
@@ -506,60 +491,46 @@ namespace Newtonsoft.Json
return true;
}
- private void ParseQuotedProperty(char quoteChar)
- {
- // parse property name until quoted char is hit
- while (MoveNext())
- {
- if (_currentChar == quoteChar)
- {
- return;
- }
- else
- {
- _buffer.Append(_currentChar);
- }
- }
-
- throw CreateJsonReaderException("Unclosed quoted property. Expected: {0}. Line {1}, position {2}.", quoteChar, _currentLineNumber, _currentLinePosition);
- }
-
private bool ValidIdentifierChar(char value)
{
- return (char.IsLetterOrDigit(_currentChar) || _currentChar == '_' || _currentChar == '$');
+ return (char.IsLetterOrDigit(value) || value == '_' || value == '$');
}
- private void ParseUnquotedProperty()
+ private char ParseUnquotedProperty(char firstChar)
{
// parse unquoted property name until whitespace or colon
- _buffer.Append(_currentChar);
+ _buffer.Append(firstChar);
- while (MoveNext())
+ char currentChar;
+
+ while ((currentChar = MoveNext()) != '\0' || !_end)
{
- if (char.IsWhiteSpace(_currentChar) || _currentChar == ':')
+ if (char.IsWhiteSpace(currentChar) || currentChar == ':')
{
- break;
+ return currentChar;
}
- else if (ValidIdentifierChar(_currentChar))
+ else if (ValidIdentifierChar(currentChar))
{
- _buffer.Append(_currentChar);
+ _buffer.Append(currentChar);
}
else
{
- throw CreateJsonReaderException("Invalid JavaScript property identifier character: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
+ throw CreateJsonReaderException("Invalid JavaScript property identifier character: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
}
}
+
+ throw CreateJsonReaderException("Unexpected end when parsing unquoted property name. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
- private bool ParseValue()
+ private bool ParseValue(char currentChar)
{
do
{
- switch (_currentChar)
+ switch (currentChar)
{
case '"':
case '\'':
- ParseString(_currentChar);
+ ParseString(currentChar);
return true;
case 't':
ParseTrue();
@@ -570,14 +541,14 @@ namespace Newtonsoft.Json
case 'n':
if (HasNext())
{
- char next = PeekNext();
+ char next = (char)PeekNext();
if (next == 'u')
ParseNull();
else if (next == 'e')
ParseConstructor();
else
- throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
+ throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
}
else
{
@@ -594,7 +565,7 @@ namespace Newtonsoft.Json
if (PeekNext() == 'I')
ParseNumberNegativeInfinity();
else
- ParseNumber();
+ ParseNumber(currentChar);
return true;
case '/':
ParseComment();
@@ -616,63 +587,70 @@ namespace Newtonsoft.Json
return true;
case ',':
SetToken(JsonToken.Undefined);
- //ClearCurrentChar();
return true;
case ')':
SetToken(JsonToken.EndConstructor);
return true;
case ' ':
+ case StringUtils.Tab:
+ case StringUtils.LineFeed:
+ case StringUtils.CarriageReturn:
// eat
break;
default:
- if (char.IsWhiteSpace(_currentChar))
+ if (char.IsWhiteSpace(currentChar))
{
// eat
}
- else if (char.IsNumber(_currentChar) || _currentChar == '-' || _currentChar == '.')
+ else if (char.IsNumber(currentChar) || currentChar == '-' || currentChar == '.')
{
- ParseNumber();
+ ParseNumber(currentChar);
return true;
}
else
{
- throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
+ throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
}
break;
}
- } while (MoveNext());
+ } while ((currentChar = MoveNext()) != '\0' || !_end);
return false;
}
- private bool EatWhitespace(bool oneOrMore)
+ private bool EatWhitespace(char initialChar, bool oneOrMore, out char finalChar)
{
bool whitespace = false;
- while (_currentChar == ' ' || char.IsWhiteSpace(_currentChar))
+ char currentChar = initialChar;
+ while (currentChar == ' ' || char.IsWhiteSpace(currentChar))
{
whitespace = true;
- MoveNext();
+ currentChar = MoveNext();
}
+ finalChar = currentChar;
+
return (!oneOrMore || whitespace);
}
private void ParseConstructor()
{
- if (MatchValue("new", true))
+ if (MatchValue('n', "new", true))
{
- if (EatWhitespace(true))
+ char currentChar = MoveNext();
+
+ if (EatWhitespace(currentChar, true, out currentChar))
{
- while (char.IsLetter(_currentChar))
+ while (char.IsLetter(currentChar))
{
- _buffer.Append(_currentChar);
- MoveNext();
+ _buffer.Append(currentChar);
+ currentChar = MoveNext();
}
- EatWhitespace(false);
+ EatWhitespace(currentChar, false, out currentChar);
- if (_currentChar != '(')
- throw CreateJsonReaderException("Unexpected character while parsing constructor: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
+ if (currentChar != '(')
+ throw CreateJsonReaderException("Unexpected character while parsing constructor: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
string constructorName = _buffer.ToString();
_buffer.Position = 0;
@@ -682,22 +660,25 @@ namespace Newtonsoft.Json
}
}
- private void ParseNumber()
+ private void ParseNumber(char firstChar)
{
+ char currentChar = firstChar;
+
// parse until seperator character or end
bool end = false;
do
{
- if (CurrentIsSeperator())
+ if (IsSeperator(currentChar))
+ {
end = true;
+ _lastChar = currentChar;
+ }
else
- _buffer.Append(_currentChar);
+ {
+ _buffer.Append(currentChar);
+ }
- } while (!end && MoveNext());
-
- // hit the end of the reader before the number ended. clear the last number value
- if (!end)
- ClearCurrentChar();
+ } while (!end && ((currentChar = MoveNext()) != '\0' || !_end));
string number = _buffer.ToString();
object numberValue;
@@ -706,12 +687,12 @@ namespace Newtonsoft.Json
if (number.IndexOf(".", StringComparison.OrdinalIgnoreCase) == -1
&& number.IndexOf("e", StringComparison.OrdinalIgnoreCase) == -1)
{
- numberValue = Convert.ToInt64(_buffer.ToString(), CultureInfo.InvariantCulture);
+ numberValue = Convert.ToInt64(number, CultureInfo.InvariantCulture);
numberType = JsonToken.Integer;
}
else
{
- numberValue = Convert.ToDouble(_buffer.ToString(), CultureInfo.InvariantCulture);
+ numberValue = Convert.ToDouble(number, CultureInfo.InvariantCulture);
numberType = JsonToken.Float;
}
@@ -724,30 +705,30 @@ namespace Newtonsoft.Json
{
// should have already parsed / character before reaching this method
- MoveNext();
+ char currentChar = MoveNext();
- if (_currentChar == '*')
+ if (currentChar == '*')
{
- while (MoveNext())
+ while ((currentChar = MoveNext()) != '\0' || !_end)
{
- if (_currentChar == '*')
+ if (currentChar == '*')
{
- if (MoveNext())
+ if ((currentChar = MoveNext()) != '\0' || !_end)
{
- if (_currentChar == '/')
+ if (currentChar == '/')
{
break;
}
else
{
_buffer.Append('*');
- _buffer.Append(_currentChar);
+ _buffer.Append(currentChar);
}
}
}
else
{
- _buffer.Append(_currentChar);
+ _buffer.Append(currentChar);
}
}
}
@@ -759,30 +740,30 @@ namespace Newtonsoft.Json
SetToken(JsonToken.Comment, _buffer.ToString());
_buffer.Position = 0;
-
- ClearCurrentChar();
}
- private bool MatchValue(string value)
+ private bool MatchValue(char firstChar, string value)
{
+ char currentChar = firstChar;
+
int i = 0;
do
{
- if (_currentChar != value[i])
+ if (currentChar != value[i])
{
break;
}
i++;
}
- while (i < value.Length && MoveNext());
+ while (i < value.Length && ((currentChar = MoveNext()) != '\0' || !_end));
return (i == value.Length);
}
- private bool MatchValue(string value, bool noTrailingNonSeperatorCharacters)
+ private bool MatchValue(char firstChar, string value, bool noTrailingNonSeperatorCharacters)
{
// will match value and then move to the next character, checking that it is a seperator character
- bool match = MatchValue(value);
+ bool match = MatchValue(firstChar, value);
if (!noTrailingNonSeperatorCharacters)
{
@@ -790,17 +771,17 @@ namespace Newtonsoft.Json
}
else
{
- bool matchAndNoTrainingNonSeperatorCharacters = (match && (!MoveNext() || CurrentIsSeperator()));
- if (!CurrentIsSeperator())
- ClearCurrentChar();
+ int c = PeekNext();
+ char next = (c != -1) ? (char) c : '\0';
+ bool matchAndNoTrainingNonSeperatorCharacters = (match && (next == '\0' || IsSeperator(next)));
return matchAndNoTrainingNonSeperatorCharacters;
}
}
- private bool CurrentIsSeperator()
+ private bool IsSeperator(char c)
{
- switch (_currentChar)
+ switch (c)
{
case '}':
case ']':
@@ -814,9 +795,12 @@ namespace Newtonsoft.Json
return true;
break;
case ' ':
+ case StringUtils.Tab:
+ case StringUtils.LineFeed:
+ case StringUtils.CarriageReturn:
return true;
default:
- if (char.IsWhiteSpace(_currentChar))
+ if (char.IsWhiteSpace(c))
return true;
break;
}
@@ -829,7 +813,7 @@ namespace Newtonsoft.Json
// check characters equal 'true'
// and that it is followed by either a seperator character
// or the text ends
- if (MatchValue(JsonConvert.True, true))
+ if (MatchValue('t', JsonConvert.True, true))
{
SetToken(JsonToken.Boolean, true);
}
@@ -841,7 +825,7 @@ namespace Newtonsoft.Json
private void ParseNull()
{
- if (MatchValue(JsonConvert.Null, true))
+ if (MatchValue('n', JsonConvert.Null, true))
{
SetToken(JsonToken.Null);
}
@@ -853,7 +837,7 @@ namespace Newtonsoft.Json
private void ParseUndefined()
{
- if (MatchValue(JsonConvert.Undefined, true))
+ if (MatchValue('u', JsonConvert.Undefined, true))
{
SetToken(JsonToken.Undefined);
}
@@ -865,7 +849,7 @@ namespace Newtonsoft.Json
private void ParseFalse()
{
- if (MatchValue(JsonConvert.False, true))
+ if (MatchValue('f', JsonConvert.False, true))
{
SetToken(JsonToken.Boolean, false);
}
@@ -877,7 +861,7 @@ namespace Newtonsoft.Json
private void ParseNumberNegativeInfinity()
{
- if (MatchValue(JsonConvert.NegativeInfinity, true))
+ if (MatchValue('-', JsonConvert.NegativeInfinity, true))
{
SetToken(JsonToken.Float, double.NegativeInfinity);
}
@@ -889,7 +873,7 @@ namespace Newtonsoft.Json
private void ParseNumberPositiveInfinity()
{
- if (MatchValue(JsonConvert.PositiveInfinity, true))
+ if (MatchValue('I', JsonConvert.PositiveInfinity, true))
{
SetToken(JsonToken.Float, double.PositiveInfinity);
}
@@ -901,7 +885,7 @@ namespace Newtonsoft.Json
private void ParseNumberNaN()
{
- if (MatchValue(JsonConvert.NaN, true))
+ if (MatchValue('N', JsonConvert.NaN, true))
{
SetToken(JsonToken.Float, double.NaN);
}
@@ -964,4 +948,4 @@ namespace Newtonsoft.Json
get { return _currentLinePosition; }
}
}
-}
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs
index df444f76..df7b7d85 100644
--- a/Src/Newtonsoft.Json/JsonTextWriter.cs
+++ b/Src/Newtonsoft.Json/JsonTextWriter.cs
@@ -288,7 +288,15 @@ namespace Newtonsoft.Json
public override void WriteValue(string value)
{
base.WriteValue(value);
- WriteValueInternal((value != null) ? JsonConvert.ToString(value, _quoteChar) : JsonConvert.Null, JsonToken.String);
+ if (value == null)
+ WriteValueInternal(JsonConvert.Null, JsonToken.Null);
+ else
+ {
+ JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, true);
+ //_writer.Write(JavaScriptUtils.EscapeJavaScriptString(value, _quoteChar, false));
+ //WriteValueInternal(, JsonToken.String);
+ //JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, true);
+ }
}
///
@@ -428,7 +436,7 @@ namespace Newtonsoft.Json
public override void WriteValue(DateTime value)
{
base.WriteValue(value);
- WriteValueInternal(JsonConvert.ToString(value), JsonToken.Date);
+ JsonConvert.WriteDateTimeString(_writer, value);
}
///
diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs
index 2a7ddc6f..3b5b9884 100644
--- a/Src/Newtonsoft.Json/JsonWriter.cs
+++ b/Src/Newtonsoft.Json/JsonWriter.cs
@@ -107,17 +107,17 @@ namespace Newtonsoft.Json
}
// array that gives a new state based on the current state an the token being written
- private static readonly State[,] stateArray = {
+ private static readonly State[][] stateArray = new[] {
// Start PropertyName ObjectStart Object ArrayStart Array ConstructorStart Constructor Closed Error
//
-/* None */{ State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
-/* StartObject */{ State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.Error, State.Error },
-/* StartArray */{ State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.Error, State.Error },
-/* StartConstructor */{ State.ConstructorStart, State.ConstructorStart, State.Error, State.Error, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error, State.Error },
-/* StartProperty */{ State.Property, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
-/* Comment */{ State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
-/* Raw */{ State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
-/* Value */{ State.Start, State.Object, State.Error, State.Error, State.Array, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
+/* None */new[]{ State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
+/* StartObject */new[]{ State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.Error, State.Error },
+/* StartArray */new[]{ State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.Error, State.Error },
+/* StartConstructor */new[]{ State.ConstructorStart, State.ConstructorStart, State.Error, State.Error, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error, State.Error },
+/* StartProperty */new[]{ State.Property, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
+/* Comment */new[]{ State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
+/* Raw */new[]{ State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
+/* Value */new[]{ State.Start, State.Object, State.Error, State.Error, State.Array, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
};
private int _top;
@@ -586,7 +586,7 @@ namespace Newtonsoft.Json
}
// gets new state based on the current state and what is being written
- State newState = stateArray[token, (int)_currentState];
+ State newState = stateArray[token][(int)_currentState];
if (newState == State.Error)
throw new JsonWriterException("Token {0} in state {1} would result in an invalid JavaScript object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()));
diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
index 9868d3b1..b4f41e02 100644
--- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
+++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
@@ -209,7 +209,7 @@ namespace Newtonsoft.Json.Serialization
if (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, true)
|| contract.CreatedType.IsValueType)
{
-#if !PocketPC
+#if !PocketPC && !SILVERLIGHT
contract.DefaultCreator = LateBoundDelegateFactory.CreateDefaultConstructor(contract.CreatedType);
#else
ConstructorInfo constructorInfo = ReflectionUtils.GetDefaultConstructor(contract.CreatedType, true);
@@ -414,7 +414,7 @@ namespace Newtonsoft.Json.Serialization
{
JsonProperty property = new JsonProperty();
property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member);
-#if !PocketPC
+#if !PocketPC && !SILVERLIGHT
property.ValueProvider = new DynamicValueProvider(member);
#else
property.ValueProvider = new ReflectionValueProvider(member);
diff --git a/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs b/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs
index d0ad41cb..41736ed5 100644
--- a/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs
+++ b/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs
@@ -23,7 +23,7 @@
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
-#if !PocketPC
+#if !PocketPC && !SILVERLIGHT
using System;
using System.Collections.Generic;
using System.Linq;
@@ -65,6 +65,20 @@ namespace Newtonsoft.Json.Serialization
if (_setter == null)
_setter = LateBoundDelegateFactory.CreateSet