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