diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs index d57e264b..6c3ae9d4 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs @@ -83,6 +83,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -172,6 +173,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndArray, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } @@ -220,6 +222,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -261,6 +264,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndArray, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -322,6 +326,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndArray, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); string decodedString = Encoding.UTF8.GetString(encodedStringData, 0, encodedStringData.Length); Assert.AreEqual("Hello world!", decodedString); @@ -360,6 +365,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -418,6 +424,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -492,6 +499,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -520,6 +528,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -548,6 +557,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -576,6 +586,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -622,6 +633,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -680,6 +692,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -722,6 +735,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -746,6 +760,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -796,6 +811,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -1107,6 +1123,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -1158,6 +1175,7 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.EndObject, reader.TokenType); Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs index 987489df..bda2f3e3 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs @@ -553,12 +553,13 @@ Parameter name: reader")] } [Test] - [ExpectedException(typeof(JsonReaderException), ExpectedMessage = "Unexpected end when reading bytes. Line 1, position 3.")] public void ReadBytesNoStartWithUnexpectedEnd() { JsonReader reader = new JsonTextReader(new StringReader(@"[ ")); Assert.IsTrue(reader.Read()); - reader.ReadAsBytes(); + + Assert.IsNull(reader.ReadAsBytes()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -909,11 +910,11 @@ bye", reader.Value); Assert.AreEqual(typeof(string), reader.ValueType); Assert.AreEqual(20000, reader.Value.ToString().Length); - reader.Read(); + Assert.IsTrue(reader.Read()); Assert.AreEqual(JsonToken.EndArray, reader.TokenType); - reader.Read(); - Assert.AreEqual(JsonToken.EndArray, reader.TokenType); + Assert.IsFalse(reader.Read()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -1128,21 +1129,21 @@ bye", reader.Value); } [Test] - [ExpectedException(typeof(JsonReaderException), ExpectedMessage = "Unexpected end when reading decimal. Line 0, position 0.")] public void ReadAsDecimalNoContent() { JsonTextReader reader = new JsonTextReader(new StringReader(@"")); - reader.ReadAsDecimal(); + Assert.IsNull(reader.ReadAsDecimal()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] - [ExpectedException(typeof(JsonReaderException), ExpectedMessage = "Unexpected end when reading bytes. Line 0, position 0.")] public void ReadAsBytesNoContent() { JsonTextReader reader = new JsonTextReader(new StringReader(@"")); - reader.ReadAsBytes(); + Assert.IsNull(reader.ReadAsBytes()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] @@ -1156,12 +1157,12 @@ bye", reader.Value); #if !NET20 [Test] - [ExpectedException(typeof(JsonReaderException), ExpectedMessage = "Unexpected end when reading date. Line 0, position 0.")] public void ReadAsDateTimeOffsetNoContent() { JsonTextReader reader = new JsonTextReader(new StringReader(@"")); - reader.ReadAsDateTimeOffset(); + Assert.IsNull(reader.ReadAsDateTimeOffset()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } #endif @@ -1171,7 +1172,8 @@ bye", reader.Value); { JsonTextReader reader = new JsonTextReader(new StringReader(@"new Date()")); - reader.ReadAsDecimal(); + Assert.IsNull(reader.ReadAsDecimal()); + Assert.AreEqual(JsonToken.None, reader.TokenType); } [Test] diff --git a/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs b/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs index ae065654..c2729960 100644 --- a/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs @@ -1453,5 +1453,75 @@ namespace Newtonsoft.Json.Tests Assert.AreEqual(2, values[1]); Assert.AreEqual(3, values[2]); } + + [Test] + public void ReadAsInt32InArray() + { + string schemaJson = @"{ + ""type"":""array"", + ""items"":{ + ""type"":""integer"" + }, + ""maxItems"":1 +}"; + + string json = "[1,2]"; + + Json.Schema.ValidationEventArgs validationEventArgs = null; + + JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json))); + reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; }; + reader.Schema = JsonSchema.Parse(schemaJson); + + reader.Read(); + Assert.AreEqual(JsonToken.StartArray, reader.TokenType); + + reader.ReadAsInt32(); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + Assert.AreEqual(null, validationEventArgs); + + reader.ReadAsInt32(); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + Assert.AreEqual(null, validationEventArgs); + + reader.ReadAsInt32(); + Assert.AreEqual(JsonToken.EndArray, reader.TokenType); + Assert.AreEqual("Array item count 2 exceeds maximum count of 1. Line 1, position 5.", validationEventArgs.Message); + } + + [Test] + public void ReadAsInt32InArrayIncomplete() + { + string schemaJson = @"{ + ""type"":""array"", + ""items"":{ + ""type"":""integer"" + }, + ""maxItems"":1 +}"; + + string json = "[1,2"; + + Json.Schema.ValidationEventArgs validationEventArgs = null; + + JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json))); + reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; }; + reader.Schema = JsonSchema.Parse(schemaJson); + + reader.Read(); + Assert.AreEqual(JsonToken.StartArray, reader.TokenType); + + reader.ReadAsInt32(); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + Assert.AreEqual(null, validationEventArgs); + + reader.ReadAsInt32(); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + Assert.AreEqual(null, validationEventArgs); + + reader.ReadAsInt32(); + Assert.AreEqual(JsonToken.None, reader.TokenType); + Assert.AreEqual(null, validationEventArgs); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenReaderTest.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenReaderTest.cs index 1d3a35e9..1a201ba4 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenReaderTest.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenReaderTest.cs @@ -97,6 +97,7 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(JsonToken.EndObject, jsonReader.TokenType); Assert.IsFalse(jsonReader.Read()); + Assert.AreEqual(JsonToken.None, jsonReader.TokenType); } using (JsonReader jsonReader = new JTokenReader(o.Property("Test2"))) @@ -110,6 +111,7 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(new DateTimeOffset(2000, 10, 15, 5, 5, 5, new TimeSpan(11, 11, 0)), jsonReader.Value); Assert.IsFalse(jsonReader.Read()); + Assert.AreEqual(JsonToken.None, jsonReader.TokenType); } } @@ -255,6 +257,9 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(0, lineInfo.LineNumber); Assert.AreEqual(0, lineInfo.LinePosition); Assert.AreEqual(false, lineInfo.HasLineInfo()); + + jsonReader.Read(); + Assert.AreEqual(jsonReader.TokenType, JsonToken.None); } } @@ -284,6 +289,7 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(JsonToken.EndObject, jsonReader.TokenType); Assert.IsFalse(jsonReader.Read()); + Assert.AreEqual(JsonToken.None, jsonReader.TokenType); } } diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index d407433c..015fac8a 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -5180,7 +5180,7 @@ keyword such as type of business."" } [Test] - [ExpectedException(typeof (JsonReaderException), ExpectedMessage = "Unexpected end when reading integer. Line 2, position 18.")] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Unexpected end when setting PreProperty's value. Line 2, position 18.")] public void DeserializeUnexpectedEndInt() { string json = @"{ @@ -5297,6 +5297,80 @@ keyword such as type of business."" var dict2 = serializer.Deserialize>(reader); Assert.AreEqual(dict["k1"], dict2["k1"]); + } + + [Test] + public void DeserializeEmptyStrings() + { + object v = JsonConvert.DeserializeObject(""); + Assert.IsNull(v); + + v = JsonConvert.DeserializeObject(""); + Assert.IsNull(v); + + v = JsonConvert.DeserializeObject(""); + Assert.IsNull(v); + + v = JsonConvert.DeserializeObject(""); + Assert.IsNull(v); + + v = JsonConvert.DeserializeObject(""); + Assert.IsNull(v); + + v = JsonConvert.DeserializeObject(""); + Assert.IsNull(v); + + v = JsonConvert.DeserializeObject(""); + Assert.IsNull(v); + } + + public class Sdfsdf + { + public double Id { get; set; } + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "No JSON content found and type 'System.Double' is not nullable.")] + public void DeserializeDoubleFromEmptyString() + { + JsonConvert.DeserializeObject(""); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "No JSON content found and type 'System.StringComparison' is not nullable.")] + public void DeserializeEnumFromEmptyString() + { + JsonConvert.DeserializeObject(""); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "No JSON content found and type 'System.Int32' is not nullable.")] + public void DeserializeInt32FromEmptyString() + { + JsonConvert.DeserializeObject(""); + } + + [Test] + public void DeserializeByteArrayFromEmptyString() + { + byte[] b = JsonConvert.DeserializeObject(""); + Assert.IsNull(b); + } + + [Test] + [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null. +Parameter name: value")] + public void DeserializeDoubleFromNullString() + { + JsonConvert.DeserializeObject(null); + } + + [Test] + [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null. +Parameter name: value")] + public void DeserializeFromNullString() + { + JsonConvert.DeserializeObject(null); } } diff --git a/Src/Newtonsoft.Json/Bson/BsonReader.cs b/Src/Newtonsoft.Json/Bson/BsonReader.cs index 5d377a77..c80491d8 100644 --- a/Src/Newtonsoft.Json/Bson/BsonReader.cs +++ b/Src/Newtonsoft.Json/Bson/BsonReader.cs @@ -350,26 +350,40 @@ namespace Newtonsoft.Json.Bson { try { + bool success; + switch (_bsonReaderState) { case BsonReaderState.Normal: - return ReadNormal(); + success = ReadNormal(); + break; case BsonReaderState.ReferenceStart: case BsonReaderState.ReferenceRef: case BsonReaderState.ReferenceId: - return ReadReference(); + success = ReadReference(); + break; case BsonReaderState.CodeWScopeStart: case BsonReaderState.CodeWScopeCode: case BsonReaderState.CodeWScopeScope: case BsonReaderState.CodeWScopeScopeObject: case BsonReaderState.CodeWScopeScopeEnd: - return ReadCodeWScope(); + success = ReadCodeWScope(); + break; default: throw CreateReaderException(this, "Unexpected state: {0}".FormatWith(CultureInfo.InvariantCulture, _bsonReaderState)); } + + if (!success) + { + SetToken(JsonToken.None); + return false; + } + + return true; } catch (EndOfStreamException) { + SetToken(JsonToken.None); return false; } } diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index 556a7f87..fc598bb4 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -722,6 +722,8 @@ namespace Newtonsoft.Json /// The deserialized object from the JSON string. public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings) { + ValidationUtils.ArgumentNotNull(value, "value"); + StringReader sr = new StringReader(value); JsonSerializer jsonSerializer = JsonSerializer.Create(settings); diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index 64cacfd8..eb792c2f 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -327,7 +327,13 @@ namespace Newtonsoft.Json public override bool Read() { _readType = ReadType.Read; - return ReadInternal(); + if (!ReadInternal()) + { + SetToken(JsonToken.None); + return false; + } + + return true; } private bool IsWrappedInTypeObject() @@ -371,7 +377,10 @@ namespace Newtonsoft.Json do { if (!ReadInternal()) - throw CreateReaderException(this, "Unexpected end when reading bytes."); + { + SetToken(JsonToken.None); + return null; + } } while (TokenType == JsonToken.Comment); if (IsWrappedInTypeObject()) @@ -431,7 +440,10 @@ namespace Newtonsoft.Json do { if (!ReadInternal()) - throw CreateReaderException(this, "Unexpected end when reading decimal."); + { + SetToken(JsonToken.None); + return null; + } } while (TokenType == JsonToken.Comment); if (TokenType == JsonToken.Float) @@ -471,7 +483,10 @@ namespace Newtonsoft.Json do { if (!ReadInternal()) - throw CreateReaderException(this, "Unexpected end when reading integer."); + { + SetToken(JsonToken.None); + return null; + } } while (TokenType == JsonToken.Comment); if (TokenType == JsonToken.Integer) @@ -512,7 +527,10 @@ namespace Newtonsoft.Json do { if (!ReadInternal()) - throw CreateReaderException(this, "Unexpected end when reading date."); + { + SetToken(JsonToken.None); + return null; + } } while (TokenType == JsonToken.Comment); if (TokenType == JsonToken.Date) diff --git a/Src/Newtonsoft.Json/JsonValidatingReader.cs b/Src/Newtonsoft.Json/JsonValidatingReader.cs index fd5e5395..8c60fd80 100644 --- a/Src/Newtonsoft.Json/JsonValidatingReader.cs +++ b/Src/Newtonsoft.Json/JsonValidatingReader.cs @@ -504,6 +504,9 @@ namespace Newtonsoft.Json case JsonToken.Bytes: // these have no equivalent in JSON schema break; + case JsonToken.None: + // no content, do nothing + break; default: throw new ArgumentOutOfRangeException(); } diff --git a/Src/Newtonsoft.Json/Linq/JTokenReader.cs b/Src/Newtonsoft.Json/Linq/JTokenReader.cs index bb003418..0faf9b47 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenReader.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenReader.cs @@ -246,7 +246,7 @@ namespace Newtonsoft.Json.Linq private bool ReadToEnd() { - //CurrentState = State.Finished; + SetToken(JsonToken.None); return false; } diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 96a3d5dc..29575786 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -112,7 +112,12 @@ namespace Newtonsoft.Json.Serialization JsonConverter converter = GetConverter(contract, null); if (reader.TokenType == JsonToken.None && !ReadForType(reader, contract, converter != null, false)) + { + if (!contract.IsNullable) + throw new JsonSerializationException("No JSON content found and type '{0}' is not nullable.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); + return null; + } return CreateValueNonProperty(reader, objectType, contract, converter); } @@ -1114,21 +1119,23 @@ namespace Newtonsoft.Json.Serialization return true; case ReadType.ReadAsInt32: reader.ReadAsInt32(); - return true; + break; case ReadType.ReadAsDecimal: reader.ReadAsDecimal(); - return true; + break; case ReadType.ReadAsBytes: reader.ReadAsBytes(); - return true; + break; #if !NET20 case ReadType.ReadAsDateTimeOffset: reader.ReadAsDateTimeOffset(); - return true; + break; #endif default: throw new ArgumentOutOfRangeException(); } + + return (reader.TokenType != JsonToken.None); } private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, string id)