1 #region License 2 // Copyright (c) 2007 James Newton-King 3 // 4 // Permission is hereby granted, free of charge, to any person 5 // obtaining a copy of this software and associated documentation 6 // files (the "Software"), to deal in the Software without 7 // restriction, including without limitation the rights to use, 8 // copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the 10 // Software is furnished to do so, subject to the following 11 // conditions: 12 // 13 // The above copyright notice and this permission notice shall be 14 // included in all copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 // OTHER DEALINGS IN THE SOFTWARE. 24 #endregion 25 26 using System; 27 using System.Collections.Generic; 28 using System.Globalization; 29 using System.IO; 30 using System.Text; 31 using System.Xml; 32 using Newtonsoft.Json.Linq; 33 #if DNXCORE50 34 using Xunit; 35 using Test = Xunit.FactAttribute; 36 using Assert = Newtonsoft.Json.Tests.XUnitAssert; 37 #else 38 using NUnit.Framework; 39 40 #endif 41 42 #if !(DNXCORE50 || NET20) 43 44 namespace Newtonsoft.Json.Tests.Documentation.Samples.Json 45 { 46 47 #region Types 48 public class XmlJsonReader : JsonReader 49 { 50 private readonly Stack<JTokenType> _stateStack; 51 private readonly XmlReader _reader; 52 53 private JTokenType? _valueType; 54 XmlJsonReader(XmlReader reader)55 public XmlJsonReader(XmlReader reader) 56 { 57 _reader = reader; 58 _stateStack = new Stack<JTokenType>(); 59 } 60 PeekState()61 private JTokenType PeekState() 62 { 63 JTokenType current = (_stateStack.Count > 0) ? _stateStack.Peek() : JTokenType.None; 64 return current; 65 } 66 Read()67 public override bool Read() 68 { 69 if (HandleValueType()) 70 { 71 return true; 72 } 73 74 while (_reader.Read()) 75 { 76 switch (_reader.NodeType) 77 { 78 case XmlNodeType.Element: 79 string typeName = _reader.GetAttribute("type"); 80 if (typeName == null) 81 { 82 throw new Exception("No type specified."); 83 } 84 85 _valueType = (JTokenType)Enum.Parse(typeof(JTokenType), typeName, true); 86 87 switch (PeekState()) 88 { 89 case JTokenType.None: 90 HandleValueType(); 91 return true; 92 case JTokenType.Object: 93 SetToken(JsonToken.PropertyName, _reader.LocalName); 94 _stateStack.Push(JTokenType.Property); 95 return true; 96 case JTokenType.Array: 97 case JTokenType.Constructor: 98 continue; 99 default: 100 throw new ArgumentOutOfRangeException(); 101 } 102 case XmlNodeType.EndElement: 103 switch (_stateStack.Peek()) 104 { 105 case JTokenType.Object: 106 SetToken(JsonToken.EndObject); 107 _stateStack.Pop(); 108 if (PeekState() == JTokenType.Property) 109 { 110 _stateStack.Pop(); 111 } 112 return true; 113 case JTokenType.Array: 114 SetToken(JsonToken.EndArray); 115 _stateStack.Pop(); 116 if (PeekState() == JTokenType.Property) 117 { 118 _stateStack.Pop(); 119 } 120 return true; 121 case JTokenType.Constructor: 122 SetToken(JsonToken.EndConstructor); 123 _stateStack.Pop(); 124 if (PeekState() == JTokenType.Property) 125 { 126 _stateStack.Pop(); 127 } 128 return true; 129 } 130 131 _stateStack.Pop(); 132 if (PeekState() == JTokenType.Property) 133 { 134 _stateStack.Pop(); 135 } 136 137 break; 138 case XmlNodeType.Text: 139 case XmlNodeType.CDATA: 140 switch (_valueType) 141 { 142 case JTokenType.Integer: 143 SetToken(JsonToken.Integer, Convert.ToInt64(_reader.Value, CultureInfo.InvariantCulture)); 144 break; 145 case JTokenType.Float: 146 SetToken(JsonToken.Float, Convert.ToDouble(_reader.Value, CultureInfo.InvariantCulture)); 147 break; 148 case JTokenType.String: 149 case JTokenType.Uri: 150 case JTokenType.TimeSpan: 151 case JTokenType.Guid: 152 SetToken(JsonToken.String, _reader.Value); 153 break; 154 case JTokenType.Boolean: 155 SetToken(JsonToken.Boolean, Convert.ToBoolean(_reader.Value, CultureInfo.InvariantCulture)); 156 break; 157 case JTokenType.Date: 158 SetToken(JsonToken.Date, Convert.ToDateTime(_reader.Value, CultureInfo.InvariantCulture)); 159 break; 160 case JTokenType.Bytes: 161 SetToken(JsonToken.Bytes, Convert.FromBase64String(_reader.Value)); 162 break; 163 default: 164 throw new ArgumentOutOfRangeException(); 165 } 166 _stateStack.Push(_valueType.Value); 167 return true; 168 default: 169 throw new ArgumentOutOfRangeException(); 170 } 171 } 172 173 return false; 174 } 175 HandleValueType()176 private bool HandleValueType() 177 { 178 switch (_valueType) 179 { 180 case JTokenType.Null: 181 SetToken(JsonToken.Null); 182 _valueType = null; 183 184 if (PeekState() == JTokenType.Property) 185 { 186 _stateStack.Pop(); 187 } 188 return true; 189 case JTokenType.Object: 190 SetToken(JsonToken.StartObject); 191 _stateStack.Push(JTokenType.Object); 192 _valueType = null; 193 return true; 194 case JTokenType.Array: 195 SetToken(JsonToken.StartArray); 196 _stateStack.Push(JTokenType.Array); 197 _valueType = null; 198 return true; 199 case JTokenType.Constructor: 200 string constructorName = _reader.GetAttribute("name"); 201 if (constructorName == null) 202 { 203 throw new Exception("No constructor name specified."); 204 } 205 206 SetToken(JsonToken.StartConstructor, constructorName); 207 _stateStack.Push(JTokenType.Constructor); 208 _valueType = null; 209 return true; 210 } 211 return false; 212 } 213 ReadAsInt32()214 public override int? ReadAsInt32() 215 { 216 if (!Read()) 217 { 218 return null; 219 } 220 221 return (Value != null) ? (int?)Convert.ToInt32(Value) : null; 222 } 223 ReadAsString()224 public override string ReadAsString() 225 { 226 if (!Read()) 227 { 228 return null; 229 } 230 231 return (string)Value; 232 } 233 ReadAsBytes()234 public override byte[] ReadAsBytes() 235 { 236 if (!Read()) 237 { 238 return null; 239 } 240 241 return (byte[])Value; 242 } 243 ReadAsDecimal()244 public override decimal? ReadAsDecimal() 245 { 246 if (!Read()) 247 { 248 return null; 249 } 250 251 return (Value != null) ? (decimal?)Convert.ToDecimal(Value) : null; 252 } 253 ReadAsDateTime()254 public override DateTime? ReadAsDateTime() 255 { 256 if (!Read()) 257 { 258 return null; 259 } 260 261 return (Value != null) ? (DateTime?)Convert.ToDateTime(Value) : null; 262 } 263 ReadAsDateTimeOffset()264 public override DateTimeOffset? ReadAsDateTimeOffset() 265 { 266 if (!Read()) 267 { 268 return null; 269 } 270 271 return (Value != null) ? (DateTimeOffset?)Convert.ToDateTime(Value) : null; 272 } 273 } 274 #endregion 275 276 [TestFixture] 277 public class CustomJsonReader : TestFixtureBase 278 { 279 [Test] Example()280 public void Example() 281 { 282 #region Usage 283 string xml = @"<Root type=""Object""> 284 <Null type=""Null"" /> 285 <String type=""String"">This is a string!</String> 286 <Char type=""String"">!</Char> 287 <Integer type=""Integer"">123</Integer> 288 <DateTime type=""Date"">2001-02-22T20:59:59Z</DateTime> 289 <DateTimeOffset type=""Date"">2001-02-22T20:59:59+12:00</DateTimeOffset> 290 <Float type=""Float"">1.1</Float> 291 <Double type=""Float"">3.14</Double> 292 <Decimal type=""Float"">19.95</Decimal> 293 <Guid type=""Guid"">d66eab59-3715-4b35-9e06-fa61c1216eaa</Guid> 294 <Uri type=""Uri"">http://james.newtonking.com</Uri> 295 <Array type=""Array""> 296 <Item type=""Integer"">1</Item> 297 <Item type=""Bytes"">SGVsbG8gd29ybGQh</Item> 298 <Item type=""Boolean"">True</Item> 299 </Array> 300 <Object type=""Object""> 301 <String type=""String"">This is a string!</String> 302 <Null type=""Null"" /> 303 </Object> 304 <Constructor type=""Constructor"" name=""Date""> 305 <Item type=""Integer"">2000</Item> 306 <Item type=""Integer"">12</Item> 307 <Item type=""Integer"">30</Item> 308 </Constructor> 309 </Root>"; 310 311 StringReader sr = new StringReader(xml); 312 313 using (XmlReader xmlReader = XmlReader.Create(sr, new XmlReaderSettings { IgnoreWhitespace = true })) 314 using (XmlJsonReader reader = new XmlJsonReader(xmlReader)) 315 { 316 JObject o = JObject.Load(reader); 317 //{ 318 // "Null": null, 319 // "String": "This is a string!", 320 // "Char": "!", 321 // "Integer": 123, 322 // "DateTime": "2001-02-23T09:59:59+13:00", 323 // "DateTimeOffset": "2001-02-22T21:59:59+13:00", 324 // "Float": 1.1, 325 // "Double": 3.14, 326 // "Decimal": 19.95, 327 // "Guid": "d66eab59-3715-4b35-9e06-fa61c1216eaa", 328 // "Uri": "http://james.newtonking.com", 329 // "Array": [ 330 // 1, 331 // "SGVsbG8gd29ybGQh", 332 // true 333 // ], 334 // "Object": { 335 // "String": "This is a string!", 336 // "Null": null 337 // }, 338 // "Constructor": new Date(2000, 12, 30) 339 //} 340 } 341 #endregion 342 343 using (XmlReader xmlReader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { IgnoreWhitespace = true })) 344 using (XmlJsonReader reader = new XmlJsonReader(xmlReader)) 345 { 346 Assert.IsTrue(reader.Read()); 347 Assert.AreEqual(JsonToken.StartObject, reader.TokenType); 348 349 Assert.IsTrue(reader.Read()); 350 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 351 Assert.AreEqual("Null", reader.Value); 352 353 Assert.IsTrue(reader.Read()); 354 Assert.AreEqual(JsonToken.Null, reader.TokenType); 355 356 Assert.IsTrue(reader.Read()); 357 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 358 Assert.AreEqual("String", reader.Value); 359 360 Assert.IsTrue(reader.Read()); 361 Assert.AreEqual(JsonToken.String, reader.TokenType); 362 Assert.AreEqual("This is a string!", reader.Value); 363 364 Assert.IsTrue(reader.Read()); 365 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 366 Assert.AreEqual("Char", reader.Value); 367 368 Assert.IsTrue(reader.Read()); 369 Assert.AreEqual(JsonToken.String, reader.TokenType); 370 Assert.AreEqual("!", reader.Value); 371 372 Assert.IsTrue(reader.Read()); 373 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 374 Assert.AreEqual("Integer", reader.Value); 375 376 Assert.IsTrue(reader.Read()); 377 Assert.AreEqual(JsonToken.Integer, reader.TokenType); 378 Assert.AreEqual(123, reader.Value); 379 380 Assert.IsTrue(reader.Read()); 381 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 382 Assert.AreEqual("DateTime", reader.Value); 383 384 Assert.IsTrue(reader.Read()); 385 Assert.AreEqual(JsonToken.Date, reader.TokenType); 386 Assert.AreEqual(DateTime.Parse("2001-02-22T20:59:59Z"), reader.Value); 387 388 Assert.IsTrue(reader.Read()); 389 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 390 Assert.AreEqual("DateTimeOffset", reader.Value); 391 392 Assert.IsTrue(reader.Read()); 393 Assert.AreEqual(JsonToken.Date, reader.TokenType); 394 Assert.AreEqual(DateTime.Parse("2001-02-22T20:59:59+12:00"), reader.Value); 395 396 Assert.IsTrue(reader.Read()); 397 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 398 Assert.AreEqual("Float", reader.Value); 399 400 Assert.IsTrue(reader.Read()); 401 Assert.AreEqual(JsonToken.Float, reader.TokenType); 402 Assert.AreEqual(1.1d, reader.Value); 403 404 Assert.IsTrue(reader.Read()); 405 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 406 Assert.AreEqual("Double", reader.Value); 407 408 Assert.IsTrue(reader.Read()); 409 Assert.AreEqual(JsonToken.Float, reader.TokenType); 410 Assert.AreEqual(3.14d, reader.Value); 411 412 Assert.IsTrue(reader.Read()); 413 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 414 Assert.AreEqual("Decimal", reader.Value); 415 416 Assert.IsTrue(reader.Read()); 417 Assert.AreEqual(JsonToken.Float, reader.TokenType); 418 Assert.AreEqual(19.95d, reader.Value); 419 420 Assert.IsTrue(reader.Read()); 421 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 422 Assert.AreEqual("Guid", reader.Value); 423 424 Assert.IsTrue(reader.Read()); 425 Assert.AreEqual(JsonToken.String, reader.TokenType); 426 Assert.AreEqual("d66eab59-3715-4b35-9e06-fa61c1216eaa", reader.Value); 427 428 Assert.IsTrue(reader.Read()); 429 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 430 Assert.AreEqual("Uri", reader.Value); 431 432 Assert.IsTrue(reader.Read()); 433 Assert.AreEqual(JsonToken.String, reader.TokenType); 434 Assert.AreEqual("http://james.newtonking.com", reader.Value); 435 436 Assert.IsTrue(reader.Read()); 437 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 438 Assert.AreEqual("Array", reader.Value); 439 440 Assert.IsTrue(reader.Read()); 441 Assert.AreEqual(JsonToken.StartArray, reader.TokenType); 442 443 Assert.AreEqual(1, reader.ReadAsInt32()); 444 Assert.AreEqual(JsonToken.Integer, reader.TokenType); 445 Assert.AreEqual(1, reader.Value); 446 447 Assert.IsTrue(reader.Read()); 448 Assert.AreEqual(JsonToken.Bytes, reader.TokenType); 449 Assert.AreEqual(Encoding.UTF8.GetBytes("Hello world!"), reader.Value); 450 451 Assert.IsTrue(reader.Read()); 452 Assert.AreEqual(JsonToken.Boolean, reader.TokenType); 453 Assert.AreEqual(true, reader.Value); 454 455 Assert.IsTrue(reader.Read()); 456 Assert.AreEqual(JsonToken.EndArray, reader.TokenType); 457 458 Assert.IsTrue(reader.Read()); 459 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 460 Assert.AreEqual("Object", reader.Value); 461 462 Assert.IsTrue(reader.Read()); 463 Assert.AreEqual(JsonToken.StartObject, reader.TokenType); 464 465 Assert.IsTrue(reader.Read()); 466 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 467 Assert.AreEqual("String", reader.Value); 468 469 Assert.AreEqual("This is a string!", reader.ReadAsString()); 470 Assert.AreEqual(JsonToken.String, reader.TokenType); 471 Assert.AreEqual("This is a string!", reader.Value); 472 473 Assert.IsTrue(reader.Read()); 474 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 475 Assert.AreEqual("Null", reader.Value); 476 477 Assert.IsTrue(reader.Read()); 478 Assert.AreEqual(JsonToken.Null, reader.TokenType); 479 480 Assert.IsTrue(reader.Read()); 481 Assert.AreEqual(JsonToken.EndObject, reader.TokenType); 482 483 Assert.IsTrue(reader.Read()); 484 Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); 485 Assert.AreEqual("Constructor", reader.Value); 486 487 Assert.IsTrue(reader.Read()); 488 Assert.AreEqual(JsonToken.StartConstructor, reader.TokenType); 489 Assert.AreEqual("Date", reader.Value); 490 491 Assert.IsTrue(reader.Read()); 492 Assert.AreEqual(JsonToken.Integer, reader.TokenType); 493 Assert.AreEqual(2000, reader.Value); 494 495 Assert.IsTrue(reader.Read()); 496 Assert.AreEqual(JsonToken.Integer, reader.TokenType); 497 Assert.AreEqual(12, reader.Value); 498 499 Assert.IsTrue(reader.Read()); 500 Assert.AreEqual(JsonToken.Integer, reader.TokenType); 501 Assert.AreEqual(30, reader.Value); 502 503 Assert.IsTrue(reader.Read()); 504 Assert.AreEqual(JsonToken.EndConstructor, reader.TokenType); 505 506 Assert.IsTrue(reader.Read()); 507 Assert.AreEqual(JsonToken.EndObject, reader.TokenType); 508 509 Assert.IsFalse(reader.Read()); 510 } 511 } 512 } 513 } 514 515 #endif