diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs index ca55c877..fa2f6da7 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs @@ -572,5 +572,29 @@ namespace Newtonsoft.Json.Tests.Bson Assert.IsFalse(reader.Read()); } + + [Test] + public void ReadEmptyStrings() + { + string bson = "0C-00-00-00-02-00-01-00-00-00-00-00"; + + BsonReader reader = new BsonReader(new MemoryStream(MiscellaneousUtils.HexToBytes(bson))); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartObject, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); + Assert.AreEqual("", reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.String, reader.TokenType); + Assert.AreEqual("", reader.Value); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndObject, reader.TokenType); + + Assert.IsFalse(reader.Read()); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs index c9209566..83c7bfd0 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs @@ -216,5 +216,139 @@ namespace Newtonsoft.Json.Tests.Bson string bson = MiscellaneousUtils.BytesToHex(ms.ToArray()); Assert.AreEqual("4E-02-00-00-02-30-2D-31-2D-32-2D-33-2D-34-2D-35-2D-36-2D-37-2D-38-2D-39-2D-31-30-2D-31-31-2D-31-32-2D-31-33-2D-31-34-2D-31-35-2D-31-36-2D-31-37-2D-31-38-2D-31-39-2D-32-30-2D-32-31-2D-32-32-2D-32-33-2D-32-34-2D-32-35-2D-32-36-2D-32-37-2D-32-38-2D-32-39-2D-33-30-2D-33-31-2D-33-32-2D-33-33-2D-33-34-2D-33-35-2D-33-36-2D-33-37-2D-33-38-2D-33-39-2D-34-30-2D-34-31-2D-34-32-2D-34-33-2D-34-34-2D-34-35-2D-34-36-2D-34-37-2D-34-38-2D-34-39-2D-35-30-2D-35-31-2D-35-32-2D-35-33-2D-35-34-2D-35-35-2D-35-36-2D-35-37-2D-35-38-2D-35-39-2D-36-30-2D-36-31-2D-36-32-2D-36-33-2D-36-34-2D-36-35-2D-36-36-2D-36-37-2D-36-38-2D-36-39-2D-37-30-2D-37-31-2D-37-32-2D-37-33-2D-37-34-2D-37-35-2D-37-36-2D-37-37-2D-37-38-2D-37-39-2D-38-30-2D-38-31-2D-38-32-2D-38-33-2D-38-34-2D-38-35-2D-38-36-2D-38-37-2D-38-38-2D-38-39-2D-39-30-2D-39-31-2D-39-32-2D-39-33-2D-39-34-2D-39-35-2D-39-36-2D-39-37-2D-39-38-2D-39-39-00-22-01-00-00-30-2D-31-2D-32-2D-33-2D-34-2D-35-2D-36-2D-37-2D-38-2D-39-2D-31-30-2D-31-31-2D-31-32-2D-31-33-2D-31-34-2D-31-35-2D-31-36-2D-31-37-2D-31-38-2D-31-39-2D-32-30-2D-32-31-2D-32-32-2D-32-33-2D-32-34-2D-32-35-2D-32-36-2D-32-37-2D-32-38-2D-32-39-2D-33-30-2D-33-31-2D-33-32-2D-33-33-2D-33-34-2D-33-35-2D-33-36-2D-33-37-2D-33-38-2D-33-39-2D-34-30-2D-34-31-2D-34-32-2D-34-33-2D-34-34-2D-34-35-2D-34-36-2D-34-37-2D-34-38-2D-34-39-2D-35-30-2D-35-31-2D-35-32-2D-35-33-2D-35-34-2D-35-35-2D-35-36-2D-35-37-2D-35-38-2D-35-39-2D-36-30-2D-36-31-2D-36-32-2D-36-33-2D-36-34-2D-36-35-2D-36-36-2D-36-37-2D-36-38-2D-36-39-2D-37-30-2D-37-31-2D-37-32-2D-37-33-2D-37-34-2D-37-35-2D-37-36-2D-37-37-2D-37-38-2D-37-39-2D-38-30-2D-38-31-2D-38-32-2D-38-33-2D-38-34-2D-38-35-2D-38-36-2D-38-37-2D-38-38-2D-38-39-2D-39-30-2D-39-31-2D-39-32-2D-39-33-2D-39-34-2D-39-35-2D-39-36-2D-39-37-2D-39-38-2D-39-39-00-00", bson); } + + [Test] + public void SerializeGoogleGeoCode() + { + string json = @"{ + ""name"": ""1600 Amphitheatre Parkway, Mountain View, CA, USA"", + ""Status"": { + ""code"": 200, + ""request"": ""geocode"" + }, + ""Placemark"": [ + { + ""address"": ""1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA"", + ""AddressDetails"": { + ""Country"": { + ""CountryNameCode"": ""US"", + ""AdministrativeArea"": { + ""AdministrativeAreaName"": ""CA"", + ""SubAdministrativeArea"": { + ""SubAdministrativeAreaName"": ""Santa Clara"", + ""Locality"": { + ""LocalityName"": ""Mountain View"", + ""Thoroughfare"": { + ""ThoroughfareName"": ""1600 Amphitheatre Pkwy"" + }, + ""PostalCode"": { + ""PostalCodeNumber"": ""94043"" + } + } + } + } + }, + ""Accuracy"": 8 + }, + ""Point"": { + ""coordinates"": [-122.083739, 37.423021, 0] + } + } + ] +}"; + + GoogleMapGeocoderStructure jsonGoogleMapGeocoder = JsonConvert.DeserializeObject(json); + + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + JsonSerializer serializer = new JsonSerializer(); + serializer.Serialize(writer, jsonGoogleMapGeocoder); + + ms.Seek(0, SeekOrigin.Begin); + BsonReader reader = new BsonReader(ms); + GoogleMapGeocoderStructure bsonGoogleMapGeocoder = (GoogleMapGeocoderStructure)serializer.Deserialize(reader, typeof (GoogleMapGeocoderStructure)); + + Assert.IsNotNull(bsonGoogleMapGeocoder); + Assert.AreEqual("1600 Amphitheatre Parkway, Mountain View, CA, USA", bsonGoogleMapGeocoder.Name); + Assert.AreEqual("200", bsonGoogleMapGeocoder.Status.Code); + Assert.AreEqual("geocode", bsonGoogleMapGeocoder.Status.Request); + + IList placemarks = bsonGoogleMapGeocoder.Placemark; + Assert.IsNotNull(placemarks); + Assert.AreEqual(1, placemarks.Count); + + Placemark placemark = placemarks[0]; + Assert.AreEqual("1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA", placemark.Address); + Assert.AreEqual(8, placemark.AddressDetails.Accuracy); + Assert.AreEqual("US", placemark.AddressDetails.Country.CountryNameCode); + Assert.AreEqual("CA", placemark.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName); + Assert.AreEqual("Santa Clara", placemark.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.SubAdministrativeAreaName); + Assert.AreEqual("Mountain View", placemark.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName); + Assert.AreEqual("1600 Amphitheatre Pkwy", placemark.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.Thoroughfare.ThoroughfareName); + Assert.AreEqual("94043", placemark.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.PostalCode.PostalCodeNumber); + Assert.AreEqual(-122.083739m, placemark.Point.Coordinates[0]); + Assert.AreEqual(37.423021m, placemark.Point.Coordinates[1]); + Assert.AreEqual(0m, placemark.Point.Coordinates[2]); + } + + [Test] + public void WriteEmptyStrings() + { + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + writer.WriteStartObject(); + writer.WritePropertyName(""); + writer.WriteValue(""); + writer.WriteEndObject(); + + string bson = MiscellaneousUtils.BytesToHex(ms.ToArray()); + Assert.AreEqual("0C-00-00-00-02-00-01-00-00-00-00-00", bson); + } + + [Test] + [ExpectedException(typeof(JsonWriterException), ExpectedMessage = "Cannot write JSON comment as BSON.")] + public void WriteComment() + { + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + writer.WriteStartArray(); + writer.WriteComment("fail"); + } + + [Test] + [ExpectedException(typeof(JsonWriterException), ExpectedMessage = "Cannot write JSON constructor as BSON.")] + public void WriteConstructor() + { + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + writer.WriteStartArray(); + writer.WriteStartConstructor("fail"); + } + + [Test] + [ExpectedException(typeof(JsonWriterException), ExpectedMessage = "Cannot write raw JSON as BSON.")] + public void WriteRaw() + { + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + writer.WriteStartArray(); + writer.WriteRaw("fail"); + } + + [Test] + [ExpectedException(typeof(JsonWriterException), ExpectedMessage = "Cannot write raw JSON as BSON.")] + public void WriteRawValue() + { + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + writer.WriteStartArray(); + writer.WriteRawValue("fail"); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenWriterTest.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenWriterTest.cs index e8d55ff6..a6538c30 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenWriterTest.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenWriterTest.cs @@ -115,5 +115,53 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(WriteState.Start, jsonWriter.WriteState); } } + + [Test] + public void WriteComment() + { + JTokenWriter writer = new JTokenWriter(); + + writer.WriteStartArray(); + writer.WriteComment("fail"); + writer.WriteEndArray(); + + Assert.AreEqual(@"[ + /*fail*/]", writer.Token.ToString()); + } + + [Test] + public void WriteRaw() + { + JTokenWriter writer = new JTokenWriter(); + + writer.WriteStartArray(); + writer.WriteRaw("fail"); + writer.WriteRaw("fail"); + writer.WriteEndArray(); + + // this is a bug. write raw shouldn't be autocompleting like this + // hard to fix without introducing Raw and RawValue token types + // meh + Assert.AreEqual(@"[ + fail, + fail +]", writer.Token.ToString()); + } + + [Test] + public void WriteRawValue() + { + JTokenWriter writer = new JTokenWriter(); + + writer.WriteStartArray(); + writer.WriteRawValue("fail"); + writer.WriteRawValue("fail"); + writer.WriteEndArray(); + + Assert.AreEqual(@"[ + fail, + fail +]", writer.Token.ToString()); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Bson/BsonWriter.cs b/Src/Newtonsoft.Json/Bson/BsonWriter.cs index 507fea14..aa15cb18 100644 --- a/Src/Newtonsoft.Json/Bson/BsonWriter.cs +++ b/Src/Newtonsoft.Json/Bson/BsonWriter.cs @@ -117,7 +117,7 @@ namespace Newtonsoft.Json.Bson _writer.Write(data); break; default: - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException("Type", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); } } @@ -158,18 +158,13 @@ namespace Newtonsoft.Json.Bson case JTokenType.Bytes: return BsonType.Binary; default: - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException("Type", "Unexpected token when resolving JSON type to BSON type: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); } } private int CalculateSize(string s) { - int ret; - if (s != null) - ret = Encoding.UTF8.GetByteCount(s); - else - ret = 0; - return ret + 1; + return Encoding.UTF8.GetByteCount(s) + 1; } private int CalculateSizeWithLength(string s, bool includeSize) @@ -178,12 +173,9 @@ namespace Newtonsoft.Json.Bson ? 5 // size bytes + terminator : 1; // terminator - int ret; - if (s != null) - ret = Encoding.UTF8.GetByteCount(s); - else - ret = 0; - return baseSize + ret; + int byteCount = Encoding.UTF8.GetByteCount(s); + + return baseSize + byteCount; } private int CalculateSize(JToken t) @@ -214,16 +206,12 @@ namespace Newtonsoft.Json.Bson bases += 1; return bases; } - case JTokenType.Constructor: - throw new JsonWriterException("Cannot write JSON constructor as BSON."); case JTokenType.Property: JProperty property = (JProperty) t; int ss = 1; ss += CalculateSize(property.Name); ss += CalculateSize(property.Value); return ss; - case JTokenType.Comment: - throw new JsonWriterException("Cannot write JSON comment as BSON."); case JTokenType.Integer: return 4; case JTokenType.Float: @@ -239,13 +227,11 @@ namespace Newtonsoft.Json.Bson return 0; case JTokenType.Date: return 8; - case JTokenType.Raw: - throw new JsonWriterException("Cannot write raw JSON as BSON."); case JTokenType.Bytes: byte[] data = (byte[]) t; return 4 + 1 + data.Length; default: - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException("Type", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); } } @@ -262,5 +248,25 @@ namespace Newtonsoft.Json.Bson WriteToken(Token); } } + + public override void WriteComment(string text) + { + throw new JsonWriterException("Cannot write JSON comment as BSON."); + } + + public override void WriteStartConstructor(string name) + { + throw new JsonWriterException("Cannot write JSON constructor as BSON."); + } + + public override void WriteRaw(string json) + { + throw new JsonWriterException("Cannot write raw JSON as BSON."); + } + + public override void WriteRawValue(string json) + { + throw new JsonWriterException("Cannot write raw JSON as BSON."); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs index d9413a39..35f56be8 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs @@ -180,10 +180,15 @@ namespace Newtonsoft.Json.Linq public override void WriteRaw(string json) { base.WriteRaw(json); - // hack AddValue(JValue.CreateRaw(json), JsonToken.Raw); } + public override void WriteComment(string text) + { + base.WriteComment(text); + AddValue(JValue.CreateComment(text), JsonToken.Comment); + } + /// /// Writes a value. ///