diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs index e29cd1d5..f2d51d0e 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs @@ -2194,6 +2194,54 @@ bye", reader.Value); Assert.AreEqual(JsonToken.EndArray, reader.TokenType); } + [Test] + public void SupportMultipleContent() + { + JsonTextReader reader = new JsonTextReader(new StringReader(@"1 2 ""name"" [][]null {}{} 1.1")); + reader.SupportMultipleContent = true; + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.String, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartArray, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndArray, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartArray, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndArray, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Null, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartObject, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndObject, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartObject, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndObject, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Float, reader.TokenType); + + Assert.IsFalse(reader.Read()); + } + [Test] public void ParseBooleanWithNoExtraContent() { diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index b5f6b015..77d3ab7d 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -7280,6 +7280,35 @@ Parameter name: value", } #endif + public class MultipleItemsClass + { + public string Name { get; set; } + } + + [Test] + public void MultipleItems() + { + IList values = new List(); + + JsonTextReader reader = new JsonTextReader(new StringReader(@"{ ""name"": ""bar"" }{ ""name"": ""baz"" }")); + reader.SupportMultipleContent = true; + + while (true) + { + if (!reader.Read()) + break; + + JsonSerializer serializer = new JsonSerializer(); + MultipleItemsClass foo = serializer.Deserialize(reader); + + values.Add(foo); + } + + Assert.AreEqual(2, values.Count); + Assert.AreEqual("bar", values[0].Name); + Assert.AreEqual("baz", values[1].Name); + } + private class FooBar { public DateTimeOffset Foo { get; set; } diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs index d5f29e93..0a951b50 100644 --- a/Src/Newtonsoft.Json/JsonReader.cs +++ b/Src/Newtonsoft.Json/JsonReader.cs @@ -147,6 +147,15 @@ namespace Newtonsoft.Json /// public bool CloseInput { get; set; } + /// + /// Gets or sets a value indicating whether multiple pieces of JSON content can + /// be read from a stream of content without erroring. + /// + /// + /// true to support reading multiple pieces of JSON content; otherwise false. The default is false. + /// + public bool SupportMultipleContent { get; set; } + /// /// Gets the quotation mark character used to enclose the value of a string. /// @@ -831,7 +840,10 @@ namespace Newtonsoft.Json case JsonToken.String: case JsonToken.Raw: case JsonToken.Bytes: - _currentState = (Peek() != JsonContainerType.None) ? State.PostValue : State.Finished; + if (Peek() != JsonContainerType.None) + _currentState = State.PostValue; + else + SetFinished(); UpdateScopeWithFinishedValue(); break; @@ -851,7 +863,10 @@ namespace Newtonsoft.Json if (GetTypeForCloseToken(endToken) != currentObject) throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, currentObject)); - _currentState = (Peek() != JsonContainerType.None) ? State.PostValue : State.Finished; + if (Peek() != JsonContainerType.None) + _currentState = State.PostValue; + else + SetFinished(); } /// @@ -873,13 +888,21 @@ namespace Newtonsoft.Json _currentState = State.Constructor; break; case JsonContainerType.None: - _currentState = State.Finished; + SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, currentObject)); } } + private void SetFinished() + { + if (SupportMultipleContent) + _currentState = State.Start; + else + _currentState = State.Finished; + } + internal static bool IsPrimitiveToken(JsonToken token) { switch (token)