diff --git a/Libs/EpicMorg.Net.AWC.dll b/Libs/EpicMorg.Net.AWC.dll
deleted file mode 100644
index 72a4bd4..0000000
Binary files a/Libs/EpicMorg.Net.AWC.dll and /dev/null differ
diff --git a/Libs/JsonNet/Bson/BsonBinaryType.cs b/Libs/JsonNet/Bson/BsonBinaryType.cs
new file mode 100644
index 0000000..638039f
--- /dev/null
+++ b/Libs/JsonNet/Bson/BsonBinaryType.cs
@@ -0,0 +1,44 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Bson
+{
+ internal enum BsonBinaryType : byte
+ {
+ Binary = 0x00,
+ Function = 0x01,
+
+ [Obsolete("This type has been deprecated in the BSON specification. Use Binary instead.")]
+ BinaryOld = 0x02,
+
+ [Obsolete("This type has been deprecated in the BSON specification. Use Uuid instead.")]
+ UuidOld = 0x03,
+ Uuid = 0x04,
+ Md5 = 0x05,
+ UserDefined = 0x80
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Bson/BsonBinaryWriter.cs b/Libs/JsonNet/Bson/BsonBinaryWriter.cs
new file mode 100644
index 0000000..b0f4026
--- /dev/null
+++ b/Libs/JsonNet/Bson/BsonBinaryWriter.cs
@@ -0,0 +1,325 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Bson
+{
+ internal class BsonBinaryWriter
+ {
+ private static readonly Encoding Encoding = new UTF8Encoding(false);
+
+ private readonly BinaryWriter _writer;
+
+ private byte[] _largeByteBuffer;
+
+ public DateTimeKind DateTimeKindHandling { get; set; }
+
+ public BsonBinaryWriter(BinaryWriter writer)
+ {
+ DateTimeKindHandling = DateTimeKind.Utc;
+ _writer = writer;
+ }
+
+ public void Flush()
+ {
+ _writer.Flush();
+ }
+
+ public void Close()
+ {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ _writer.Close();
+#else
+ _writer.Dispose();
+#endif
+ }
+
+ public void WriteToken(BsonToken t)
+ {
+ CalculateSize(t);
+ WriteTokenInternal(t);
+ }
+
+ private void WriteTokenInternal(BsonToken t)
+ {
+ switch (t.Type)
+ {
+ case BsonType.Object:
+ {
+ BsonObject value = (BsonObject)t;
+ _writer.Write(value.CalculatedSize);
+ foreach (BsonProperty property in value)
+ {
+ _writer.Write((sbyte)property.Value.Type);
+ WriteString((string)property.Name.Value, property.Name.ByteCount, null);
+ WriteTokenInternal(property.Value);
+ }
+ _writer.Write((byte)0);
+ }
+ break;
+ case BsonType.Array:
+ {
+ BsonArray value = (BsonArray)t;
+ _writer.Write(value.CalculatedSize);
+ ulong index = 0;
+ foreach (BsonToken c in value)
+ {
+ _writer.Write((sbyte)c.Type);
+ WriteString(index.ToString(CultureInfo.InvariantCulture), MathUtils.IntLength(index), null);
+ WriteTokenInternal(c);
+ index++;
+ }
+ _writer.Write((byte)0);
+ }
+ break;
+ case BsonType.Integer:
+ {
+ BsonValue value = (BsonValue)t;
+ _writer.Write(Convert.ToInt32(value.Value, CultureInfo.InvariantCulture));
+ }
+ break;
+ case BsonType.Long:
+ {
+ BsonValue value = (BsonValue)t;
+ _writer.Write(Convert.ToInt64(value.Value, CultureInfo.InvariantCulture));
+ }
+ break;
+ case BsonType.Number:
+ {
+ BsonValue value = (BsonValue)t;
+ _writer.Write(Convert.ToDouble(value.Value, CultureInfo.InvariantCulture));
+ }
+ break;
+ case BsonType.String:
+ {
+ BsonString value = (BsonString)t;
+ WriteString((string)value.Value, value.ByteCount, value.CalculatedSize - 4);
+ }
+ break;
+ case BsonType.Boolean:
+ {
+ BsonValue value = (BsonValue)t;
+ _writer.Write((bool)value.Value);
+ }
+ break;
+ case BsonType.Null:
+ case BsonType.Undefined:
+ break;
+ case BsonType.Date:
+ {
+ BsonValue value = (BsonValue)t;
+
+ long ticks = 0;
+
+ if (value.Value is DateTime)
+ {
+ DateTime dateTime = (DateTime)value.Value;
+ if (DateTimeKindHandling == DateTimeKind.Utc)
+ dateTime = dateTime.ToUniversalTime();
+ else if (DateTimeKindHandling == DateTimeKind.Local)
+ dateTime = dateTime.ToLocalTime();
+
+ ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTime, false);
+ }
+#if !NET20
+ else
+ {
+ DateTimeOffset dateTimeOffset = (DateTimeOffset)value.Value;
+ ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTimeOffset.UtcDateTime, dateTimeOffset.Offset);
+ }
+#endif
+
+ _writer.Write(ticks);
+ }
+ break;
+ case BsonType.Binary:
+ {
+ BsonBinary value = (BsonBinary)t;
+
+ byte[] data = (byte[])value.Value;
+ _writer.Write(data.Length);
+ _writer.Write((byte)value.BinaryType);
+ _writer.Write(data);
+ }
+ break;
+ case BsonType.Oid:
+ {
+ BsonValue value = (BsonValue)t;
+
+ byte[] data = (byte[])value.Value;
+ _writer.Write(data);
+ }
+ break;
+ case BsonType.Regex:
+ {
+ BsonRegex value = (BsonRegex)t;
+
+ WriteString((string)value.Pattern.Value, value.Pattern.ByteCount, null);
+ WriteString((string)value.Options.Value, value.Options.ByteCount, null);
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("t", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type));
+ }
+ }
+
+ private void WriteString(string s, int byteCount, int? calculatedlengthPrefix)
+ {
+ if (calculatedlengthPrefix != null)
+ _writer.Write(calculatedlengthPrefix.Value);
+
+ WriteUtf8Bytes(s, byteCount);
+
+ _writer.Write((byte)0);
+ }
+
+ public void WriteUtf8Bytes(string s, int byteCount)
+ {
+ if (s != null)
+ {
+ if (_largeByteBuffer == null)
+ {
+ _largeByteBuffer = new byte[256];
+ }
+ if (byteCount <= 256)
+ {
+ Encoding.GetBytes(s, 0, s.Length, _largeByteBuffer, 0);
+ _writer.Write(_largeByteBuffer, 0, byteCount);
+ }
+ else
+ {
+ byte[] bytes = Encoding.GetBytes(s);
+ _writer.Write(bytes);
+ }
+ }
+ }
+
+ private int CalculateSize(int stringByteCount)
+ {
+ return stringByteCount + 1;
+ }
+
+ private int CalculateSizeWithLength(int stringByteCount, bool includeSize)
+ {
+ int baseSize = (includeSize)
+ ? 5 // size bytes + terminator
+ : 1; // terminator
+
+ return baseSize + stringByteCount;
+ }
+
+ private int CalculateSize(BsonToken t)
+ {
+ switch (t.Type)
+ {
+ case BsonType.Object:
+ {
+ BsonObject value = (BsonObject)t;
+
+ int bases = 4;
+ foreach (BsonProperty p in value)
+ {
+ int size = 1;
+ size += CalculateSize(p.Name);
+ size += CalculateSize(p.Value);
+
+ bases += size;
+ }
+ bases += 1;
+ value.CalculatedSize = bases;
+ return bases;
+ }
+ case BsonType.Array:
+ {
+ BsonArray value = (BsonArray)t;
+
+ int size = 4;
+ ulong index = 0;
+ foreach (BsonToken c in value)
+ {
+ size += 1;
+ size += CalculateSize(MathUtils.IntLength(index));
+ size += CalculateSize(c);
+ index++;
+ }
+ size += 1;
+ value.CalculatedSize = size;
+
+ return value.CalculatedSize;
+ }
+ case BsonType.Integer:
+ return 4;
+ case BsonType.Long:
+ return 8;
+ case BsonType.Number:
+ return 8;
+ case BsonType.String:
+ {
+ BsonString value = (BsonString)t;
+ string s = (string)value.Value;
+ value.ByteCount = (s != null) ? Encoding.GetByteCount(s) : 0;
+ value.CalculatedSize = CalculateSizeWithLength(value.ByteCount, value.IncludeLength);
+
+ return value.CalculatedSize;
+ }
+ case BsonType.Boolean:
+ return 1;
+ case BsonType.Null:
+ case BsonType.Undefined:
+ return 0;
+ case BsonType.Date:
+ return 8;
+ case BsonType.Binary:
+ {
+ BsonBinary value = (BsonBinary)t;
+
+ byte[] data = (byte[])value.Value;
+ value.CalculatedSize = 4 + 1 + data.Length;
+
+ return value.CalculatedSize;
+ }
+ case BsonType.Oid:
+ return 12;
+ case BsonType.Regex:
+ {
+ BsonRegex value = (BsonRegex)t;
+ int size = 0;
+ size += CalculateSize(value.Pattern);
+ size += CalculateSize(value.Options);
+ value.CalculatedSize = size;
+
+ return value.CalculatedSize;
+ }
+ default:
+ throw new ArgumentOutOfRangeException("t", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Bson/BsonObjectId.cs b/Libs/JsonNet/Bson/BsonObjectId.cs
new file mode 100644
index 0000000..399e5f4
--- /dev/null
+++ b/Libs/JsonNet/Bson/BsonObjectId.cs
@@ -0,0 +1,55 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Bson
+{
+ ///
+ /// Represents a BSON Oid (object id).
+ ///
+ public class BsonObjectId
+ {
+ ///
+ /// Gets or sets the value of the Oid.
+ ///
+ /// The value of the Oid.
+ public byte[] Value { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Oid value.
+ public BsonObjectId(byte[] value)
+ {
+ ValidationUtils.ArgumentNotNull(value, "value");
+ if (value.Length != 12)
+ throw new ArgumentException("An ObjectId must be 12 bytes", "value");
+
+ Value = value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Bson/BsonReader.cs b/Libs/JsonNet/Bson/BsonReader.cs
new file mode 100644
index 0000000..ccd5662
--- /dev/null
+++ b/Libs/JsonNet/Bson/BsonReader.cs
@@ -0,0 +1,856 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.IO;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Linq;
+
+namespace Newtonsoft.Json.Bson
+{
+ ///
+ /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
+ ///
+ public class BsonReader : JsonReader
+ {
+ private const int MaxCharBytesSize = 128;
+ private static readonly byte[] SeqRange1 = new byte[] { 0, 127 }; // range of 1-byte sequence
+ private static readonly byte[] SeqRange2 = new byte[] { 194, 223 }; // range of 2-byte sequence
+ private static readonly byte[] SeqRange3 = new byte[] { 224, 239 }; // range of 3-byte sequence
+ private static readonly byte[] SeqRange4 = new byte[] { 240, 244 }; // range of 4-byte sequence
+
+ private readonly BinaryReader _reader;
+ private readonly List _stack;
+
+ private byte[] _byteBuffer;
+ private char[] _charBuffer;
+
+ private BsonType _currentElementType;
+ private BsonReaderState _bsonReaderState;
+ private ContainerContext _currentContext;
+
+ private bool _readRootValueAsArray;
+ private bool _jsonNet35BinaryCompatibility;
+ private DateTimeKind _dateTimeKindHandling;
+
+ private enum BsonReaderState
+ {
+ Normal,
+ ReferenceStart,
+ ReferenceRef,
+ ReferenceId,
+ CodeWScopeStart,
+ CodeWScopeCode,
+ CodeWScopeScope,
+ CodeWScopeScopeObject,
+ CodeWScopeScopeEnd
+ }
+
+ private class ContainerContext
+ {
+ public readonly BsonType Type;
+ public int Length;
+ public int Position;
+
+ public ContainerContext(BsonType type)
+ {
+ Type = type;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether binary data reading should compatible with incorrect Json.NET 3.5 written binary.
+ ///
+ ///
+ /// true if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, false .
+ ///
+ [Obsolete("JsonNet35BinaryCompatibility will be removed in a future version of Json.NET.")]
+ public bool JsonNet35BinaryCompatibility
+ {
+ get { return _jsonNet35BinaryCompatibility; }
+ set { _jsonNet35BinaryCompatibility = value; }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the root object will be read as a JSON array.
+ ///
+ ///
+ /// true if the root object will be read as a JSON array; otherwise, false .
+ ///
+ public bool ReadRootValueAsArray
+ {
+ get { return _readRootValueAsArray; }
+ set { _readRootValueAsArray = value; }
+ }
+
+ ///
+ /// Gets or sets the used when reading values from BSON.
+ ///
+ /// The used when reading values from BSON.
+ public DateTimeKind DateTimeKindHandling
+ {
+ get { return _dateTimeKindHandling; }
+ set { _dateTimeKindHandling = value; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ public BsonReader(Stream stream)
+ : this(stream, false, DateTimeKind.Local)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The reader.
+ public BsonReader(BinaryReader reader)
+ : this(reader, false, DateTimeKind.Local)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// if set to true the root object will be read as a JSON array.
+ /// The used when reading values from BSON.
+ public BsonReader(Stream stream, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling)
+ {
+ ValidationUtils.ArgumentNotNull(stream, "stream");
+ _reader = new BinaryReader(stream);
+ _stack = new List();
+ _readRootValueAsArray = readRootValueAsArray;
+ _dateTimeKindHandling = dateTimeKindHandling;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The reader.
+ /// if set to true the root object will be read as a JSON array.
+ /// The used when reading values from BSON.
+ public BsonReader(BinaryReader reader, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling)
+ {
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+ _reader = reader;
+ _stack = new List();
+ _readRootValueAsArray = readRootValueAsArray;
+ _dateTimeKindHandling = dateTimeKindHandling;
+ }
+
+ private string ReadElement()
+ {
+ _currentElementType = ReadType();
+ string elementName = ReadString();
+ return elementName;
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a [].
+ ///
+ ///
+ /// A [] or a null reference if the next JSON token is null. This method will return null at the end of an array.
+ ///
+ public override byte[] ReadAsBytes()
+ {
+ return ReadAsBytesInternal();
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override decimal? ReadAsDecimal()
+ {
+ return ReadAsDecimalInternal();
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override int? ReadAsInt32()
+ {
+ return ReadAsInt32Internal();
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override string ReadAsString()
+ {
+ return ReadAsStringInternal();
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override DateTime? ReadAsDateTime()
+ {
+ return ReadAsDateTimeInternal();
+ }
+
+#if !NET20
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ ///
+ /// A . This method will return null at the end of an array.
+ ///
+ public override DateTimeOffset? ReadAsDateTimeOffset()
+ {
+ return ReadAsDateTimeOffsetInternal();
+ }
+#endif
+
+ ///
+ /// Reads the next JSON token from the stream.
+ ///
+ ///
+ /// true if the next token was read successfully; false if there are no more tokens to read.
+ ///
+ public override bool Read()
+ {
+ _readType = Json.ReadType.Read;
+
+ return ReadInternal();
+ }
+
+ internal override bool ReadInternal()
+ {
+ try
+ {
+ bool success;
+
+ switch (_bsonReaderState)
+ {
+ case BsonReaderState.Normal:
+ success = ReadNormal();
+ break;
+ case BsonReaderState.ReferenceStart:
+ case BsonReaderState.ReferenceRef:
+ case BsonReaderState.ReferenceId:
+ success = ReadReference();
+ break;
+ case BsonReaderState.CodeWScopeStart:
+ case BsonReaderState.CodeWScopeCode:
+ case BsonReaderState.CodeWScopeScope:
+ case BsonReaderState.CodeWScopeScopeObject:
+ case BsonReaderState.CodeWScopeScopeEnd:
+ success = ReadCodeWScope();
+ break;
+ default:
+ throw JsonReaderException.Create(this, "Unexpected state: {0}".FormatWith(CultureInfo.InvariantCulture, _bsonReaderState));
+ }
+
+ if (!success)
+ {
+ SetToken(JsonToken.None);
+ return false;
+ }
+
+ return true;
+ }
+ catch (EndOfStreamException)
+ {
+ SetToken(JsonToken.None);
+ return false;
+ }
+ }
+
+ ///
+ /// Changes the to Closed.
+ ///
+ public override void Close()
+ {
+ base.Close();
+
+ if (CloseInput && _reader != null)
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ _reader.Close();
+#else
+ _reader.Dispose();
+#endif
+ }
+
+ private bool ReadCodeWScope()
+ {
+ switch (_bsonReaderState)
+ {
+ case BsonReaderState.CodeWScopeStart:
+ SetToken(JsonToken.PropertyName, "$code");
+ _bsonReaderState = BsonReaderState.CodeWScopeCode;
+ return true;
+ case BsonReaderState.CodeWScopeCode:
+ // total CodeWScope size - not used
+ ReadInt32();
+
+ SetToken(JsonToken.String, ReadLengthString());
+ _bsonReaderState = BsonReaderState.CodeWScopeScope;
+ return true;
+ case BsonReaderState.CodeWScopeScope:
+ if (CurrentState == State.PostValue)
+ {
+ SetToken(JsonToken.PropertyName, "$scope");
+ return true;
+ }
+ else
+ {
+ SetToken(JsonToken.StartObject);
+ _bsonReaderState = BsonReaderState.CodeWScopeScopeObject;
+
+ ContainerContext newContext = new ContainerContext(BsonType.Object);
+ PushContext(newContext);
+ newContext.Length = ReadInt32();
+
+ return true;
+ }
+ case BsonReaderState.CodeWScopeScopeObject:
+ bool result = ReadNormal();
+ if (result && TokenType == JsonToken.EndObject)
+ _bsonReaderState = BsonReaderState.CodeWScopeScopeEnd;
+
+ return result;
+ case BsonReaderState.CodeWScopeScopeEnd:
+ SetToken(JsonToken.EndObject);
+ _bsonReaderState = BsonReaderState.Normal;
+ return true;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ private bool ReadReference()
+ {
+ switch (CurrentState)
+ {
+ case State.ObjectStart:
+ {
+ SetToken(JsonToken.PropertyName, JsonTypeReflector.RefPropertyName);
+ _bsonReaderState = BsonReaderState.ReferenceRef;
+ return true;
+ }
+ case State.Property:
+ {
+ if (_bsonReaderState == BsonReaderState.ReferenceRef)
+ {
+ SetToken(JsonToken.String, ReadLengthString());
+ return true;
+ }
+ else if (_bsonReaderState == BsonReaderState.ReferenceId)
+ {
+ SetToken(JsonToken.Bytes, ReadBytes(12));
+ return true;
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState);
+ }
+ }
+ case State.PostValue:
+ {
+ if (_bsonReaderState == BsonReaderState.ReferenceRef)
+ {
+ SetToken(JsonToken.PropertyName, JsonTypeReflector.IdPropertyName);
+ _bsonReaderState = BsonReaderState.ReferenceId;
+ return true;
+ }
+ else if (_bsonReaderState == BsonReaderState.ReferenceId)
+ {
+ SetToken(JsonToken.EndObject);
+ _bsonReaderState = BsonReaderState.Normal;
+ return true;
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState);
+ }
+ }
+ default:
+ throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + CurrentState);
+ }
+ }
+
+ private bool ReadNormal()
+ {
+ switch (CurrentState)
+ {
+ case State.Start:
+ {
+ JsonToken token = (!_readRootValueAsArray) ? JsonToken.StartObject : JsonToken.StartArray;
+ BsonType type = (!_readRootValueAsArray) ? BsonType.Object : BsonType.Array;
+
+ SetToken(token);
+ ContainerContext newContext = new ContainerContext(type);
+ PushContext(newContext);
+ newContext.Length = ReadInt32();
+ return true;
+ }
+ case State.Complete:
+ case State.Closed:
+ return false;
+ case State.Property:
+ {
+ ReadType(_currentElementType);
+ return true;
+ }
+ case State.ObjectStart:
+ case State.ArrayStart:
+ case State.PostValue:
+ ContainerContext context = _currentContext;
+ if (context == null)
+ return false;
+
+ int lengthMinusEnd = context.Length - 1;
+
+ if (context.Position < lengthMinusEnd)
+ {
+ if (context.Type == BsonType.Array)
+ {
+ ReadElement();
+ ReadType(_currentElementType);
+ return true;
+ }
+ else
+ {
+ SetToken(JsonToken.PropertyName, ReadElement());
+ return true;
+ }
+ }
+ else if (context.Position == lengthMinusEnd)
+ {
+ if (ReadByte() != 0)
+ throw JsonReaderException.Create(this, "Unexpected end of object byte value.");
+
+ PopContext();
+ if (_currentContext != null)
+ MovePosition(context.Length);
+
+ JsonToken endToken = (context.Type == BsonType.Object) ? JsonToken.EndObject : JsonToken.EndArray;
+ SetToken(endToken);
+ return true;
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Read past end of current container context.");
+ }
+ case State.ConstructorStart:
+ break;
+ case State.Constructor:
+ break;
+ case State.Error:
+ break;
+ case State.Finished:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ return false;
+ }
+
+ private void PopContext()
+ {
+ _stack.RemoveAt(_stack.Count - 1);
+ if (_stack.Count == 0)
+ _currentContext = null;
+ else
+ _currentContext = _stack[_stack.Count - 1];
+ }
+
+ private void PushContext(ContainerContext newContext)
+ {
+ _stack.Add(newContext);
+ _currentContext = newContext;
+ }
+
+ private byte ReadByte()
+ {
+ MovePosition(1);
+ return _reader.ReadByte();
+ }
+
+ private void ReadType(BsonType type)
+ {
+ switch (type)
+ {
+ case BsonType.Number:
+ double d = ReadDouble();
+
+ if (_floatParseHandling == FloatParseHandling.Decimal)
+ SetToken(JsonToken.Float, Convert.ToDecimal(d, CultureInfo.InvariantCulture));
+ else
+ SetToken(JsonToken.Float, d);
+ break;
+ case BsonType.String:
+ case BsonType.Symbol:
+ SetToken(JsonToken.String, ReadLengthString());
+ break;
+ case BsonType.Object:
+ {
+ SetToken(JsonToken.StartObject);
+
+ ContainerContext newContext = new ContainerContext(BsonType.Object);
+ PushContext(newContext);
+ newContext.Length = ReadInt32();
+ break;
+ }
+ case BsonType.Array:
+ {
+ SetToken(JsonToken.StartArray);
+
+ ContainerContext newContext = new ContainerContext(BsonType.Array);
+ PushContext(newContext);
+ newContext.Length = ReadInt32();
+ break;
+ }
+ case BsonType.Binary:
+ BsonBinaryType binaryType;
+ byte[] data = ReadBinary(out binaryType);
+
+ object value = (binaryType != BsonBinaryType.Uuid)
+ ? data
+ : (object)new Guid(data);
+
+ SetToken(JsonToken.Bytes, value);
+ break;
+ case BsonType.Undefined:
+ SetToken(JsonToken.Undefined);
+ break;
+ case BsonType.Oid:
+ byte[] oid = ReadBytes(12);
+ SetToken(JsonToken.Bytes, oid);
+ break;
+ case BsonType.Boolean:
+ bool b = Convert.ToBoolean(ReadByte());
+ SetToken(JsonToken.Boolean, b);
+ break;
+ case BsonType.Date:
+ long ticks = ReadInt64();
+ DateTime utcDateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
+
+ DateTime dateTime;
+ switch (DateTimeKindHandling)
+ {
+ case DateTimeKind.Unspecified:
+ dateTime = DateTime.SpecifyKind(utcDateTime, DateTimeKind.Unspecified);
+ break;
+ case DateTimeKind.Local:
+ dateTime = utcDateTime.ToLocalTime();
+ break;
+ default:
+ dateTime = utcDateTime;
+ break;
+ }
+
+ SetToken(JsonToken.Date, dateTime);
+ break;
+ case BsonType.Null:
+ SetToken(JsonToken.Null);
+ break;
+ case BsonType.Regex:
+ string expression = ReadString();
+ string modifiers = ReadString();
+
+ string regex = @"/" + expression + @"/" + modifiers;
+ SetToken(JsonToken.String, regex);
+ break;
+ case BsonType.Reference:
+ SetToken(JsonToken.StartObject);
+ _bsonReaderState = BsonReaderState.ReferenceStart;
+ break;
+ case BsonType.Code:
+ SetToken(JsonToken.String, ReadLengthString());
+ break;
+ case BsonType.CodeWScope:
+ SetToken(JsonToken.StartObject);
+ _bsonReaderState = BsonReaderState.CodeWScopeStart;
+ break;
+ case BsonType.Integer:
+ SetToken(JsonToken.Integer, (long)ReadInt32());
+ break;
+ case BsonType.TimeStamp:
+ case BsonType.Long:
+ SetToken(JsonToken.Integer, ReadInt64());
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("type", "Unexpected BsonType value: " + type);
+ }
+ }
+
+ private byte[] ReadBinary(out BsonBinaryType binaryType)
+ {
+ int dataLength = ReadInt32();
+
+ binaryType = (BsonBinaryType)ReadByte();
+
+#pragma warning disable 612,618
+ // the old binary type has the data length repeated in the data for some reason
+ if (binaryType == BsonBinaryType.BinaryOld && !_jsonNet35BinaryCompatibility)
+ {
+ dataLength = ReadInt32();
+ }
+#pragma warning restore 612,618
+
+ return ReadBytes(dataLength);
+ }
+
+ private string ReadString()
+ {
+ EnsureBuffers();
+
+ StringBuilder builder = null;
+
+ int totalBytesRead = 0;
+ // used in case of left over multibyte characters in the buffer
+ int offset = 0;
+ do
+ {
+ int count = offset;
+ byte b;
+ while (count < MaxCharBytesSize && (b = _reader.ReadByte()) > 0)
+ {
+ _byteBuffer[count++] = b;
+ }
+ int byteCount = count - offset;
+ totalBytesRead += byteCount;
+
+ if (count < MaxCharBytesSize && builder == null)
+ {
+ // pref optimization to avoid reading into a string builder
+ // if string is smaller than the buffer then return it directly
+ int length = Encoding.UTF8.GetChars(_byteBuffer, 0, byteCount, _charBuffer, 0);
+
+ MovePosition(totalBytesRead + 1);
+ return new string(_charBuffer, 0, length);
+ }
+ else
+ {
+ // calculate the index of the end of the last full character in the buffer
+ int lastFullCharStop = GetLastFullCharStop(count - 1);
+
+ int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0);
+
+ if (builder == null)
+ builder = new StringBuilder(MaxCharBytesSize * 2);
+
+ builder.Append(_charBuffer, 0, charCount);
+
+ if (lastFullCharStop < byteCount - 1)
+ {
+ offset = byteCount - lastFullCharStop - 1;
+ // copy left over multi byte characters to beginning of buffer for next iteration
+ Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, offset);
+ }
+ else
+ {
+ // reached end of string
+ if (count < MaxCharBytesSize)
+ {
+ MovePosition(totalBytesRead + 1);
+ return builder.ToString();
+ }
+
+ offset = 0;
+ }
+ }
+ } while (true);
+ }
+
+ private string ReadLengthString()
+ {
+ int length = ReadInt32();
+
+ MovePosition(length);
+
+ string s = GetString(length - 1);
+ _reader.ReadByte();
+
+ return s;
+ }
+
+ private string GetString(int length)
+ {
+ if (length == 0)
+ return string.Empty;
+
+ EnsureBuffers();
+
+ StringBuilder builder = null;
+
+ int totalBytesRead = 0;
+
+ // used in case of left over multibyte characters in the buffer
+ int offset = 0;
+ do
+ {
+ int count = ((length - totalBytesRead) > MaxCharBytesSize - offset)
+ ? MaxCharBytesSize - offset
+ : length - totalBytesRead;
+
+ int byteCount = _reader.Read(_byteBuffer, offset, count);
+
+ if (byteCount == 0)
+ throw new EndOfStreamException("Unable to read beyond the end of the stream.");
+
+ totalBytesRead += byteCount;
+
+ // Above, byteCount is how many bytes we read this time.
+ // Below, byteCount is how many bytes are in the _byteBuffer.
+ byteCount += offset;
+
+ if (byteCount == length)
+ {
+ // pref optimization to avoid reading into a string builder
+ // first iteration and all bytes read then return string directly
+ int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, byteCount, _charBuffer, 0);
+ return new string(_charBuffer, 0, charCount);
+ }
+ else
+ {
+ int lastFullCharStop = GetLastFullCharStop(byteCount - 1);
+
+ if (builder == null)
+ builder = new StringBuilder(length);
+
+ int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0);
+ builder.Append(_charBuffer, 0, charCount);
+
+ if (lastFullCharStop < byteCount - 1)
+ {
+ offset = byteCount - lastFullCharStop - 1;
+ // copy left over multi byte characters to beginning of buffer for next iteration
+ Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, offset);
+ }
+ else
+ {
+ offset = 0;
+ }
+ }
+ } while (totalBytesRead < length);
+
+ return builder.ToString();
+ }
+
+ private int GetLastFullCharStop(int start)
+ {
+ int lookbackPos = start;
+ int bis = 0;
+ while (lookbackPos >= 0)
+ {
+ bis = BytesInSequence(_byteBuffer[lookbackPos]);
+ if (bis == 0)
+ {
+ lookbackPos--;
+ continue;
+ }
+ else if (bis == 1)
+ {
+ break;
+ }
+ else
+ {
+ lookbackPos--;
+ break;
+ }
+ }
+ if (bis == start - lookbackPos)
+ {
+ //Full character.
+ return start;
+ }
+ else
+ {
+ return lookbackPos;
+ }
+ }
+
+ private int BytesInSequence(byte b)
+ {
+ if (b <= SeqRange1[1]) return 1;
+ if (b >= SeqRange2[0] && b <= SeqRange2[1]) return 2;
+ if (b >= SeqRange3[0] && b <= SeqRange3[1]) return 3;
+ if (b >= SeqRange4[0] && b <= SeqRange4[1]) return 4;
+ return 0;
+ }
+
+ private void EnsureBuffers()
+ {
+ if (_byteBuffer == null)
+ {
+ _byteBuffer = new byte[MaxCharBytesSize];
+ }
+ if (_charBuffer == null)
+ {
+ int charBufferSize = Encoding.UTF8.GetMaxCharCount(MaxCharBytesSize);
+ _charBuffer = new char[charBufferSize];
+ }
+ }
+
+ private double ReadDouble()
+ {
+ MovePosition(8);
+ return _reader.ReadDouble();
+ }
+
+ private int ReadInt32()
+ {
+ MovePosition(4);
+ return _reader.ReadInt32();
+ }
+
+ private long ReadInt64()
+ {
+ MovePosition(8);
+ return _reader.ReadInt64();
+ }
+
+ private BsonType ReadType()
+ {
+ MovePosition(1);
+ return (BsonType)_reader.ReadSByte();
+ }
+
+ private void MovePosition(int count)
+ {
+ _currentContext.Position += count;
+ }
+
+ private byte[] ReadBytes(int count)
+ {
+ MovePosition(count);
+ return _reader.ReadBytes(count);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Bson/BsonToken.cs b/Libs/JsonNet/Bson/BsonToken.cs
new file mode 100644
index 0000000..06927a4
--- /dev/null
+++ b/Libs/JsonNet/Bson/BsonToken.cs
@@ -0,0 +1,157 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Bson
+{
+ internal abstract class BsonToken
+ {
+ public abstract BsonType Type { get; }
+ public BsonToken Parent { get; set; }
+ public int CalculatedSize { get; set; }
+ }
+
+ internal class BsonObject : BsonToken, IEnumerable
+ {
+ private readonly List _children = new List();
+
+ public void Add(string name, BsonToken token)
+ {
+ _children.Add(new BsonProperty { Name = new BsonString(name, false), Value = token });
+ token.Parent = this;
+ }
+
+ public override BsonType Type
+ {
+ get { return BsonType.Object; }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _children.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+
+ internal class BsonArray : BsonToken, IEnumerable
+ {
+ private readonly List _children = new List();
+
+ public void Add(BsonToken token)
+ {
+ _children.Add(token);
+ token.Parent = this;
+ }
+
+ public override BsonType Type
+ {
+ get { return BsonType.Array; }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _children.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+
+ internal class BsonValue : BsonToken
+ {
+ private readonly object _value;
+ private readonly BsonType _type;
+
+ public BsonValue(object value, BsonType type)
+ {
+ _value = value;
+ _type = type;
+ }
+
+ public object Value
+ {
+ get { return _value; }
+ }
+
+ public override BsonType Type
+ {
+ get { return _type; }
+ }
+ }
+
+ internal class BsonString : BsonValue
+ {
+ public int ByteCount { get; set; }
+ public bool IncludeLength { get; set; }
+
+ public BsonString(object value, bool includeLength)
+ : base(value, BsonType.String)
+ {
+ IncludeLength = includeLength;
+ }
+ }
+
+ internal class BsonBinary : BsonValue
+ {
+ public BsonBinaryType BinaryType { get; set; }
+
+ public BsonBinary(byte[] value, BsonBinaryType binaryType)
+ : base(value, BsonType.Binary)
+ {
+ BinaryType = binaryType;
+ }
+ }
+
+ internal class BsonRegex : BsonToken
+ {
+ public BsonString Pattern { get; set; }
+ public BsonString Options { get; set; }
+
+ public BsonRegex(string pattern, string options)
+ {
+ Pattern = new BsonString(pattern, false);
+ Options = new BsonString(options, false);
+ }
+
+ public override BsonType Type
+ {
+ get { return BsonType.Regex; }
+ }
+ }
+
+ internal class BsonProperty
+ {
+ public BsonString Name { get; set; }
+ public BsonToken Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Bson/BsonType.cs b/Libs/JsonNet/Bson/BsonType.cs
new file mode 100644
index 0000000..e119298
--- /dev/null
+++ b/Libs/JsonNet/Bson/BsonType.cs
@@ -0,0 +1,51 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Bson
+{
+ internal enum BsonType : sbyte
+ {
+ Number = 1,
+ String = 2,
+ Object = 3,
+ Array = 4,
+ Binary = 5,
+ Undefined = 6,
+ Oid = 7,
+ Boolean = 8,
+ Date = 9,
+ Null = 10,
+ Regex = 11,
+ Reference = 12,
+ Code = 13,
+ Symbol = 14,
+ CodeWScope = 15,
+ Integer = 16,
+ TimeStamp = 17,
+ Long = 18,
+ MinKey = -1,
+ MaxKey = 127
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Bson/BsonWriter.cs b/Libs/JsonNet/Bson/BsonWriter.cs
new file mode 100644
index 0000000..a0ea088
--- /dev/null
+++ b/Libs/JsonNet/Bson/BsonWriter.cs
@@ -0,0 +1,517 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using System.Text;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Linq;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Bson
+{
+ ///
+ /// Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
+ ///
+ public class BsonWriter : JsonWriter
+ {
+ private readonly BsonBinaryWriter _writer;
+
+ private BsonToken _root;
+ private BsonToken _parent;
+ private string _propertyName;
+
+ ///
+ /// Gets or sets the used when writing values to BSON.
+ /// When set to no conversion will occur.
+ ///
+ /// The used when writing values to BSON.
+ public DateTimeKind DateTimeKindHandling
+ {
+ get { return _writer.DateTimeKindHandling; }
+ set { _writer.DateTimeKindHandling = value; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ public BsonWriter(Stream stream)
+ {
+ ValidationUtils.ArgumentNotNull(stream, "stream");
+ _writer = new BsonBinaryWriter(new BinaryWriter(stream));
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The writer.
+ public BsonWriter(BinaryWriter writer)
+ {
+ ValidationUtils.ArgumentNotNull(writer, "writer");
+ _writer = new BsonBinaryWriter(writer);
+ }
+
+ ///
+ /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+ ///
+ public override void Flush()
+ {
+ _writer.Flush();
+ }
+
+ ///
+ /// Writes the end.
+ ///
+ /// The token.
+ protected override void WriteEnd(JsonToken token)
+ {
+ base.WriteEnd(token);
+ RemoveParent();
+
+ if (Top == 0)
+ {
+ _writer.WriteToken(_root);
+ }
+ }
+
+ ///
+ /// Writes out a comment /*...*/
containing the specified text.
+ ///
+ /// Text to place inside the comment.
+ public override void WriteComment(string text)
+ {
+ throw JsonWriterException.Create(this, "Cannot write JSON comment as BSON.", null);
+ }
+
+ ///
+ /// Writes the start of a constructor with the given name.
+ ///
+ /// The name of the constructor.
+ public override void WriteStartConstructor(string name)
+ {
+ throw JsonWriterException.Create(this, "Cannot write JSON constructor as BSON.", null);
+ }
+
+ ///
+ /// Writes raw JSON.
+ ///
+ /// The raw JSON to write.
+ public override void WriteRaw(string json)
+ {
+ throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null);
+ }
+
+ ///
+ /// Writes raw JSON where a value is expected and updates the writer's state.
+ ///
+ /// The raw JSON to write.
+ public override void WriteRawValue(string json)
+ {
+ throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null);
+ }
+
+ ///
+ /// Writes the beginning of a Json array.
+ ///
+ public override void WriteStartArray()
+ {
+ base.WriteStartArray();
+
+ AddParent(new BsonArray());
+ }
+
+ ///
+ /// Writes the beginning of a Json object.
+ ///
+ public override void WriteStartObject()
+ {
+ base.WriteStartObject();
+
+ AddParent(new BsonObject());
+ }
+
+ ///
+ /// Writes the property name of a name/value pair on a Json object.
+ ///
+ /// The name of the property.
+ public override void WritePropertyName(string name)
+ {
+ base.WritePropertyName(name);
+
+ _propertyName = name;
+ }
+
+ ///
+ /// Closes this stream and the underlying stream.
+ ///
+ public override void Close()
+ {
+ base.Close();
+
+ if (CloseOutput && _writer != null)
+ _writer.Close();
+ }
+
+ private void AddParent(BsonToken container)
+ {
+ AddToken(container);
+ _parent = container;
+ }
+
+ private void RemoveParent()
+ {
+ _parent = _parent.Parent;
+ }
+
+ private void AddValue(object value, BsonType type)
+ {
+ AddToken(new BsonValue(value, type));
+ }
+
+ internal void AddToken(BsonToken token)
+ {
+ if (_parent != null)
+ {
+ if (_parent is BsonObject)
+ {
+ ((BsonObject)_parent).Add(_propertyName, token);
+ _propertyName = null;
+ }
+ else
+ {
+ ((BsonArray)_parent).Add(token);
+ }
+ }
+ else
+ {
+ if (token.Type != BsonType.Object && token.Type != BsonType.Array)
+ throw JsonWriterException.Create(this, "Error writing {0} value. BSON must start with an Object or Array.".FormatWith(CultureInfo.InvariantCulture, token.Type), null);
+
+ _parent = token;
+ _root = token;
+ }
+ }
+
+ #region WriteValue methods
+ ///
+ /// Writes a value.
+ /// An error will raised if the value cannot be written as a single JSON token.
+ ///
+ /// The value to write.
+ public override void WriteValue(object value)
+ {
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+ if (value is BigInteger)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ AddToken(new BsonBinary(((BigInteger)value).ToByteArray(), BsonBinaryType.Binary));
+ }
+ else
+#endif
+ {
+ base.WriteValue(value);
+ }
+ }
+
+ ///
+ /// Writes a null value.
+ ///
+ public override void WriteNull()
+ {
+ base.WriteNull();
+ AddValue(null, BsonType.Null);
+ }
+
+ ///
+ /// Writes an undefined value.
+ ///
+ public override void WriteUndefined()
+ {
+ base.WriteUndefined();
+ AddValue(null, BsonType.Undefined);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(string value)
+ {
+ base.WriteValue(value);
+ if (value == null)
+ AddValue(null, BsonType.Null);
+ else
+ AddToken(new BsonString(value, true));
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(int value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public override void WriteValue(uint value)
+ {
+ if (value > int.MaxValue)
+ throw JsonWriterException.Create(this, "Value is too large to fit in a signed 32 bit integer. BSON does not support unsigned values.", null);
+
+ base.WriteValue(value);
+ AddValue(value, BsonType.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(long value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Long);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public override void WriteValue(ulong value)
+ {
+ if (value > long.MaxValue)
+ throw JsonWriterException.Create(this, "Value is too large to fit in a signed 64 bit integer. BSON does not support unsigned values.", null);
+
+ base.WriteValue(value);
+ AddValue(value, BsonType.Long);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(float value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Number);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(double value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Number);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(bool value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Boolean);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(short value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public override void WriteValue(ushort value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(char value)
+ {
+ base.WriteValue(value);
+ string s = null;
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ s = value.ToString(CultureInfo.InvariantCulture);
+#else
+ s = value.ToString();
+#endif
+ AddToken(new BsonString(s, true));
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(byte value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public override void WriteValue(sbyte value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(decimal value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Number);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(DateTime value)
+ {
+ base.WriteValue(value);
+ value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
+ AddValue(value, BsonType.Date);
+ }
+
+#if !NET20
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(DateTimeOffset value)
+ {
+ base.WriteValue(value);
+ AddValue(value, BsonType.Date);
+ }
+#endif
+
+ ///
+ /// Writes a [] value.
+ ///
+ /// The [] value to write.
+ public override void WriteValue(byte[] value)
+ {
+ base.WriteValue(value);
+ AddToken(new BsonBinary(value, BsonBinaryType.Binary));
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(Guid value)
+ {
+ base.WriteValue(value);
+ AddToken(new BsonBinary(value.ToByteArray(), BsonBinaryType.Uuid));
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(TimeSpan value)
+ {
+ base.WriteValue(value);
+ AddToken(new BsonString(value.ToString(), true));
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(Uri value)
+ {
+ base.WriteValue(value);
+ AddToken(new BsonString(value.ToString(), true));
+ }
+ #endregion
+
+ ///
+ /// Writes a [] value that represents a BSON object id.
+ ///
+ /// The Object ID value to write.
+ public void WriteObjectId(byte[] value)
+ {
+ ValidationUtils.ArgumentNotNull(value, "value");
+
+ if (value.Length != 12)
+ throw JsonWriterException.Create(this, "An object id must be 12 bytes", null);
+
+ // hack to update the writer state
+ UpdateScopeWithFinishedValue();
+ AutoComplete(JsonToken.Undefined);
+ AddValue(value, BsonType.Oid);
+ }
+
+ ///
+ /// Writes a BSON regex.
+ ///
+ /// The regex pattern.
+ /// The regex options.
+ public void WriteRegex(string pattern, string options)
+ {
+ ValidationUtils.ArgumentNotNull(pattern, "pattern");
+
+ // hack to update the writer state
+ UpdateScopeWithFinishedValue();
+ AutoComplete(JsonToken.Undefined);
+ AddToken(new BsonRegex(pattern, options));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/ConstructorHandling.cs b/Libs/JsonNet/ConstructorHandling.cs
new file mode 100644
index 0000000..e403f1e
--- /dev/null
+++ b/Libs/JsonNet/ConstructorHandling.cs
@@ -0,0 +1,43 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies how constructors are used when initializing objects during deserialization by the .
+ ///
+ public enum ConstructorHandling
+ {
+ ///
+ /// First attempt to use the public default constructor, then fall back to single paramatized constructor, then the non-public default constructor.
+ ///
+ Default = 0,
+
+ ///
+ /// Json.NET will use a non-public default constructor before falling back to a paramatized constructor.
+ ///
+ AllowNonPublicDefaultConstructor = 1
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/BinaryConverter.cs b/Libs/JsonNet/Converters/BinaryConverter.cs
new file mode 100644
index 0000000..6c2284d
--- /dev/null
+++ b/Libs/JsonNet/Converters/BinaryConverter.cs
@@ -0,0 +1,188 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using System.Data.SqlTypes;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a binary value to and from a base 64 string value.
+ ///
+ public class BinaryConverter : JsonConverter
+ {
+#if !NET20
+ private const string BinaryTypeName = "System.Data.Linq.Binary";
+ private const string BinaryToArrayName = "ToArray";
+ private ReflectionObject _reflectionObject;
+#endif
+
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ if (value == null)
+ {
+ writer.WriteNull();
+ return;
+ }
+
+ byte[] data = GetByteArray(value);
+
+ writer.WriteValue(data);
+ }
+
+ private byte[] GetByteArray(object value)
+ {
+#if !(NET20)
+ if (value.GetType().AssignableToTypeName(BinaryTypeName))
+ {
+ EnsureReflectionObject(value.GetType());
+ return (byte[])_reflectionObject.GetValue(value, BinaryToArrayName);
+ }
+#endif
+ if (value is SqlBinary)
+ return ((SqlBinary)value).Value;
+
+ throw new JsonSerializationException("Unexpected value type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
+ }
+
+#if !NET20
+ private void EnsureReflectionObject(Type t)
+ {
+ if (_reflectionObject == null)
+ _reflectionObject = ReflectionObject.Create(t, t.GetConstructor(new[] { typeof(byte[]) }), BinaryToArrayName);
+ }
+#endif
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ Type t = (ReflectionUtils.IsNullableType(objectType))
+ ? Nullable.GetUnderlyingType(objectType)
+ : objectType;
+
+ if (reader.TokenType == JsonToken.Null)
+ {
+ if (!ReflectionUtils.IsNullable(objectType))
+ throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+ return null;
+ }
+
+ byte[] data;
+
+ if (reader.TokenType == JsonToken.StartArray)
+ {
+ data = ReadByteArray(reader);
+ }
+ else if (reader.TokenType == JsonToken.String)
+ {
+ // current token is already at base64 string
+ // unable to call ReadAsBytes so do it the old fashion way
+ string encodedData = reader.Value.ToString();
+ data = Convert.FromBase64String(encodedData);
+ }
+ else
+ {
+ throw JsonSerializationException.Create(reader, "Unexpected token parsing binary. Expected String or StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+ }
+
+#if !NET20
+ if (t.AssignableToTypeName(BinaryTypeName))
+ {
+ EnsureReflectionObject(t);
+
+ return _reflectionObject.Creator(data);
+ }
+#endif
+
+ if (t == typeof(SqlBinary))
+ return new SqlBinary(data);
+
+ throw JsonSerializationException.Create(reader, "Unexpected object type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, objectType));
+ }
+
+ private byte[] ReadByteArray(JsonReader reader)
+ {
+ List byteList = new List();
+
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.Integer:
+ byteList.Add(Convert.ToByte(reader.Value, CultureInfo.InvariantCulture));
+ break;
+ case JsonToken.EndArray:
+ return byteList.ToArray();
+ case JsonToken.Comment:
+ // skip
+ break;
+ default:
+ throw JsonSerializationException.Create(reader, "Unexpected token when reading bytes: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+ }
+ }
+
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading bytes.");
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+#if !NET20
+ if (objectType.AssignableToTypeName(BinaryTypeName))
+ return true;
+#endif
+
+ if (objectType == typeof(SqlBinary) || objectType == typeof(SqlBinary?))
+ return true;
+
+ return false;
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/BsonObjectIdConverter.cs b/Libs/JsonNet/Converters/BsonObjectIdConverter.cs
new file mode 100644
index 0000000..8c5618d
--- /dev/null
+++ b/Libs/JsonNet/Converters/BsonObjectIdConverter.cs
@@ -0,0 +1,89 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Bson;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from JSON and BSON.
+ ///
+ public class BsonObjectIdConverter : JsonConverter
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ BsonObjectId objectId = (BsonObjectId)value;
+
+ BsonWriter bsonWriter = writer as BsonWriter;
+ if (bsonWriter != null)
+ {
+ bsonWriter.WriteObjectId(objectId.Value);
+ }
+ else
+ {
+ writer.WriteValue(objectId.Value);
+ }
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType != JsonToken.Bytes)
+ throw new JsonSerializationException("Expected Bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+ byte[] value = (byte[])reader.Value;
+
+ return new BsonObjectId(value);
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return (objectType == typeof(BsonObjectId));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/CustomCreationConverter.cs b/Libs/JsonNet/Converters/CustomCreationConverter.cs
new file mode 100644
index 0000000..adf519b
--- /dev/null
+++ b/Libs/JsonNet/Converters/CustomCreationConverter.cs
@@ -0,0 +1,99 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Create a custom object
+ ///
+ /// The object type to convert.
+ public abstract class CustomCreationConverter : JsonConverter
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ throw new NotSupportedException("CustomCreationConverter should only be used while deserializing.");
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ return null;
+
+ T value = Create(objectType);
+ if (value == null)
+ throw new JsonSerializationException("No object created.");
+
+ serializer.Populate(reader, value);
+ return value;
+ }
+
+ ///
+ /// Creates an object which will then be populated by the serializer.
+ ///
+ /// Type of the object.
+ /// The created object.
+ public abstract T Create(Type objectType);
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return typeof(T).IsAssignableFrom(objectType);
+ }
+
+ ///
+ /// Gets a value indicating whether this can write JSON.
+ ///
+ ///
+ /// true if this can write JSON; otherwise, false .
+ ///
+ public override bool CanWrite
+ {
+ get { return false; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/DataSetConverter.cs b/Libs/JsonNet/Converters/DataSetConverter.cs
new file mode 100644
index 0000000..3bfffff
--- /dev/null
+++ b/Libs/JsonNet/Converters/DataSetConverter.cs
@@ -0,0 +1,118 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using System.Data;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from JSON.
+ ///
+ public class DataSetConverter : JsonConverter
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ DataSet dataSet = (DataSet)value;
+ DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+ DataTableConverter converter = new DataTableConverter();
+
+ writer.WriteStartObject();
+
+ foreach (DataTable table in dataSet.Tables)
+ {
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(table.TableName) : table.TableName);
+
+ converter.WriteJson(writer, table, serializer);
+ }
+
+ writer.WriteEndObject();
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ // handle typed datasets
+ DataSet ds = (objectType == typeof(DataSet))
+ ? new DataSet()
+ : (DataSet)Activator.CreateInstance(objectType);
+
+ DataTableConverter converter = new DataTableConverter();
+
+ CheckedRead(reader);
+
+ while (reader.TokenType == JsonToken.PropertyName)
+ {
+ DataTable dt = ds.Tables[(string)reader.Value];
+ bool exists = (dt != null);
+
+ dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer);
+
+ if (!exists)
+ ds.Tables.Add(dt);
+
+ CheckedRead(reader);
+ }
+
+ return ds;
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified value type.
+ ///
+ /// Type of the value.
+ ///
+ /// true if this instance can convert the specified value type; otherwise, false .
+ ///
+ public override bool CanConvert(Type valueType)
+ {
+ return typeof(DataSet).IsAssignableFrom(valueType);
+ }
+
+ private void CheckedRead(JsonReader reader)
+ {
+ if (!reader.Read())
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading DataSet.");
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/DataTableConverter.cs b/Libs/JsonNet/Converters/DataTableConverter.cs
new file mode 100644
index 0000000..82d3143
--- /dev/null
+++ b/Libs/JsonNet/Converters/DataTableConverter.cs
@@ -0,0 +1,226 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using System.Data;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from JSON.
+ ///
+ public class DataTableConverter : JsonConverter
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ DataTable table = (DataTable)value;
+ DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+ writer.WriteStartArray();
+
+ foreach (DataRow row in table.Rows)
+ {
+ writer.WriteStartObject();
+ foreach (DataColumn column in row.Table.Columns)
+ {
+ if (serializer.NullValueHandling == NullValueHandling.Ignore && (row[column] == null || row[column] == DBNull.Value))
+ continue;
+
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(column.ColumnName) : column.ColumnName);
+ serializer.Serialize(writer, row[column]);
+ }
+ writer.WriteEndObject();
+ }
+
+ writer.WriteEndArray();
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ DataTable dt = existingValue as DataTable;
+
+ if (dt == null)
+ {
+ // handle typed datasets
+ dt = (objectType == typeof(DataTable))
+ ? new DataTable()
+ : (DataTable)Activator.CreateInstance(objectType);
+ }
+
+ if (reader.TokenType == JsonToken.PropertyName)
+ {
+ dt.TableName = (string)reader.Value;
+
+ CheckedRead(reader);
+ }
+
+ if (reader.TokenType != JsonToken.StartArray)
+ throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable. Expected StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+ CheckedRead(reader);
+
+ while (reader.TokenType != JsonToken.EndArray)
+ {
+ CreateRow(reader, dt);
+
+ CheckedRead(reader);
+ }
+
+ return dt;
+ }
+
+ private static void CreateRow(JsonReader reader, DataTable dt)
+ {
+ DataRow dr = dt.NewRow();
+ CheckedRead(reader);
+
+ while (reader.TokenType == JsonToken.PropertyName)
+ {
+ string columnName = (string)reader.Value;
+
+ CheckedRead(reader);
+
+ DataColumn column = dt.Columns[columnName];
+ if (column == null)
+ {
+ Type columnType = GetColumnDataType(reader);
+ column = new DataColumn(columnName, columnType);
+ dt.Columns.Add(column);
+ }
+
+ if (column.DataType == typeof(DataTable))
+ {
+ if (reader.TokenType == JsonToken.StartArray)
+ CheckedRead(reader);
+
+ DataTable nestedDt = new DataTable();
+
+ while (reader.TokenType != JsonToken.EndArray)
+ {
+ CreateRow(reader, nestedDt);
+
+ CheckedRead(reader);
+ }
+
+ dr[columnName] = nestedDt;
+ }
+ else if (column.DataType.IsArray && column.DataType != typeof(byte[]))
+ {
+ if (reader.TokenType == JsonToken.StartArray)
+ CheckedRead(reader);
+
+ List o = new List();
+
+ while (reader.TokenType != JsonToken.EndArray)
+ {
+ o.Add(reader.Value);
+ CheckedRead(reader);
+ }
+
+ Array destinationArray = Array.CreateInstance(column.DataType.GetElementType(), o.Count);
+ Array.Copy(o.ToArray(), destinationArray, o.Count);
+
+ dr[columnName] = destinationArray;
+ }
+ else
+ {
+ dr[columnName] = reader.Value ?? DBNull.Value;
+ }
+
+ CheckedRead(reader);
+ }
+
+ dr.EndEdit();
+ dt.Rows.Add(dr);
+ }
+
+ private static Type GetColumnDataType(JsonReader reader)
+ {
+ JsonToken tokenType = reader.TokenType;
+
+ switch (tokenType)
+ {
+ case JsonToken.Integer:
+ case JsonToken.Boolean:
+ case JsonToken.Float:
+ case JsonToken.String:
+ case JsonToken.Date:
+ case JsonToken.Bytes:
+ return reader.ValueType;
+ case JsonToken.Null:
+ case JsonToken.Undefined:
+ return typeof(string);
+ case JsonToken.StartArray:
+ CheckedRead(reader);
+ if (reader.TokenType == JsonToken.StartObject)
+ return typeof(DataTable); // nested datatable
+
+ Type arrayType = GetColumnDataType(reader);
+ return arrayType.MakeArrayType();
+ default:
+ throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType));
+ }
+ }
+
+ private static void CheckedRead(JsonReader reader)
+ {
+ if (!reader.Read())
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading DataTable.");
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified value type.
+ ///
+ /// Type of the value.
+ ///
+ /// true if this instance can convert the specified value type; otherwise, false .
+ ///
+ public override bool CanConvert(Type valueType)
+ {
+ return typeof(DataTable).IsAssignableFrom(valueType);
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/DateTimeConverterBase.cs b/Libs/JsonNet/Converters/DateTimeConverterBase.cs
new file mode 100644
index 0000000..a928b13
--- /dev/null
+++ b/Libs/JsonNet/Converters/DateTimeConverterBase.cs
@@ -0,0 +1,54 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Provides a base class for converting a to and from JSON.
+ ///
+ public abstract class DateTimeConverterBase : JsonConverter
+ {
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ if (objectType == typeof(DateTime) || objectType == typeof(DateTime?))
+ return true;
+#if !NET20
+ if (objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?))
+ return true;
+#endif
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/DiscriminatedUnionConverter.cs b/Libs/JsonNet/Converters/DiscriminatedUnionConverter.cs
new file mode 100644
index 0000000..0edb0f9
--- /dev/null
+++ b/Libs/JsonNet/Converters/DiscriminatedUnionConverter.cs
@@ -0,0 +1,214 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET35 || NET20 || NETFX_CORE)
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using System.Reflection;
+using Newtonsoft.Json.Serialization;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a F# discriminated union type to and from JSON.
+ ///
+ public class DiscriminatedUnionConverter : JsonConverter
+ {
+ private const string CasePropertyName = "Case";
+ private const string FieldsPropertyName = "Fields";
+
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+ Type t = value.GetType();
+
+ object result = FSharpUtils.GetUnionFields(null, value, t, null);
+ object info = FSharpUtils.GetUnionCaseInfo(result);
+ object fields = FSharpUtils.GetUnionCaseFields(result);
+ object caseName = FSharpUtils.GetUnionCaseInfoName(info);
+ object[] fieldsAsArray = fields as object[];
+
+ writer.WriteStartObject();
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(CasePropertyName) : CasePropertyName);
+ writer.WriteValue((string)caseName);
+ if (fieldsAsArray != null && fieldsAsArray.Length > 0)
+ {
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName);
+ serializer.Serialize(writer, fields);
+ }
+ writer.WriteEndObject();
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ return null;
+
+ object matchingCaseInfo = null;
+ string caseName = null;
+ JArray fields = null;
+
+ // start object
+ ReadAndAssert(reader);
+
+ while (reader.TokenType == JsonToken.PropertyName)
+ {
+ string propertyName = reader.Value.ToString();
+ if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase))
+ {
+ ReadAndAssert(reader);
+
+ IEnumerable cases = (IEnumerable)FSharpUtils.GetUnionCases(null, objectType, null);
+
+ caseName = reader.Value.ToString();
+
+ foreach (object c in cases)
+ {
+ if ((string)FSharpUtils.GetUnionCaseInfoName(c) == caseName)
+ {
+ matchingCaseInfo = c;
+ break;
+ }
+ }
+
+ if (matchingCaseInfo == null)
+ throw JsonSerializationException.Create(reader, "No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName));
+ }
+ else if (string.Equals(propertyName, FieldsPropertyName, StringComparison.OrdinalIgnoreCase))
+ {
+ ReadAndAssert(reader);
+ if (reader.TokenType != JsonToken.StartArray)
+ throw JsonSerializationException.Create(reader, "Union fields must been an array.");
+
+ fields = (JArray)JToken.ReadFrom(reader);
+ }
+ else
+ {
+ throw JsonSerializationException.Create(reader, "Unexpected property '{0}' found when reading union.".FormatWith(CultureInfo.InvariantCulture, propertyName));
+ }
+
+ ReadAndAssert(reader);
+ }
+
+ if (matchingCaseInfo == null)
+ throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, CasePropertyName));
+
+ PropertyInfo[] fieldProperties = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(matchingCaseInfo);
+ object[] typedFieldValues = new object[fieldProperties.Length];
+
+ if (fieldProperties.Length > 0 && fields == null)
+ throw JsonSerializationException.Create(reader, "No '{0}' property with union fields found.".FormatWith(CultureInfo.InvariantCulture, FieldsPropertyName));
+
+ if (fields != null)
+ {
+ if (fieldProperties.Length != fields.Count)
+ throw JsonSerializationException.Create(reader, "The number of field values does not match the number of properties definied by union '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName));
+
+
+ for (int i = 0; i < fields.Count; i++)
+ {
+ JToken t = fields[i];
+ PropertyInfo fieldProperty = fieldProperties[i];
+
+ typedFieldValues[i] = t.ToObject(fieldProperty.PropertyType, serializer);
+ }
+ }
+
+ return FSharpUtils.MakeUnion(null, matchingCaseInfo, typedFieldValues, null);
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ if (typeof(IEnumerable).IsAssignableFrom(objectType))
+ return false;
+
+ // all fsharp objects have CompilationMappingAttribute
+ // get the fsharp assembly from the attribute and initialize latebound methods
+ object[] attributes;
+#if !(NETFX_CORE || PORTABLE)
+ attributes = objectType.GetCustomAttributes(true);
+#else
+ attributes = objectType.GetTypeInfo().GetCustomAttributes(true).ToArray();
+#endif
+
+ bool isFSharpType = false;
+ foreach (object attribute in attributes)
+ {
+ Type attributeType = attribute.GetType();
+ if (attributeType.FullName == "Microsoft.FSharp.Core.CompilationMappingAttribute")
+ {
+ FSharpUtils.EnsureInitialized(attributeType.Assembly());
+
+ isFSharpType = true;
+ break;
+ }
+ }
+
+ if (!isFSharpType)
+ return false;
+
+ return (bool)FSharpUtils.IsUnion(null, objectType, null);
+ }
+
+ private static void ReadAndAssert(JsonReader reader)
+ {
+ if (!reader.Read())
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading union.");
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/EntityKeyMemberConverter.cs b/Libs/JsonNet/Converters/EntityKeyMemberConverter.cs
new file mode 100644
index 0000000..d3b1075
--- /dev/null
+++ b/Libs/JsonNet/Converters/EntityKeyMemberConverter.cs
@@ -0,0 +1,154 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using Newtonsoft.Json.Serialization;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts an Entity Framework EntityKey to and from JSON.
+ ///
+ public class EntityKeyMemberConverter : JsonConverter
+ {
+ private const string EntityKeyMemberFullTypeName = "System.Data.EntityKeyMember";
+
+ private const string KeyPropertyName = "Key";
+ private const string TypePropertyName = "Type";
+ private const string ValuePropertyName = "Value";
+
+ private static ReflectionObject _reflectionObject;
+
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ EnsureReflectionObject(value.GetType());
+
+ DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+ string keyName = (string)_reflectionObject.GetValue(value, KeyPropertyName);
+ object keyValue = _reflectionObject.GetValue(value, ValuePropertyName);
+
+ Type keyValueType = (keyValue != null) ? keyValue.GetType() : null;
+
+ writer.WriteStartObject();
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyPropertyName) : KeyPropertyName);
+ writer.WriteValue(keyName);
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(TypePropertyName) : TypePropertyName);
+ writer.WriteValue((keyValueType != null) ? keyValueType.FullName : null);
+
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValuePropertyName) : ValuePropertyName);
+
+ if (keyValueType != null)
+ {
+ string valueJson;
+ if (JsonSerializerInternalWriter.TryConvertToString(keyValue, keyValueType, out valueJson))
+ writer.WriteValue(valueJson);
+ else
+ writer.WriteValue(keyValue);
+ }
+ else
+ {
+ writer.WriteNull();
+ }
+
+ writer.WriteEndObject();
+ }
+
+ private static void ReadAndAssertProperty(JsonReader reader, string propertyName)
+ {
+ ReadAndAssert(reader);
+
+ if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value.ToString(), propertyName, StringComparison.OrdinalIgnoreCase))
+ throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName));
+ }
+
+ private static void ReadAndAssert(JsonReader reader)
+ {
+ if (!reader.Read())
+ throw new JsonSerializationException("Unexpected end.");
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ EnsureReflectionObject(objectType);
+
+ object entityKeyMember = _reflectionObject.Creator();
+
+ ReadAndAssertProperty(reader, KeyPropertyName);
+ ReadAndAssert(reader);
+ _reflectionObject.SetValue(entityKeyMember, KeyPropertyName, reader.Value.ToString());
+
+ ReadAndAssertProperty(reader, TypePropertyName);
+ ReadAndAssert(reader);
+ string type = reader.Value.ToString();
+
+ Type t = Type.GetType(type);
+
+ ReadAndAssertProperty(reader, ValuePropertyName);
+ ReadAndAssert(reader);
+ _reflectionObject.SetValue(entityKeyMember, ValuePropertyName, serializer.Deserialize(reader, t));
+
+ ReadAndAssert(reader);
+
+ return entityKeyMember;
+ }
+
+ private static void EnsureReflectionObject(Type objectType)
+ {
+ if (_reflectionObject == null)
+ _reflectionObject = ReflectionObject.Create(objectType, KeyPropertyName, ValuePropertyName);
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType.AssignableToTypeName(EntityKeyMemberFullTypeName);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/ExpandoObjectConverter.cs b/Libs/JsonNet/Converters/ExpandoObjectConverter.cs
new file mode 100644
index 0000000..d07599d
--- /dev/null
+++ b/Libs/JsonNet/Converters/ExpandoObjectConverter.cs
@@ -0,0 +1,165 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET35 || NET20 || PORTABLE40)
+
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts an ExpandoObject to and from JSON.
+ ///
+ public class ExpandoObjectConverter : JsonConverter
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ // can write is set to false
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ return ReadValue(reader);
+ }
+
+ private object ReadValue(JsonReader reader)
+ {
+ while (reader.TokenType == JsonToken.Comment)
+ {
+ if (!reader.Read())
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
+ }
+
+ switch (reader.TokenType)
+ {
+ case JsonToken.StartObject:
+ return ReadObject(reader);
+ case JsonToken.StartArray:
+ return ReadList(reader);
+ default:
+ if (JsonReader.IsPrimitiveToken(reader.TokenType))
+ return reader.Value;
+
+ throw JsonSerializationException.Create(reader, "Unexpected token when converting ExpandoObject: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+ }
+ }
+
+ private object ReadList(JsonReader reader)
+ {
+ IList list = new List();
+
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.Comment:
+ break;
+ default:
+ object v = ReadValue(reader);
+
+ list.Add(v);
+ break;
+ case JsonToken.EndArray:
+ return list;
+ }
+ }
+
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
+ }
+
+ private object ReadObject(JsonReader reader)
+ {
+ IDictionary expandoObject = new ExpandoObject();
+
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ string propertyName = reader.Value.ToString();
+
+ if (!reader.Read())
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
+
+ object v = ReadValue(reader);
+
+ expandoObject[propertyName] = v;
+ break;
+ case JsonToken.Comment:
+ break;
+ case JsonToken.EndObject:
+ return expandoObject;
+ }
+ }
+
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return (objectType == typeof(ExpandoObject));
+ }
+
+ ///
+ /// Gets a value indicating whether this can write JSON.
+ ///
+ ///
+ /// true if this can write JSON; otherwise, false .
+ ///
+ public override bool CanWrite
+ {
+ get { return false; }
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/IsoDateTimeConverter.cs b/Libs/JsonNet/Converters/IsoDateTimeConverter.cs
new file mode 100644
index 0000000..a7d78e8
--- /dev/null
+++ b/Libs/JsonNet/Converters/IsoDateTimeConverter.cs
@@ -0,0 +1,171 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from the ISO 8601 date format (e.g. 2008-04-12T12:53Z).
+ ///
+ public class IsoDateTimeConverter : DateTimeConverterBase
+ {
+ private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
+
+ private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
+ private string _dateTimeFormat;
+ private CultureInfo _culture;
+
+ ///
+ /// Gets or sets the date time styles used when converting a date to and from JSON.
+ ///
+ /// The date time styles used when converting a date to and from JSON.
+ public DateTimeStyles DateTimeStyles
+ {
+ get { return _dateTimeStyles; }
+ set { _dateTimeStyles = value; }
+ }
+
+ ///
+ /// Gets or sets the date time format used when converting a date to and from JSON.
+ ///
+ /// The date time format used when converting a date to and from JSON.
+ public string DateTimeFormat
+ {
+ get { return _dateTimeFormat ?? string.Empty; }
+ set { _dateTimeFormat = StringUtils.NullEmptyString(value); }
+ }
+
+ ///
+ /// Gets or sets the culture used when converting a date to and from JSON.
+ ///
+ /// The culture used when converting a date to and from JSON.
+ public CultureInfo Culture
+ {
+ get { return _culture ?? CultureInfo.CurrentCulture; }
+ set { _culture = value; }
+ }
+
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ string text;
+
+ if (value is DateTime)
+ {
+ DateTime dateTime = (DateTime)value;
+
+ if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
+ || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
+ dateTime = dateTime.ToUniversalTime();
+
+ text = dateTime.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
+ }
+#if !NET20
+ else if (value is DateTimeOffset)
+ {
+ DateTimeOffset dateTimeOffset = (DateTimeOffset)value;
+ if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
+ || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
+ dateTimeOffset = dateTimeOffset.ToUniversalTime();
+
+ text = dateTimeOffset.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
+ }
+#endif
+ else
+ {
+ throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value)));
+ }
+
+ writer.WriteValue(text);
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ bool nullable = ReflectionUtils.IsNullableType(objectType);
+#if !NET20
+ Type t = (nullable)
+ ? Nullable.GetUnderlyingType(objectType)
+ : objectType;
+#endif
+
+ if (reader.TokenType == JsonToken.Null)
+ {
+ if (!ReflectionUtils.IsNullableType(objectType))
+ throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+ return null;
+ }
+
+ if (reader.TokenType == JsonToken.Date)
+ {
+#if !NET20
+ if (t == typeof(DateTimeOffset))
+ return reader.Value is DateTimeOffset ? reader.Value : new DateTimeOffset((DateTime)reader.Value);
+#endif
+
+ return reader.Value;
+ }
+
+ if (reader.TokenType != JsonToken.String)
+ throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+ string dateText = reader.Value.ToString();
+
+ if (string.IsNullOrEmpty(dateText) && nullable)
+ return null;
+
+#if !NET20
+ if (t == typeof(DateTimeOffset))
+ {
+ if (!string.IsNullOrEmpty(_dateTimeFormat))
+ return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
+ else
+ return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles);
+ }
+#endif
+
+ if (!string.IsNullOrEmpty(_dateTimeFormat))
+ return DateTime.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
+ else
+ return DateTime.Parse(dateText, Culture, _dateTimeStyles);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/JavaScriptDateTimeConverter.cs b/Libs/JsonNet/Converters/JavaScriptDateTimeConverter.cs
new file mode 100644
index 0000000..d670279
--- /dev/null
+++ b/Libs/JsonNet/Converters/JavaScriptDateTimeConverter.cs
@@ -0,0 +1,120 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from a JavaScript date constructor (e.g. new Date(52231943)).
+ ///
+ public class JavaScriptDateTimeConverter : DateTimeConverterBase
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ long ticks;
+
+ if (value is DateTime)
+ {
+ DateTime dateTime = (DateTime)value;
+ DateTime utcDateTime = dateTime.ToUniversalTime();
+ ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(utcDateTime);
+ }
+#if !NET20
+ else if (value is DateTimeOffset)
+ {
+ DateTimeOffset dateTimeOffset = (DateTimeOffset)value;
+ DateTimeOffset utcDateTimeOffset = dateTimeOffset.ToUniversalTime();
+ ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(utcDateTimeOffset.UtcDateTime);
+ }
+#endif
+ else
+ {
+ throw new JsonSerializationException("Expected date object value.");
+ }
+
+ writer.WriteStartConstructor("Date");
+ writer.WriteValue(ticks);
+ writer.WriteEndConstructor();
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing property value of the JSON that is being converted.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+#if !NET20
+ Type t = (ReflectionUtils.IsNullableType(objectType))
+ ? Nullable.GetUnderlyingType(objectType)
+ : objectType;
+#endif
+
+ if (reader.TokenType == JsonToken.Null)
+ {
+ if (!ReflectionUtils.IsNullable(objectType))
+ throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+ return null;
+ }
+
+ if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal))
+ throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
+
+ reader.Read();
+
+ if (reader.TokenType != JsonToken.Integer)
+ throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected Integer, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+ long ticks = (long)reader.Value;
+
+ DateTime d = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
+
+ reader.Read();
+
+ if (reader.TokenType != JsonToken.EndConstructor)
+ throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected EndConstructor, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+#if !NET20
+ if (t == typeof(DateTimeOffset))
+ return new DateTimeOffset(d);
+#endif
+
+ return d;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/JsonValueConverter.cs b/Libs/JsonNet/Converters/JsonValueConverter.cs
new file mode 100644
index 0000000..25f979f
--- /dev/null
+++ b/Libs/JsonNet/Converters/JsonValueConverter.cs
@@ -0,0 +1,225 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+
+#if NETFX_CORE
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Security;
+using Newtonsoft.Json.Utilities;
+using Windows.Data.Json;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from JSON.
+ ///
+ public class JsonValueConverter : JsonConverter
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ WriteJsonValue(writer, (IJsonValue)value);
+ }
+
+ private void WriteJsonValue(JsonWriter writer, IJsonValue value)
+ {
+ switch (value.ValueType)
+ {
+ case JsonValueType.Array:
+ {
+ JsonArray a = value.GetArray();
+ writer.WriteStartArray();
+ for (int i = 0; i < a.Count; i++)
+ {
+ WriteJsonValue(writer, a[i]);
+ }
+ writer.WriteEndArray();
+ }
+ break;
+ case JsonValueType.Boolean:
+ {
+ writer.WriteValue(value.GetBoolean());
+ }
+ break;
+ case JsonValueType.Null:
+ {
+ writer.WriteNull();
+ }
+ break;
+ case JsonValueType.Number:
+ {
+ // JsonValue doesn't support integers
+ // serialize whole numbers without a decimal point
+ double d = value.GetNumber();
+ bool isInteger = (d % 1 == 0);
+ if (isInteger && d <= long.MaxValue && d >= long.MinValue)
+ writer.WriteValue(Convert.ToInt64(d));
+ else
+ writer.WriteValue(d);
+ }
+ break;
+ case JsonValueType.Object:
+ {
+ JsonObject o = value.GetObject();
+ writer.WriteStartObject();
+ foreach (KeyValuePair v in o)
+ {
+ writer.WritePropertyName(v.Key);
+ WriteJsonValue(writer, v.Value);
+ }
+ writer.WriteEndObject();
+ }
+ break;
+ case JsonValueType.String:
+ {
+ writer.WriteValue(value.GetString());
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("ValueType");
+ }
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.None)
+ reader.Read();
+
+ IJsonValue value = CreateJsonValue(reader);
+
+ if (!objectType.IsAssignableFrom(value.GetType()))
+ throw JsonSerializationException.Create(reader, "Could not convert '{0}' to '{1}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), objectType));
+
+ return value;
+ }
+
+ private IJsonValue CreateJsonValue(JsonReader reader)
+ {
+ while (reader.TokenType == JsonToken.Comment)
+ {
+ if (!reader.Read())
+ throw JsonSerializationException.Create(reader, "Unexpected end.");
+ }
+
+ switch (reader.TokenType)
+ {
+ case JsonToken.StartObject:
+ {
+ return CreateJsonObject(reader);
+ }
+ case JsonToken.StartArray:
+ {
+ JsonArray a = new JsonArray();
+
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.EndArray:
+ return a;
+ default:
+ IJsonValue value = CreateJsonValue(reader);
+ a.Add(value);
+ break;
+ }
+ }
+ }
+ break;
+ case JsonToken.Integer:
+ case JsonToken.Float:
+ return JsonValue.CreateNumberValue(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture));
+ case JsonToken.String:
+ return JsonValue.CreateStringValue(reader.Value.ToString());
+ case JsonToken.Boolean:
+ return JsonValue.CreateBooleanValue(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
+ case JsonToken.Null:
+ // surely there is a better way to create a null value than this?
+ return JsonValue.Parse("null");
+ case JsonToken.Date:
+ return JsonValue.CreateStringValue(reader.Value.ToString());
+ case JsonToken.Bytes:
+ return JsonValue.CreateStringValue(reader.Value.ToString());
+ default:
+ throw JsonSerializationException.Create(reader, "Unexpected or unsupported token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+ }
+
+ throw JsonSerializationException.Create(reader, "Unexpected end.");
+ }
+
+ private JsonObject CreateJsonObject(JsonReader reader)
+ {
+ JsonObject o = new JsonObject();
+ string propertyName = null;
+
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ propertyName = (string)reader.Value;
+ break;
+ case JsonToken.EndObject:
+ return o;
+ case JsonToken.Comment:
+ break;
+ default:
+ IJsonValue propertyValue = CreateJsonValue(reader);
+ o.Add(propertyName, propertyValue);
+ break;
+ }
+ }
+
+ throw JsonSerializationException.Create(reader, "Unexpected end.");
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return typeof(IJsonValue).IsAssignableFrom(objectType);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/KeyValuePairConverter.cs b/Libs/JsonNet/Converters/KeyValuePairConverter.cs
new file mode 100644
index 0000000..e5b219f
--- /dev/null
+++ b/Libs/JsonNet/Converters/KeyValuePairConverter.cs
@@ -0,0 +1,153 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+using System.Reflection;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from JSON.
+ ///
+ public class KeyValuePairConverter : JsonConverter
+ {
+ private const string KeyName = "Key";
+ private const string ValueName = "Value";
+
+ private static readonly ThreadSafeStore ReflectionObjectPerType = new ThreadSafeStore(InitializeReflectionObject);
+
+ private static ReflectionObject InitializeReflectionObject(Type t)
+ {
+ IList genericArguments = t.GetGenericArguments();
+ Type keyType = genericArguments[0];
+ Type valueType = genericArguments[1];
+
+ return ReflectionObject.Create(t, t.GetConstructor(new[] { keyType, valueType }), KeyName, ValueName);
+ }
+
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType());
+
+ DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+ writer.WriteStartObject();
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyName) : KeyName);
+ serializer.Serialize(writer, reflectionObject.GetValue(value, KeyName), reflectionObject.GetType(KeyName));
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValueName) : ValueName);
+ serializer.Serialize(writer, reflectionObject.GetValue(value, ValueName), reflectionObject.GetType(ValueName));
+ writer.WriteEndObject();
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ bool isNullable = ReflectionUtils.IsNullableType(objectType);
+
+ Type t = (isNullable)
+ ? Nullable.GetUnderlyingType(objectType)
+ : objectType;
+
+ ReflectionObject reflectionObject = ReflectionObjectPerType.Get(t);
+
+ if (reader.TokenType == JsonToken.Null)
+ {
+ if (!isNullable)
+ throw JsonSerializationException.Create(reader, "Cannot convert null value to KeyValuePair.");
+
+ return null;
+ }
+
+ object key = null;
+ object value = null;
+
+ ReadAndAssert(reader);
+
+ while (reader.TokenType == JsonToken.PropertyName)
+ {
+ string propertyName = reader.Value.ToString();
+ if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase))
+ {
+ ReadAndAssert(reader);
+ key = serializer.Deserialize(reader, reflectionObject.GetType(KeyName));
+ }
+ else if (string.Equals(propertyName, ValueName, StringComparison.OrdinalIgnoreCase))
+ {
+ ReadAndAssert(reader);
+ value = serializer.Deserialize(reader, reflectionObject.GetType(ValueName));
+ }
+ else
+ {
+ reader.Skip();
+ }
+
+ ReadAndAssert(reader);
+ }
+
+ return reflectionObject.Creator(key, value);
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ Type t = (ReflectionUtils.IsNullableType(objectType))
+ ? Nullable.GetUnderlyingType(objectType)
+ : objectType;
+
+ if (t.IsValueType() && t.IsGenericType())
+ return (t.GetGenericTypeDefinition() == typeof(KeyValuePair<,>));
+
+ return false;
+ }
+
+ private static void ReadAndAssert(JsonReader reader)
+ {
+ if (!reader.Read())
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading KeyValuePair.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/RegexConverter.cs b/Libs/JsonNet/Converters/RegexConverter.cs
new file mode 100644
index 0000000..e589833
--- /dev/null
+++ b/Libs/JsonNet/Converters/RegexConverter.cs
@@ -0,0 +1,201 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Text.RegularExpressions;
+using Newtonsoft.Json.Bson;
+using System.Globalization;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from JSON and BSON.
+ ///
+ public class RegexConverter : JsonConverter
+ {
+ private const string PatternName = "Pattern";
+ private const string OptionsName = "Options";
+
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ Regex regex = (Regex)value;
+
+ BsonWriter bsonWriter = writer as BsonWriter;
+ if (bsonWriter != null)
+ WriteBson(bsonWriter, regex);
+ else
+ WriteJson(writer, regex, serializer);
+ }
+
+ private bool HasFlag(RegexOptions options, RegexOptions flag)
+ {
+ return ((options & flag) == flag);
+ }
+
+ private void WriteBson(BsonWriter writer, Regex regex)
+ {
+ // Regular expression - The first cstring is the regex pattern, the second
+ // is the regex options string. Options are identified by characters, which
+ // must be stored in alphabetical order. Valid options are 'i' for case
+ // insensitive matching, 'm' for multiline matching, 'x' for verbose mode,
+ // 'l' to make \w, \W, etc. locale dependent, 's' for dotall mode
+ // ('.' matches everything), and 'u' to make \w, \W, etc. match unicode.
+
+ string options = null;
+
+ if (HasFlag(regex.Options, RegexOptions.IgnoreCase))
+ options += "i";
+
+ if (HasFlag(regex.Options, RegexOptions.Multiline))
+ options += "m";
+
+ if (HasFlag(regex.Options, RegexOptions.Singleline))
+ options += "s";
+
+ options += "u";
+
+ if (HasFlag(regex.Options, RegexOptions.ExplicitCapture))
+ options += "x";
+
+ writer.WriteRegex(regex.ToString(), options);
+ }
+
+ private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer)
+ {
+ DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+ writer.WriteStartObject();
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(PatternName) : PatternName);
+ writer.WriteValue(regex.ToString());
+ writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(OptionsName) : OptionsName);
+ serializer.Serialize(writer, regex.Options);
+ writer.WriteEndObject();
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.StartObject)
+ return ReadRegexObject(reader, serializer);
+
+ if (reader.TokenType == JsonToken.String)
+ return ReadRegexString(reader);
+
+ throw JsonSerializationException.Create(reader, "Unexpected token when reading Regex.");
+ }
+
+ private object ReadRegexString(JsonReader reader)
+ {
+ string regexText = (string)reader.Value;
+ int patternOptionDelimiterIndex = regexText.LastIndexOf('/');
+
+ string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1);
+ string optionsText = regexText.Substring(patternOptionDelimiterIndex + 1);
+
+ RegexOptions options = RegexOptions.None;
+ foreach (char c in optionsText)
+ {
+ switch (c)
+ {
+ case 'i':
+ options |= RegexOptions.IgnoreCase;
+ break;
+ case 'm':
+ options |= RegexOptions.Multiline;
+ break;
+ case 's':
+ options |= RegexOptions.Singleline;
+ break;
+ case 'x':
+ options |= RegexOptions.ExplicitCapture;
+ break;
+ }
+ }
+
+ return new Regex(patternText, options);
+ }
+
+ private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer)
+ {
+ string pattern = null;
+ RegexOptions? options = null;
+
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ string propertyName = reader.Value.ToString();
+
+ if (!reader.Read())
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex.");
+
+ if (string.Equals(propertyName, PatternName, StringComparison.OrdinalIgnoreCase))
+ pattern = (string)reader.Value;
+ else if (string.Equals(propertyName, OptionsName, StringComparison.OrdinalIgnoreCase))
+ options = serializer.Deserialize(reader);
+ else
+ reader.Skip();
+ break;
+ case JsonToken.Comment:
+ break;
+ case JsonToken.EndObject:
+ if (pattern == null)
+ throw JsonSerializationException.Create(reader, "Error deserializing Regex. No pattern found.");
+
+ return new Regex(pattern, options ?? RegexOptions.None);
+ }
+ }
+
+ throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex.");
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return (objectType == typeof(Regex));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/StringEnumConverter.cs b/Libs/JsonNet/Converters/StringEnumConverter.cs
new file mode 100644
index 0000000..a30304d
--- /dev/null
+++ b/Libs/JsonNet/Converters/StringEnumConverter.cs
@@ -0,0 +1,160 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.Serialization;
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts an to and from its name string value.
+ ///
+ public class StringEnumConverter : JsonConverter
+ {
+ ///
+ /// Gets or sets a value indicating whether the written enum text should be camel case.
+ ///
+ /// true if the written enum text will be camel case; otherwise, false .
+ public bool CamelCaseText { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether integer values are allowed.
+ ///
+ /// true if integers are allowed; otherwise, false .
+ public bool AllowIntegerValues { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public StringEnumConverter()
+ {
+ AllowIntegerValues = true;
+ }
+
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ if (value == null)
+ {
+ writer.WriteNull();
+ return;
+ }
+
+ Enum e = (Enum)value;
+
+ string enumName = e.ToString("G");
+
+ if (char.IsNumber(enumName[0]) || enumName[0] == '-')
+ {
+ // enum value has no name so write number
+ writer.WriteValue(value);
+ }
+ else
+ {
+ Type enumType = e.GetType();
+
+ string finalName = EnumUtils.ToEnumName(enumType, enumName, CamelCaseText);
+
+ writer.WriteValue(finalName);
+ }
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ bool isNullable = ReflectionUtils.IsNullableType(objectType);
+ Type t = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType;
+
+ if (reader.TokenType == JsonToken.Null)
+ {
+ if (!ReflectionUtils.IsNullableType(objectType))
+ throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+ return null;
+ }
+
+ try
+ {
+ if (reader.TokenType == JsonToken.String)
+ {
+ string enumText = reader.Value.ToString();
+ return EnumUtils.ParseEnumName(enumText, isNullable, t);
+ }
+
+ if (reader.TokenType == JsonToken.Integer)
+ {
+ if (!AllowIntegerValues)
+ throw JsonSerializationException.Create(reader, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, reader.Value));
+
+ return ConvertUtils.ConvertOrCast(reader.Value, CultureInfo.InvariantCulture, t);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(reader.Value), objectType), ex);
+ }
+
+ // we don't actually expect to get here.
+ throw JsonSerializationException.Create(reader, "Unexpected token {0} when parsing enum.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ Type t = (ReflectionUtils.IsNullableType(objectType))
+ ? Nullable.GetUnderlyingType(objectType)
+ : objectType;
+
+ return t.IsEnum();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/VersionConverter.cs b/Libs/JsonNet/Converters/VersionConverter.cs
new file mode 100644
index 0000000..3f512e4
--- /dev/null
+++ b/Libs/JsonNet/Converters/VersionConverter.cs
@@ -0,0 +1,106 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+ ///
+ /// Converts a to and from a string (e.g. "1.2.3.4").
+ ///
+ public class VersionConverter : JsonConverter
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ if (value == null)
+ {
+ writer.WriteNull();
+ }
+ else if (value is Version)
+ {
+ writer.WriteValue(value.ToString());
+ }
+ else
+ {
+ throw new JsonSerializationException("Expected Version object value");
+ }
+ }
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing property value of the JSON that is being converted.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return null;
+ }
+ else
+ {
+ if (reader.TokenType == JsonToken.String)
+ {
+ try
+ {
+ Version v = new Version((string)reader.Value);
+ return v;
+ }
+ catch (Exception ex)
+ {
+ throw JsonSerializationException.Create(reader, "Error parsing version string: {0}".FormatWith(CultureInfo.InvariantCulture, reader.Value), ex);
+ }
+ }
+ else
+ {
+ throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing version. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
+ }
+ }
+ }
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(Version);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Converters/XmlNodeConverter.cs b/Libs/JsonNet/Converters/XmlNodeConverter.cs
new file mode 100644
index 0000000..402fb76
--- /dev/null
+++ b/Libs/JsonNet/Converters/XmlNodeConverter.cs
@@ -0,0 +1,1785 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !PORTABLE40
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Xml;
+#if !(NET20 || PORTABLE40)
+using System.Xml.Linq;
+#endif
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+
+namespace Newtonsoft.Json.Converters
+{
+ #region XmlNodeWrappers
+#if !NETFX_CORE && !PORTABLE && !PORTABLE40
+ internal class XmlDocumentWrapper : XmlNodeWrapper, IXmlDocument
+ {
+ private readonly XmlDocument _document;
+
+ public XmlDocumentWrapper(XmlDocument document)
+ : base(document)
+ {
+ _document = document;
+ }
+
+ public IXmlNode CreateComment(string data)
+ {
+ return new XmlNodeWrapper(_document.CreateComment(data));
+ }
+
+ public IXmlNode CreateTextNode(string text)
+ {
+ return new XmlNodeWrapper(_document.CreateTextNode(text));
+ }
+
+ public IXmlNode CreateCDataSection(string data)
+ {
+ return new XmlNodeWrapper(_document.CreateCDataSection(data));
+ }
+
+ public IXmlNode CreateWhitespace(string text)
+ {
+ return new XmlNodeWrapper(_document.CreateWhitespace(text));
+ }
+
+ public IXmlNode CreateSignificantWhitespace(string text)
+ {
+ return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text));
+ }
+
+ public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
+ {
+ return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone));
+ }
+
+ public IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset)
+ {
+ return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null));
+ }
+
+ public IXmlNode CreateProcessingInstruction(string target, string data)
+ {
+ return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data));
+ }
+
+ public IXmlElement CreateElement(string elementName)
+ {
+ return new XmlElementWrapper(_document.CreateElement(elementName));
+ }
+
+ public IXmlElement CreateElement(string qualifiedName, string namespaceUri)
+ {
+ return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri));
+ }
+
+ public IXmlNode CreateAttribute(string name, string value)
+ {
+ XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(name));
+ attribute.Value = value;
+
+ return attribute;
+ }
+
+ public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value)
+ {
+ XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri));
+ attribute.Value = value;
+
+ return attribute;
+ }
+
+ public IXmlElement DocumentElement
+ {
+ get
+ {
+ if (_document.DocumentElement == null)
+ return null;
+
+ return new XmlElementWrapper(_document.DocumentElement);
+ }
+ }
+ }
+
+ internal class XmlElementWrapper : XmlNodeWrapper, IXmlElement
+ {
+ private readonly XmlElement _element;
+
+ public XmlElementWrapper(XmlElement element)
+ : base(element)
+ {
+ _element = element;
+ }
+
+ public void SetAttributeNode(IXmlNode attribute)
+ {
+ XmlNodeWrapper xmlAttributeWrapper = (XmlNodeWrapper)attribute;
+
+ _element.SetAttributeNode((XmlAttribute)xmlAttributeWrapper.WrappedNode);
+ }
+
+ public string GetPrefixOfNamespace(string namespaceUri)
+ {
+ return _element.GetPrefixOfNamespace(namespaceUri);
+ }
+
+ public bool IsEmpty
+ {
+ get { return _element.IsEmpty; }
+ }
+ }
+
+ internal class XmlDeclarationWrapper : XmlNodeWrapper, IXmlDeclaration
+ {
+ private readonly XmlDeclaration _declaration;
+
+ public XmlDeclarationWrapper(XmlDeclaration declaration)
+ : base(declaration)
+ {
+ _declaration = declaration;
+ }
+
+ public string Version
+ {
+ get { return _declaration.Version; }
+ }
+
+ public string Encoding
+ {
+ get { return _declaration.Encoding; }
+ set { _declaration.Encoding = value; }
+ }
+
+ public string Standalone
+ {
+ get { return _declaration.Standalone; }
+ set { _declaration.Standalone = value; }
+ }
+ }
+
+ internal class XmlDocumentTypeWrapper : XmlNodeWrapper, IXmlDocumentType
+ {
+ private readonly XmlDocumentType _documentType;
+
+ public XmlDocumentTypeWrapper(XmlDocumentType documentType)
+ : base(documentType)
+ {
+ _documentType = documentType;
+ }
+
+ public string Name
+ {
+ get { return _documentType.Name; }
+ }
+
+ public string System
+ {
+ get { return _documentType.SystemId; }
+ }
+
+ public string Public
+ {
+ get { return _documentType.PublicId; }
+ }
+
+ public string InternalSubset
+ {
+ get { return _documentType.InternalSubset; }
+ }
+
+ public override string LocalName
+ {
+ get { return "DOCTYPE"; }
+ }
+ }
+
+ internal class XmlNodeWrapper : IXmlNode
+ {
+ private readonly XmlNode _node;
+ private IList _childNodes;
+
+ public XmlNodeWrapper(XmlNode node)
+ {
+ _node = node;
+ }
+
+ public object WrappedNode
+ {
+ get { return _node; }
+ }
+
+ public XmlNodeType NodeType
+ {
+ get { return _node.NodeType; }
+ }
+
+ public virtual string LocalName
+ {
+ get { return _node.LocalName; }
+ }
+
+ public IList ChildNodes
+ {
+ get
+ {
+ // childnodes is read multiple times
+ // cache results to prevent multiple reads which kills perf in large documents
+ if (_childNodes == null)
+ _childNodes = _node.ChildNodes.Cast().Select(WrapNode).ToList();
+
+ return _childNodes;
+ }
+ }
+
+ internal static IXmlNode WrapNode(XmlNode node)
+ {
+ switch (node.NodeType)
+ {
+ case XmlNodeType.Element:
+ return new XmlElementWrapper((XmlElement) node);
+ case XmlNodeType.XmlDeclaration:
+ return new XmlDeclarationWrapper((XmlDeclaration) node);
+ case XmlNodeType.DocumentType:
+ return new XmlDocumentTypeWrapper((XmlDocumentType) node);
+ default:
+ return new XmlNodeWrapper(node);
+ }
+ }
+
+ public IList Attributes
+ {
+ get
+ {
+ if (_node.Attributes == null)
+ return null;
+
+ return _node.Attributes.Cast().Select(WrapNode).ToList();
+ }
+ }
+
+ public IXmlNode ParentNode
+ {
+ get
+ {
+ XmlNode node = (_node is XmlAttribute)
+ ? ((XmlAttribute) _node).OwnerElement
+ : _node.ParentNode;
+
+ if (node == null)
+ return null;
+
+ return WrapNode(node);
+ }
+ }
+
+ public string Value
+ {
+ get { return _node.Value; }
+ set { _node.Value = value; }
+ }
+
+ public IXmlNode AppendChild(IXmlNode newChild)
+ {
+ XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper) newChild;
+ _node.AppendChild(xmlNodeWrapper._node);
+ _childNodes = null;
+
+ return newChild;
+ }
+
+ public string NamespaceUri
+ {
+ get { return _node.NamespaceURI; }
+ }
+ }
+#endif
+ #endregion
+
+ #region Interfaces
+ internal interface IXmlDocument : IXmlNode
+ {
+ IXmlNode CreateComment(string text);
+ IXmlNode CreateTextNode(string text);
+ IXmlNode CreateCDataSection(string data);
+ IXmlNode CreateWhitespace(string text);
+ IXmlNode CreateSignificantWhitespace(string text);
+ IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone);
+ IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset);
+ IXmlNode CreateProcessingInstruction(string target, string data);
+ IXmlElement CreateElement(string elementName);
+ IXmlElement CreateElement(string qualifiedName, string namespaceUri);
+ IXmlNode CreateAttribute(string name, string value);
+ IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value);
+
+ IXmlElement DocumentElement { get; }
+ }
+
+ internal interface IXmlDeclaration : IXmlNode
+ {
+ string Version { get; }
+ string Encoding { get; set; }
+ string Standalone { get; set; }
+ }
+
+ internal interface IXmlDocumentType : IXmlNode
+ {
+ string Name { get; }
+ string System { get; }
+ string Public { get; }
+ string InternalSubset { get; }
+ }
+
+ internal interface IXmlElement : IXmlNode
+ {
+ void SetAttributeNode(IXmlNode attribute);
+ string GetPrefixOfNamespace(string namespaceUri);
+ bool IsEmpty { get; }
+ }
+
+ internal interface IXmlNode
+ {
+ XmlNodeType NodeType { get; }
+ string LocalName { get; }
+ IList ChildNodes { get; }
+ IList Attributes { get; }
+ IXmlNode ParentNode { get; }
+ string Value { get; set; }
+ IXmlNode AppendChild(IXmlNode newChild);
+ string NamespaceUri { get; }
+ object WrappedNode { get; }
+ }
+ #endregion
+
+ #region XNodeWrappers
+#if !NET20
+ internal class XDeclarationWrapper : XObjectWrapper, IXmlDeclaration
+ {
+ internal XDeclaration Declaration { get; private set; }
+
+ public XDeclarationWrapper(XDeclaration declaration)
+ : base(null)
+ {
+ Declaration = declaration;
+ }
+
+ public override XmlNodeType NodeType
+ {
+ get { return XmlNodeType.XmlDeclaration; }
+ }
+
+ public string Version
+ {
+ get { return Declaration.Version; }
+ }
+
+ public string Encoding
+ {
+ get { return Declaration.Encoding; }
+ set { Declaration.Encoding = value; }
+ }
+
+ public string Standalone
+ {
+ get { return Declaration.Standalone; }
+ set { Declaration.Standalone = value; }
+ }
+ }
+
+ internal class XDocumentTypeWrapper : XObjectWrapper, IXmlDocumentType
+ {
+ private readonly XDocumentType _documentType;
+
+ public XDocumentTypeWrapper(XDocumentType documentType)
+ : base(documentType)
+ {
+ _documentType = documentType;
+ }
+
+ public string Name
+ {
+ get { return _documentType.Name; }
+ }
+
+ public string System
+ {
+ get { return _documentType.SystemId; }
+ }
+
+ public string Public
+ {
+ get { return _documentType.PublicId; }
+ }
+
+ public string InternalSubset
+ {
+ get { return _documentType.InternalSubset; }
+ }
+
+ public override string LocalName
+ {
+ get { return "DOCTYPE"; }
+ }
+ }
+
+ internal class XDocumentWrapper : XContainerWrapper, IXmlDocument
+ {
+ private XDocument Document
+ {
+ get { return (XDocument)WrappedNode; }
+ }
+
+ public XDocumentWrapper(XDocument document)
+ : base(document)
+ {
+ }
+
+ public override IList ChildNodes
+ {
+ get
+ {
+ IList childNodes = base.ChildNodes;
+
+ if (Document.Declaration != null && childNodes[0].NodeType != XmlNodeType.XmlDeclaration)
+ childNodes.Insert(0, new XDeclarationWrapper(Document.Declaration));
+
+ return childNodes;
+ }
+ }
+
+ public IXmlNode CreateComment(string text)
+ {
+ return new XObjectWrapper(new XComment(text));
+ }
+
+ public IXmlNode CreateTextNode(string text)
+ {
+ return new XObjectWrapper(new XText(text));
+ }
+
+ public IXmlNode CreateCDataSection(string data)
+ {
+ return new XObjectWrapper(new XCData(data));
+ }
+
+ public IXmlNode CreateWhitespace(string text)
+ {
+ return new XObjectWrapper(new XText(text));
+ }
+
+ public IXmlNode CreateSignificantWhitespace(string text)
+ {
+ return new XObjectWrapper(new XText(text));
+ }
+
+ public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
+ {
+ return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone));
+ }
+
+ public IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset)
+ {
+ return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset));
+ }
+
+ public IXmlNode CreateProcessingInstruction(string target, string data)
+ {
+ return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data));
+ }
+
+ public IXmlElement CreateElement(string elementName)
+ {
+ return new XElementWrapper(new XElement(elementName));
+ }
+
+ public IXmlElement CreateElement(string qualifiedName, string namespaceUri)
+ {
+ string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
+ return new XElementWrapper(new XElement(XName.Get(localName, namespaceUri)));
+ }
+
+ public IXmlNode CreateAttribute(string name, string value)
+ {
+ return new XAttributeWrapper(new XAttribute(name, value));
+ }
+
+ public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value)
+ {
+ string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
+ return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceUri), value));
+ }
+
+ public IXmlElement DocumentElement
+ {
+ get
+ {
+ if (Document.Root == null)
+ return null;
+
+ return new XElementWrapper(Document.Root);
+ }
+ }
+
+ public override IXmlNode AppendChild(IXmlNode newChild)
+ {
+ XDeclarationWrapper declarationWrapper = newChild as XDeclarationWrapper;
+ if (declarationWrapper != null)
+ {
+ Document.Declaration = declarationWrapper.Declaration;
+ return declarationWrapper;
+ }
+ else
+ {
+ return base.AppendChild(newChild);
+ }
+ }
+ }
+
+ internal class XTextWrapper : XObjectWrapper
+ {
+ private XText Text
+ {
+ get { return (XText)WrappedNode; }
+ }
+
+ public XTextWrapper(XText text)
+ : base(text)
+ {
+ }
+
+ public override string Value
+ {
+ get { return Text.Value; }
+ set { Text.Value = value; }
+ }
+
+ public override IXmlNode ParentNode
+ {
+ get
+ {
+ if (Text.Parent == null)
+ return null;
+
+ return XContainerWrapper.WrapNode(Text.Parent);
+ }
+ }
+ }
+
+ internal class XCommentWrapper : XObjectWrapper
+ {
+ private XComment Text
+ {
+ get { return (XComment)WrappedNode; }
+ }
+
+ public XCommentWrapper(XComment text)
+ : base(text)
+ {
+ }
+
+ public override string Value
+ {
+ get { return Text.Value; }
+ set { Text.Value = value; }
+ }
+
+ public override IXmlNode ParentNode
+ {
+ get
+ {
+ if (Text.Parent == null)
+ return null;
+
+ return XContainerWrapper.WrapNode(Text.Parent);
+ }
+ }
+ }
+
+ internal class XProcessingInstructionWrapper : XObjectWrapper
+ {
+ private XProcessingInstruction ProcessingInstruction
+ {
+ get { return (XProcessingInstruction)WrappedNode; }
+ }
+
+ public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction)
+ : base(processingInstruction)
+ {
+ }
+
+ public override string LocalName
+ {
+ get { return ProcessingInstruction.Target; }
+ }
+
+ public override string Value
+ {
+ get { return ProcessingInstruction.Data; }
+ set { ProcessingInstruction.Data = value; }
+ }
+ }
+
+ internal class XContainerWrapper : XObjectWrapper
+ {
+ private IList _childNodes;
+
+ private XContainer Container
+ {
+ get { return (XContainer)WrappedNode; }
+ }
+
+ public XContainerWrapper(XContainer container)
+ : base(container)
+ {
+ }
+
+ public override IList ChildNodes
+ {
+ get
+ {
+ // childnodes is read multiple times
+ // cache results to prevent multiple reads which kills perf in large documents
+ if (_childNodes == null)
+ _childNodes = Container.Nodes().Select(WrapNode).ToList();
+
+ return _childNodes;
+ }
+ }
+
+ public override IXmlNode ParentNode
+ {
+ get
+ {
+ if (Container.Parent == null)
+ return null;
+
+ return WrapNode(Container.Parent);
+ }
+ }
+
+ internal static IXmlNode WrapNode(XObject node)
+ {
+ if (node is XDocument)
+ return new XDocumentWrapper((XDocument)node);
+ else if (node is XElement)
+ return new XElementWrapper((XElement)node);
+ else if (node is XContainer)
+ return new XContainerWrapper((XContainer)node);
+ else if (node is XProcessingInstruction)
+ return new XProcessingInstructionWrapper((XProcessingInstruction)node);
+ else if (node is XText)
+ return new XTextWrapper((XText)node);
+ else if (node is XComment)
+ return new XCommentWrapper((XComment)node);
+ else if (node is XAttribute)
+ return new XAttributeWrapper((XAttribute)node);
+ else if (node is XDocumentType)
+ return new XDocumentTypeWrapper((XDocumentType)node);
+ else
+ return new XObjectWrapper(node);
+ }
+
+ public override IXmlNode AppendChild(IXmlNode newChild)
+ {
+ Container.Add(newChild.WrappedNode);
+ _childNodes = null;
+
+ return newChild;
+ }
+ }
+
+ internal class XObjectWrapper : IXmlNode
+ {
+ private readonly XObject _xmlObject;
+
+ public XObjectWrapper(XObject xmlObject)
+ {
+ _xmlObject = xmlObject;
+ }
+
+ public object WrappedNode
+ {
+ get { return _xmlObject; }
+ }
+
+ public virtual XmlNodeType NodeType
+ {
+ get { return _xmlObject.NodeType; }
+ }
+
+ public virtual string LocalName
+ {
+ get { return null; }
+ }
+
+ public virtual IList ChildNodes
+ {
+ get { return new List(); }
+ }
+
+ public virtual IList Attributes
+ {
+ get { return null; }
+ }
+
+ public virtual IXmlNode ParentNode
+ {
+ get { return null; }
+ }
+
+ public virtual string Value
+ {
+ get { return null; }
+ set { throw new InvalidOperationException(); }
+ }
+
+ public virtual IXmlNode AppendChild(IXmlNode newChild)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public virtual string NamespaceUri
+ {
+ get { return null; }
+ }
+ }
+
+ internal class XAttributeWrapper : XObjectWrapper
+ {
+ private XAttribute Attribute
+ {
+ get { return (XAttribute)WrappedNode; }
+ }
+
+ public XAttributeWrapper(XAttribute attribute)
+ : base(attribute)
+ {
+ }
+
+ public override string Value
+ {
+ get { return Attribute.Value; }
+ set { Attribute.Value = value; }
+ }
+
+ public override string LocalName
+ {
+ get { return Attribute.Name.LocalName; }
+ }
+
+ public override string NamespaceUri
+ {
+ get { return Attribute.Name.NamespaceName; }
+ }
+
+ public override IXmlNode ParentNode
+ {
+ get
+ {
+ if (Attribute.Parent == null)
+ return null;
+
+ return XContainerWrapper.WrapNode(Attribute.Parent);
+ }
+ }
+ }
+
+ internal class XElementWrapper : XContainerWrapper, IXmlElement
+ {
+ private XElement Element
+ {
+ get { return (XElement)WrappedNode; }
+ }
+
+ public XElementWrapper(XElement element)
+ : base(element)
+ {
+ }
+
+ public void SetAttributeNode(IXmlNode attribute)
+ {
+ XObjectWrapper wrapper = (XObjectWrapper)attribute;
+ Element.Add(wrapper.WrappedNode);
+ }
+
+ public override IList Attributes
+ {
+ get { return Element.Attributes().Select(a => new XAttributeWrapper(a)).Cast().ToList(); }
+ }
+
+ public override string Value
+ {
+ get { return Element.Value; }
+ set { Element.Value = value; }
+ }
+
+ public override string LocalName
+ {
+ get { return Element.Name.LocalName; }
+ }
+
+ public override string NamespaceUri
+ {
+ get { return Element.Name.NamespaceName; }
+ }
+
+ public string GetPrefixOfNamespace(string namespaceUri)
+ {
+ return Element.GetPrefixOfNamespace(namespaceUri);
+ }
+
+ public bool IsEmpty
+ {
+ get { return Element.IsEmpty; }
+ }
+ }
+#endif
+ #endregion
+
+ ///
+ /// Converts XML to and from JSON.
+ ///
+ public class XmlNodeConverter : JsonConverter
+ {
+ private const string TextName = "#text";
+ private const string CommentName = "#comment";
+ private const string CDataName = "#cdata-section";
+ private const string WhitespaceName = "#whitespace";
+ private const string SignificantWhitespaceName = "#significant-whitespace";
+ private const string DeclarationName = "?xml";
+ private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json";
+
+ ///
+ /// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements.
+ ///
+ /// The name of the deserialize root element.
+ public string DeserializeRootElementName { get; set; }
+
+ ///
+ /// Gets or sets a flag to indicate whether to write the Json.NET array attribute.
+ /// This attribute helps preserve arrays when converting the written XML back to JSON.
+ ///
+ /// true if the array attibute is written to the XML; otherwise, false .
+ public bool WriteArrayAttribute { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to write the root JSON object.
+ ///
+ /// true if the JSON root object is omitted; otherwise, false .
+ public bool OmitRootObject { get; set; }
+
+ #region Writing
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The calling serializer.
+ /// The value.
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ IXmlNode node = WrapXml(value);
+
+ XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
+ PushParentNamespaces(node, manager);
+
+ if (!OmitRootObject)
+ writer.WriteStartObject();
+
+ SerializeNode(writer, node, manager, !OmitRootObject);
+
+ if (!OmitRootObject)
+ writer.WriteEndObject();
+ }
+
+ private IXmlNode WrapXml(object value)
+ {
+#if !NET20
+ if (value is XObject)
+ return XContainerWrapper.WrapNode((XObject)value);
+#endif
+#if !(NETFX_CORE || PORTABLE)
+ if (value is XmlNode)
+ return XmlNodeWrapper.WrapNode((XmlNode)value);
+#endif
+
+ throw new ArgumentException("Value must be an XML object.", "value");
+ }
+
+ private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager)
+ {
+ List parentElements = null;
+
+ IXmlNode parent = node;
+ while ((parent = parent.ParentNode) != null)
+ {
+ if (parent.NodeType == XmlNodeType.Element)
+ {
+ if (parentElements == null)
+ parentElements = new List();
+
+ parentElements.Add(parent);
+ }
+ }
+
+ if (parentElements != null)
+ {
+ parentElements.Reverse();
+
+ foreach (IXmlNode parentElement in parentElements)
+ {
+ manager.PushScope();
+ foreach (IXmlNode attribute in parentElement.Attributes)
+ {
+ if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns")
+ manager.AddNamespace(attribute.LocalName, attribute.Value);
+ }
+ }
+ }
+ }
+
+ private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager)
+ {
+ string prefix = (node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/"))
+ ? null
+ : manager.LookupPrefix(node.NamespaceUri);
+
+ if (!string.IsNullOrEmpty(prefix))
+ return prefix + ":" + node.LocalName;
+ else
+ return node.LocalName;
+ }
+
+ private string GetPropertyName(IXmlNode node, XmlNamespaceManager manager)
+ {
+ switch (node.NodeType)
+ {
+ case XmlNodeType.Attribute:
+ if (node.NamespaceUri == JsonNamespaceUri)
+ return "$" + node.LocalName;
+ else
+ return "@" + ResolveFullName(node, manager);
+ case XmlNodeType.CDATA:
+ return CDataName;
+ case XmlNodeType.Comment:
+ return CommentName;
+ case XmlNodeType.Element:
+ return ResolveFullName(node, manager);
+ case XmlNodeType.ProcessingInstruction:
+ return "?" + ResolveFullName(node, manager);
+ case XmlNodeType.DocumentType:
+ return "!" + ResolveFullName(node, manager);
+ case XmlNodeType.XmlDeclaration:
+ return DeclarationName;
+ case XmlNodeType.SignificantWhitespace:
+ return SignificantWhitespaceName;
+ case XmlNodeType.Text:
+ return TextName;
+ case XmlNodeType.Whitespace:
+ return WhitespaceName;
+ default:
+ throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType);
+ }
+ }
+
+ private bool IsArray(IXmlNode node)
+ {
+ IXmlNode jsonArrayAttribute = (node.Attributes != null)
+ ? node.Attributes.SingleOrDefault(a => a.LocalName == "Array" && a.NamespaceUri == JsonNamespaceUri)
+ : null;
+
+ return (jsonArrayAttribute != null && XmlConvert.ToBoolean(jsonArrayAttribute.Value));
+ }
+
+ private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
+ {
+ // group nodes together by name
+ Dictionary> nodesGroupedByName = new Dictionary>();
+
+ for (int i = 0; i < node.ChildNodes.Count; i++)
+ {
+ IXmlNode childNode = node.ChildNodes[i];
+ string nodeName = GetPropertyName(childNode, manager);
+
+ List nodes;
+ if (!nodesGroupedByName.TryGetValue(nodeName, out nodes))
+ {
+ nodes = new List();
+ nodesGroupedByName.Add(nodeName, nodes);
+ }
+
+ nodes.Add(childNode);
+ }
+
+ // loop through grouped nodes. write single name instances as normal,
+ // write multiple names together in an array
+ foreach (KeyValuePair> nodeNameGroup in nodesGroupedByName)
+ {
+ List groupedNodes = nodeNameGroup.Value;
+ bool writeArray;
+
+ if (groupedNodes.Count == 1)
+ {
+ writeArray = IsArray(groupedNodes[0]);
+ }
+ else
+ {
+ writeArray = true;
+ }
+
+ if (!writeArray)
+ {
+ SerializeNode(writer, groupedNodes[0], manager, writePropertyName);
+ }
+ else
+ {
+ string elementNames = nodeNameGroup.Key;
+
+ if (writePropertyName)
+ writer.WritePropertyName(elementNames);
+
+ writer.WriteStartArray();
+
+ for (int i = 0; i < groupedNodes.Count; i++)
+ {
+ SerializeNode(writer, groupedNodes[i], manager, false);
+ }
+
+ writer.WriteEndArray();
+ }
+ }
+ }
+
+ private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
+ {
+ switch (node.NodeType)
+ {
+ case XmlNodeType.Document:
+ case XmlNodeType.DocumentFragment:
+ SerializeGroupedNodes(writer, node, manager, writePropertyName);
+ break;
+ case XmlNodeType.Element:
+ if (IsArray(node) && node.ChildNodes.All(n => n.LocalName == node.LocalName) && node.ChildNodes.Count > 0)
+ {
+ SerializeGroupedNodes(writer, node, manager, false);
+ }
+ else
+ {
+ manager.PushScope();
+
+ foreach (IXmlNode attribute in node.Attributes)
+ {
+ if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/")
+ {
+ string namespacePrefix = (attribute.LocalName != "xmlns")
+ ? attribute.LocalName
+ : string.Empty;
+ string namespaceUri = attribute.Value;
+
+ manager.AddNamespace(namespacePrefix, namespaceUri);
+ }
+ }
+
+ if (writePropertyName)
+ writer.WritePropertyName(GetPropertyName(node, manager));
+
+ if (!ValueAttributes(node.Attributes).Any() && node.ChildNodes.Count == 1
+ && node.ChildNodes[0].NodeType == XmlNodeType.Text)
+ {
+ // write elements with a single text child as a name value pair
+ writer.WriteValue(node.ChildNodes[0].Value);
+ }
+ else if (node.ChildNodes.Count == 0 && CollectionUtils.IsNullOrEmpty(node.Attributes))
+ {
+ IXmlElement element = (IXmlElement)node;
+
+ // empty element
+ if (element.IsEmpty)
+ writer.WriteNull();
+ else
+ writer.WriteValue(string.Empty);
+ }
+ else
+ {
+ writer.WriteStartObject();
+
+ for (int i = 0; i < node.Attributes.Count; i++)
+ {
+ SerializeNode(writer, node.Attributes[i], manager, true);
+ }
+
+ SerializeGroupedNodes(writer, node, manager, true);
+
+ writer.WriteEndObject();
+ }
+
+ manager.PopScope();
+ }
+
+ break;
+ case XmlNodeType.Comment:
+ if (writePropertyName)
+ writer.WriteComment(node.Value);
+ break;
+ case XmlNodeType.Attribute:
+ case XmlNodeType.Text:
+ case XmlNodeType.CDATA:
+ case XmlNodeType.ProcessingInstruction:
+ case XmlNodeType.Whitespace:
+ case XmlNodeType.SignificantWhitespace:
+ if (node.NamespaceUri == "http://www.w3.org/2000/xmlns/" && node.Value == JsonNamespaceUri)
+ return;
+
+ if (node.NamespaceUri == JsonNamespaceUri)
+ {
+ if (node.LocalName == "Array")
+ return;
+ }
+
+ if (writePropertyName)
+ writer.WritePropertyName(GetPropertyName(node, manager));
+ writer.WriteValue(node.Value);
+ break;
+ case XmlNodeType.XmlDeclaration:
+ IXmlDeclaration declaration = (IXmlDeclaration)node;
+ writer.WritePropertyName(GetPropertyName(node, manager));
+ writer.WriteStartObject();
+
+ if (!string.IsNullOrEmpty(declaration.Version))
+ {
+ writer.WritePropertyName("@version");
+ writer.WriteValue(declaration.Version);
+ }
+ if (!string.IsNullOrEmpty(declaration.Encoding))
+ {
+ writer.WritePropertyName("@encoding");
+ writer.WriteValue(declaration.Encoding);
+ }
+ if (!string.IsNullOrEmpty(declaration.Standalone))
+ {
+ writer.WritePropertyName("@standalone");
+ writer.WriteValue(declaration.Standalone);
+ }
+
+ writer.WriteEndObject();
+ break;
+ case XmlNodeType.DocumentType:
+ IXmlDocumentType documentType = (IXmlDocumentType)node;
+ writer.WritePropertyName(GetPropertyName(node, manager));
+ writer.WriteStartObject();
+
+ if (!string.IsNullOrEmpty(documentType.Name))
+ {
+ writer.WritePropertyName("@name");
+ writer.WriteValue(documentType.Name);
+ }
+ if (!string.IsNullOrEmpty(documentType.Public))
+ {
+ writer.WritePropertyName("@public");
+ writer.WriteValue(documentType.Public);
+ }
+ if (!string.IsNullOrEmpty(documentType.System))
+ {
+ writer.WritePropertyName("@system");
+ writer.WriteValue(documentType.System);
+ }
+ if (!string.IsNullOrEmpty(documentType.InternalSubset))
+ {
+ writer.WritePropertyName("@internalSubset");
+ writer.WriteValue(documentType.InternalSubset);
+ }
+
+ writer.WriteEndObject();
+ break;
+ default:
+ throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType);
+ }
+ }
+ #endregion
+
+ #region Reading
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ return null;
+
+ XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
+ IXmlDocument document = null;
+ IXmlNode rootNode = null;
+
+#if !NET20
+ if (typeof(XObject).IsAssignableFrom(objectType))
+ {
+ if (objectType != typeof(XDocument) && objectType != typeof(XElement))
+ throw new JsonSerializationException("XmlNodeConverter only supports deserializing XDocument or XElement.");
+
+ XDocument d = new XDocument();
+ document = new XDocumentWrapper(d);
+ rootNode = document;
+ }
+#endif
+#if !(NETFX_CORE || PORTABLE)
+ if (typeof(XmlNode).IsAssignableFrom(objectType))
+ {
+ if (objectType != typeof(XmlDocument))
+ throw new JsonSerializationException("XmlNodeConverter only supports deserializing XmlDocuments");
+
+ XmlDocument d = new XmlDocument();
+ // prevent http request when resolving any DTD references
+ d.XmlResolver = null;
+
+ document = new XmlDocumentWrapper(d);
+ rootNode = document;
+ }
+#endif
+
+ if (document == null || rootNode == null)
+ throw new JsonSerializationException("Unexpected type when converting XML: " + objectType);
+
+ if (reader.TokenType != JsonToken.StartObject)
+ throw new JsonSerializationException("XmlNodeConverter can only convert JSON that begins with an object.");
+
+ if (!string.IsNullOrEmpty(DeserializeRootElementName))
+ {
+ //rootNode = document.CreateElement(DeserializeRootElementName);
+ //document.AppendChild(rootNode);
+ ReadElement(reader, document, rootNode, DeserializeRootElementName, manager);
+ }
+ else
+ {
+ reader.Read();
+ DeserializeNode(reader, document, manager, rootNode);
+ }
+
+#if !NET20
+ if (objectType == typeof(XElement))
+ {
+ XElement element = (XElement)document.DocumentElement.WrappedNode;
+ element.Remove();
+
+ return element;
+ }
+#endif
+
+ return document.WrappedNode;
+ }
+
+ private void DeserializeValue(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, string propertyName, IXmlNode currentNode)
+ {
+ switch (propertyName)
+ {
+ case TextName:
+ currentNode.AppendChild(document.CreateTextNode(reader.Value.ToString()));
+ break;
+ case CDataName:
+ currentNode.AppendChild(document.CreateCDataSection(reader.Value.ToString()));
+ break;
+ case WhitespaceName:
+ currentNode.AppendChild(document.CreateWhitespace(reader.Value.ToString()));
+ break;
+ case SignificantWhitespaceName:
+ currentNode.AppendChild(document.CreateSignificantWhitespace(reader.Value.ToString()));
+ break;
+ default:
+ // processing instructions and the xml declaration start with ?
+ if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
+ {
+ CreateInstruction(reader, document, currentNode, propertyName);
+ }
+ else if (string.Equals(propertyName, "!DOCTYPE", StringComparison.OrdinalIgnoreCase))
+ {
+ CreateDocumentType(reader, document, currentNode);
+ }
+ else
+ {
+ if (reader.TokenType == JsonToken.StartArray)
+ {
+ // handle nested arrays
+ ReadArrayElements(reader, document, propertyName, currentNode, manager);
+ return;
+ }
+
+ // have to wait until attributes have been parsed before creating element
+ // attributes may contain namespace info used by the element
+ ReadElement(reader, document, currentNode, propertyName, manager);
+ }
+ break;
+ }
+ }
+
+ private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
+ {
+ if (string.IsNullOrEmpty(propertyName))
+ throw new JsonSerializationException("XmlNodeConverter cannot convert JSON with an empty property name to XML.");
+
+ Dictionary attributeNameValues = ReadAttributeElements(reader, manager);
+
+ string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
+
+ if (propertyName.StartsWith('@'))
+ {
+ string attributeName = propertyName.Substring(1);
+ string attributeValue = reader.Value.ToString();
+
+ string attributePrefix = MiscellaneousUtils.GetPrefix(attributeName);
+
+ IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
+ ? document.CreateAttribute(attributeName, manager.LookupNamespace(attributePrefix), attributeValue)
+ : document.CreateAttribute(attributeName, attributeValue);
+
+ ((IXmlElement)currentNode).SetAttributeNode(attribute);
+ }
+ else
+ {
+ IXmlElement element = CreateElement(propertyName, document, elementPrefix, manager);
+
+ currentNode.AppendChild(element);
+
+ // add attributes to newly created element
+ foreach (KeyValuePair nameValue in attributeNameValues)
+ {
+ string attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key);
+
+ IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
+ ? document.CreateAttribute(nameValue.Key, manager.LookupNamespace(attributePrefix), nameValue.Value)
+ : document.CreateAttribute(nameValue.Key, nameValue.Value);
+
+ element.SetAttributeNode(attribute);
+ }
+
+ if (reader.TokenType == JsonToken.String
+ || reader.TokenType == JsonToken.Integer
+ || reader.TokenType == JsonToken.Float
+ || reader.TokenType == JsonToken.Boolean
+ || reader.TokenType == JsonToken.Date)
+ {
+ element.AppendChild(document.CreateTextNode(ConvertTokenToXmlValue(reader)));
+ }
+ else if (reader.TokenType == JsonToken.Null)
+ {
+ // empty element. do nothing
+ }
+ else
+ {
+ // finished element will have no children to deserialize
+ if (reader.TokenType != JsonToken.EndObject)
+ {
+ manager.PushScope();
+ DeserializeNode(reader, document, manager, element);
+ manager.PopScope();
+ }
+
+ manager.RemoveNamespace(string.Empty, manager.DefaultNamespace);
+ }
+ }
+ }
+
+ private string ConvertTokenToXmlValue(JsonReader reader)
+ {
+ if (reader.TokenType == JsonToken.String)
+ {
+ return reader.Value.ToString();
+ }
+ else if (reader.TokenType == JsonToken.Integer)
+ {
+ return XmlConvert.ToString(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture));
+ }
+ else if (reader.TokenType == JsonToken.Float)
+ {
+ if (reader.Value is decimal)
+ return XmlConvert.ToString((decimal)reader.Value);
+ if (reader.Value is float)
+ return XmlConvert.ToString((float)reader.Value);
+
+ return XmlConvert.ToString(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture));
+ }
+ else if (reader.TokenType == JsonToken.Boolean)
+ {
+ return XmlConvert.ToString(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
+ }
+ else if (reader.TokenType == JsonToken.Date)
+ {
+#if !NET20
+ if (reader.Value is DateTimeOffset)
+ return XmlConvert.ToString((DateTimeOffset)reader.Value);
+#endif
+
+ DateTime d = Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture);
+#if !(NETFX_CORE || PORTABLE)
+ return XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind));
+#else
+ return XmlConvert.ToString(d);
+#endif
+ }
+ else if (reader.TokenType == JsonToken.Null)
+ {
+ return null;
+ }
+ else
+ {
+ throw JsonSerializationException.Create(reader, "Cannot get an XML string value from token type '{0}'.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+ }
+ }
+
+ private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager)
+ {
+ string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
+
+ IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager);
+
+ currentNode.AppendChild(nestedArrayElement);
+
+ int count = 0;
+ while (reader.Read() && reader.TokenType != JsonToken.EndArray)
+ {
+ DeserializeValue(reader, document, manager, propertyName, nestedArrayElement);
+ count++;
+ }
+
+ if (WriteArrayAttribute)
+ {
+ AddJsonArrayAttribute(nestedArrayElement, document);
+ }
+
+ if (count == 1 && WriteArrayAttribute)
+ {
+ IXmlElement arrayElement = nestedArrayElement.ChildNodes.OfType().Single(n => n.LocalName == propertyName);
+ AddJsonArrayAttribute(arrayElement, document);
+ }
+ }
+
+ private void AddJsonArrayAttribute(IXmlElement element, IXmlDocument document)
+ {
+ element.SetAttributeNode(document.CreateAttribute("json:Array", JsonNamespaceUri, "true"));
+
+#if !NET20
+ // linq to xml doesn't automatically include prefixes via the namespace manager
+ if (element is XElementWrapper)
+ {
+ if (element.GetPrefixOfNamespace(JsonNamespaceUri) == null)
+ {
+ element.SetAttributeNode(document.CreateAttribute("xmlns:json", "http://www.w3.org/2000/xmlns/", JsonNamespaceUri));
+ }
+ }
+#endif
+ }
+
+ private Dictionary ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)
+ {
+ Dictionary attributeNameValues = new Dictionary();
+ bool finishedAttributes = false;
+ bool finishedElement = false;
+
+ // a string token means the element only has a single text child
+ if (reader.TokenType != JsonToken.String
+ && reader.TokenType != JsonToken.Null
+ && reader.TokenType != JsonToken.Boolean
+ && reader.TokenType != JsonToken.Integer
+ && reader.TokenType != JsonToken.Float
+ && reader.TokenType != JsonToken.Date
+ && reader.TokenType != JsonToken.StartConstructor)
+ {
+ // read properties until first non-attribute is encountered
+ while (!finishedAttributes && !finishedElement && reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ string attributeName = reader.Value.ToString();
+
+ if (!string.IsNullOrEmpty(attributeName))
+ {
+ char firstChar = attributeName[0];
+ string attributeValue;
+
+ switch (firstChar)
+ {
+ case '@':
+ attributeName = attributeName.Substring(1);
+ reader.Read();
+ attributeValue = ConvertTokenToXmlValue(reader);
+ attributeNameValues.Add(attributeName, attributeValue);
+
+ string namespacePrefix;
+ if (IsNamespaceAttribute(attributeName, out namespacePrefix))
+ {
+ manager.AddNamespace(namespacePrefix, attributeValue);
+ }
+ break;
+ case '$':
+ attributeName = attributeName.Substring(1);
+ reader.Read();
+ attributeValue = reader.Value.ToString();
+
+ // check that JsonNamespaceUri is in scope
+ // if it isn't then add it to document and namespace manager
+ string jsonPrefix = manager.LookupPrefix(JsonNamespaceUri);
+ if (jsonPrefix == null)
+ {
+ // ensure that the prefix used is free
+ int? i = null;
+ while (manager.LookupNamespace("json" + i) != null)
+ {
+ i = i.GetValueOrDefault() + 1;
+ }
+ jsonPrefix = "json" + i;
+
+ attributeNameValues.Add("xmlns:" + jsonPrefix, JsonNamespaceUri);
+ manager.AddNamespace(jsonPrefix, JsonNamespaceUri);
+ }
+
+ attributeNameValues.Add(jsonPrefix + ":" + attributeName, attributeValue);
+ break;
+ default:
+ finishedAttributes = true;
+ break;
+ }
+ }
+ else
+ {
+
+ finishedAttributes = true;
+ }
+
+ break;
+ case JsonToken.EndObject:
+ finishedElement = true;
+ break;
+ case JsonToken.Comment:
+ finishedElement = true;
+ break;
+ default:
+ throw new JsonSerializationException("Unexpected JsonToken: " + reader.TokenType);
+ }
+ }
+ }
+
+ return attributeNameValues;
+ }
+
+ private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName)
+ {
+ if (propertyName == DeclarationName)
+ {
+ string version = null;
+ string encoding = null;
+ string standalone = null;
+ while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+ {
+ switch (reader.Value.ToString())
+ {
+ case "@version":
+ reader.Read();
+ version = reader.Value.ToString();
+ break;
+ case "@encoding":
+ reader.Read();
+ encoding = reader.Value.ToString();
+ break;
+ case "@standalone":
+ reader.Read();
+ standalone = reader.Value.ToString();
+ break;
+ default:
+ throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
+ }
+ }
+
+ IXmlNode declaration = document.CreateXmlDeclaration(version, encoding, standalone);
+ currentNode.AppendChild(declaration);
+ }
+ else
+ {
+ IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
+ currentNode.AppendChild(instruction);
+ }
+ }
+
+ private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode)
+ {
+ string name = null;
+ string publicId = null;
+ string systemId = null;
+ string internalSubset = null;
+ while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+ {
+ switch (reader.Value.ToString())
+ {
+ case "@name":
+ reader.Read();
+ name = reader.Value.ToString();
+ break;
+ case "@public":
+ reader.Read();
+ publicId = reader.Value.ToString();
+ break;
+ case "@system":
+ reader.Read();
+ systemId = reader.Value.ToString();
+ break;
+ case "@internalSubset":
+ reader.Read();
+ internalSubset = reader.Value.ToString();
+ break;
+ default:
+ throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
+ }
+ }
+
+ IXmlNode documentType = document.CreateXmlDocumentType(name, publicId, systemId, internalSubset);
+ currentNode.AppendChild(documentType);
+ }
+
+ private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager)
+ {
+ string ns = string.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix);
+
+ IXmlElement element = (!string.IsNullOrEmpty(ns)) ? document.CreateElement(elementName, ns) : document.CreateElement(elementName);
+
+ return element;
+ }
+
+ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode)
+ {
+ do
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null)
+ throw new JsonSerializationException("JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifing a DeserializeRootElementName.");
+
+ string propertyName = reader.Value.ToString();
+ reader.Read();
+
+ if (reader.TokenType == JsonToken.StartArray)
+ {
+ int count = 0;
+ while (reader.Read() && reader.TokenType != JsonToken.EndArray)
+ {
+ DeserializeValue(reader, document, manager, propertyName, currentNode);
+ count++;
+ }
+
+ if (count == 1 && WriteArrayAttribute)
+ {
+ IXmlElement arrayElement = currentNode.ChildNodes.OfType().Single(n => n.LocalName == propertyName);
+ AddJsonArrayAttribute(arrayElement, document);
+ }
+ }
+ else
+ {
+ DeserializeValue(reader, document, manager, propertyName, currentNode);
+ }
+ break;
+ case JsonToken.StartConstructor:
+ string constructorName = reader.Value.ToString();
+
+ while (reader.Read() && reader.TokenType != JsonToken.EndConstructor)
+ {
+ DeserializeValue(reader, document, manager, constructorName, currentNode);
+ }
+ break;
+ case JsonToken.Comment:
+ currentNode.AppendChild(document.CreateComment((string)reader.Value));
+ break;
+ case JsonToken.EndObject:
+ case JsonToken.EndArray:
+ return;
+ default:
+ throw new JsonSerializationException("Unexpected JsonToken when deserializing node: " + reader.TokenType);
+ }
+ } while (reader.TokenType == JsonToken.PropertyName || reader.Read());
+ // don't read if current token is a property. token was already read when parsing element attributes
+ }
+
+ ///
+ /// Checks if the attributeName is a namespace attribute.
+ ///
+ /// Attribute name to test.
+ /// The attribute name prefix if it has one, otherwise an empty string.
+ /// True if attribute name is for a namespace attribute, otherwise false.
+ private bool IsNamespaceAttribute(string attributeName, out string prefix)
+ {
+ if (attributeName.StartsWith("xmlns", StringComparison.Ordinal))
+ {
+ if (attributeName.Length == 5)
+ {
+ prefix = string.Empty;
+ return true;
+ }
+ else if (attributeName[5] == ':')
+ {
+ prefix = attributeName.Substring(6, attributeName.Length - 6);
+ return true;
+ }
+ }
+ prefix = null;
+ return false;
+ }
+
+ private IEnumerable ValueAttributes(IEnumerable c)
+ {
+ return c.Where(a => a.NamespaceUri != JsonNamespaceUri);
+ }
+ #endregion
+
+ ///
+ /// Determines whether this instance can convert the specified value type.
+ ///
+ /// Type of the value.
+ ///
+ /// true if this instance can convert the specified value type; otherwise, false .
+ ///
+ public override bool CanConvert(Type valueType)
+ {
+#if !NET20
+ if (typeof(XObject).IsAssignableFrom(valueType))
+ return true;
+#endif
+#if !(NETFX_CORE || PORTABLE)
+ if (typeof(XmlNode).IsAssignableFrom(valueType))
+ return true;
+#endif
+
+ return false;
+ }
+ }
+}
+
+#endif
diff --git a/Libs/JsonNet/DateFormatHandling.cs b/Libs/JsonNet/DateFormatHandling.cs
new file mode 100644
index 0000000..e26feec
--- /dev/null
+++ b/Libs/JsonNet/DateFormatHandling.cs
@@ -0,0 +1,43 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies how dates are formatted when writing JSON text.
+ ///
+ public enum DateFormatHandling
+ {
+ ///
+ /// Dates are written in the ISO 8601 format, e.g. "2012-03-21T05:40Z".
+ ///
+ IsoDateFormat,
+
+ ///
+ /// Dates are written in the Microsoft JSON format, e.g. "\/Date(1198908717056)\/".
+ ///
+ MicrosoftDateFormat
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/DateParseHandling.cs b/Libs/JsonNet/DateParseHandling.cs
new file mode 100644
index 0000000..84abaf5
--- /dev/null
+++ b/Libs/JsonNet/DateParseHandling.cs
@@ -0,0 +1,49 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON text.
+ ///
+ public enum DateParseHandling
+ {
+ ///
+ /// Date formatted strings are not parsed to a date type and are read as strings.
+ ///
+ None,
+
+ ///
+ /// Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to .
+ ///
+ DateTime,
+#if !NET20
+ ///
+ /// Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to .
+ ///
+ DateTimeOffset
+#endif
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/DateTimeZoneHandling.cs b/Libs/JsonNet/DateTimeZoneHandling.cs
new file mode 100644
index 0000000..df88908
--- /dev/null
+++ b/Libs/JsonNet/DateTimeZoneHandling.cs
@@ -0,0 +1,56 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies how to treat the time value when converting between string and .
+ ///
+ public enum DateTimeZoneHandling
+ {
+ ///
+ /// Treat as local time. If the object represents a Coordinated Universal Time (UTC), it is converted to the local time.
+ ///
+ Local,
+
+ ///
+ /// Treat as a UTC. If the object represents a local time, it is converted to a UTC.
+ ///
+ Utc,
+
+ ///
+ /// Treat as a local time if a is being converted to a string.
+ /// If a string is being converted to , convert to a local time if a time zone is specified.
+ ///
+ Unspecified,
+
+ ///
+ /// Time zone information should be preserved when converting.
+ ///
+ RoundtripKind
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/DefaultValueHandling.cs b/Libs/JsonNet/DefaultValueHandling.cs
new file mode 100644
index 0000000..6125e92
--- /dev/null
+++ b/Libs/JsonNet/DefaultValueHandling.cs
@@ -0,0 +1,67 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.ComponentModel;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies default value handling options for the .
+ ///
+ ///
+ ///
+ ///
+ ///
+ [Flags]
+ public enum DefaultValueHandling
+ {
+ ///
+ /// Include members where the member value is the same as the member's default value when serializing objects.
+ /// Included members are written to JSON. Has no effect when deserializing.
+ ///
+ Include = 0,
+
+ ///
+ /// Ignore members where the member value is the same as the member's default value when serializing objects
+ /// so that is is not written to JSON.
+ /// This option will ignore all default values (e.g. null for objects and nullable types; 0 for integers,
+ /// decimals and floating point numbers; and false for booleans). The default value ignored can be changed by
+ /// placing the on the property.
+ ///
+ Ignore = 1,
+
+ ///
+ /// Members with a default value but no JSON will be set to their default value when deserializing.
+ ///
+ Populate = 2,
+
+ ///
+ /// Ignore members where the member value is the same as the member's default value when serializing objects
+ /// and sets members to their default value when deserializing.
+ ///
+ IgnoreAndPopulate = Ignore | Populate
+ }
+}
diff --git a/Libs/JsonNet/FloatFormatHandling.cs b/Libs/JsonNet/FloatFormatHandling.cs
new file mode 100644
index 0000000..f39f7cc
--- /dev/null
+++ b/Libs/JsonNet/FloatFormatHandling.cs
@@ -0,0 +1,50 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies float format handling options when writing special floating point numbers, e.g. ,
+ /// and with .
+ ///
+ public enum FloatFormatHandling
+ {
+ ///
+ /// Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity".
+ ///
+ String,
+
+ ///
+ /// Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity.
+ /// Note that this will produce non-valid JSON.
+ ///
+ Symbol,
+
+ ///
+ /// Write special floating point values as the property's default value in JSON, e.g. 0.0 for a property, null for a property.
+ ///
+ DefaultValue
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/FloatParseHandling.cs b/Libs/JsonNet/FloatParseHandling.cs
new file mode 100644
index 0000000..093d6e9
--- /dev/null
+++ b/Libs/JsonNet/FloatParseHandling.cs
@@ -0,0 +1,43 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
+ ///
+ public enum FloatParseHandling
+ {
+ ///
+ /// Floating point numbers are parsed to .
+ ///
+ Double,
+
+ ///
+ /// Floating point numbers are parsed to .
+ ///
+ Decimal
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/FormatterAssemblyStyle.cs b/Libs/JsonNet/FormatterAssemblyStyle.cs
new file mode 100644
index 0000000..0029781
--- /dev/null
+++ b/Libs/JsonNet/FormatterAssemblyStyle.cs
@@ -0,0 +1,23 @@
+
+#if PocketPC || NETFX_CORE || PORTABLE40 || PORTABLE
+
+namespace System.Runtime.Serialization.Formatters
+{
+ ///
+ /// Indicates the method that will be used during deserialization for locating and loading assemblies.
+ ///
+ public enum FormatterAssemblyStyle
+ {
+ ///
+ /// In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. Specifically, the version numbers need not match as the LoadWithPartialName method is used to load the assembly.
+ ///
+ Simple,
+
+ ///
+ /// In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The Load method of the Assembly class is used to load the assembly.
+ ///
+ Full
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Libs/JsonNet/Formatting.cs b/Libs/JsonNet/Formatting.cs
new file mode 100644
index 0000000..55043b5
--- /dev/null
+++ b/Libs/JsonNet/Formatting.cs
@@ -0,0 +1,43 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies formatting options for the .
+ ///
+ public enum Formatting
+ {
+ ///
+ /// No special formatting is applied. This is the default.
+ ///
+ None,
+
+ ///
+ /// Causes child objects to be indented according to the and settings.
+ ///
+ Indented
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/IJsonLineInfo.cs b/Libs/JsonNet/IJsonLineInfo.cs
new file mode 100644
index 0000000..b71aedf
--- /dev/null
+++ b/Libs/JsonNet/IJsonLineInfo.cs
@@ -0,0 +1,53 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Provides an interface to enable a class to return line and position information.
+ ///
+ public interface IJsonLineInfo
+ {
+ ///
+ /// Gets a value indicating whether the class can return line information.
+ ///
+ ///
+ /// true if LineNumber and LinePosition can be provided; otherwise, false .
+ ///
+ bool HasLineInfo();
+
+ ///
+ /// Gets the current line number.
+ ///
+ /// The current line number or 0 if no line information is available (for example, HasLineInfo returns false).
+ int LineNumber { get; }
+
+ ///
+ /// Gets the current line position.
+ ///
+ /// The current line position or 0 if no line information is available (for example, HasLineInfo returns false).
+ int LinePosition { get; }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonArrayAttribute.cs b/Libs/JsonNet/JsonArrayAttribute.cs
new file mode 100644
index 0000000..bbfc90d
--- /dev/null
+++ b/Libs/JsonNet/JsonArrayAttribute.cs
@@ -0,0 +1,73 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the how to serialize the collection.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
+ public sealed class JsonArrayAttribute : JsonContainerAttribute
+ {
+ private bool _allowNullItems;
+
+ ///
+ /// Gets or sets a value indicating whether null items are allowed in the collection.
+ ///
+ /// true if null items are allowed in the collection; otherwise, false .
+ public bool AllowNullItems
+ {
+ get { return _allowNullItems; }
+ set { _allowNullItems = value; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonArrayAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with a flag indicating whether the array can contain null items
+ ///
+ /// A flag indicating whether the array can contain null items.
+ public JsonArrayAttribute(bool allowNullItems)
+ {
+ _allowNullItems = allowNullItems;
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified container Id.
+ ///
+ /// The container Id.
+ public JsonArrayAttribute(string id)
+ : base(id)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonConstructorAttribute.cs b/Libs/JsonNet/JsonConstructorAttribute.cs
new file mode 100644
index 0000000..cd5d1bb
--- /dev/null
+++ b/Libs/JsonNet/JsonConstructorAttribute.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the to use the specified constructor when deserializing that object.
+ ///
+ [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)]
+ public sealed class JsonConstructorAttribute : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonContainerAttribute.cs b/Libs/JsonNet/JsonContainerAttribute.cs
new file mode 100644
index 0000000..de77739
--- /dev/null
+++ b/Libs/JsonNet/JsonContainerAttribute.cs
@@ -0,0 +1,138 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the how to serialize the object.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
+ public abstract class JsonContainerAttribute : Attribute
+ {
+ ///
+ /// Gets or sets the id.
+ ///
+ /// The id.
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the title.
+ ///
+ /// The title.
+ public string Title { get; set; }
+
+ ///
+ /// Gets or sets the description.
+ ///
+ /// The description.
+ public string Description { get; set; }
+
+ ///
+ /// Gets the collection's items converter.
+ ///
+ /// The collection's items converter.
+ public Type ItemConverterType { get; set; }
+
+ ///
+ /// The parameter list to use when constructing the JsonConverter described by ItemConverterType.
+ /// If null, the default constructor is used.
+ /// When non-null, there must be a constructor defined in the JsonConverter that exactly matches the number,
+ /// order, and type of these parameters.
+ ///
+ ///
+ /// [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })]
+ ///
+ public object[] ItemConverterParameters { get; set; }
+
+ // yuck. can't set nullable properties on an attribute in C#
+ // have to use this approach to get an unset default state
+ internal bool? _isReference;
+ internal bool? _itemIsReference;
+ internal ReferenceLoopHandling? _itemReferenceLoopHandling;
+ internal TypeNameHandling? _itemTypeNameHandling;
+
+ ///
+ /// Gets or sets a value that indicates whether to preserve object references.
+ ///
+ ///
+ /// true to keep object reference; otherwise, false . The default is false .
+ ///
+ public bool IsReference
+ {
+ get { return _isReference ?? default(bool); }
+ set { _isReference = value; }
+ }
+
+ ///
+ /// Gets or sets a value that indicates whether to preserve collection's items references.
+ ///
+ ///
+ /// true to keep collection's items object references; otherwise, false . The default is false .
+ ///
+ public bool ItemIsReference
+ {
+ get { return _itemIsReference ?? default(bool); }
+ set { _itemIsReference = value; }
+ }
+
+ ///
+ /// Gets or sets the reference loop handling used when serializing the collection's items.
+ ///
+ /// The reference loop handling.
+ public ReferenceLoopHandling ItemReferenceLoopHandling
+ {
+ get { return _itemReferenceLoopHandling ?? default(ReferenceLoopHandling); }
+ set { _itemReferenceLoopHandling = value; }
+ }
+
+ ///
+ /// Gets or sets the type name handling used when serializing the collection's items.
+ ///
+ /// The type name handling.
+ public TypeNameHandling ItemTypeNameHandling
+ {
+ get { return _itemTypeNameHandling ?? default(TypeNameHandling); }
+ set { _itemTypeNameHandling = value; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ protected JsonContainerAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified container Id.
+ ///
+ /// The container Id.
+ protected JsonContainerAttribute(string id)
+ {
+ Id = id;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonConvert.cs b/Libs/JsonNet/JsonConvert.cs
new file mode 100644
index 0000000..3176dcf
--- /dev/null
+++ b/Libs/JsonNet/JsonConvert.cs
@@ -0,0 +1,1130 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.IO;
+using System.Globalization;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+using System.Threading.Tasks;
+#endif
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+using System.Xml;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+using System.Text;
+#if !(NET20 || PORTABLE40)
+using System.Xml.Linq;
+#endif
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Provides methods for converting between common language runtime types and JSON types.
+ ///
+ ///
+ ///
+ ///
+ public static class JsonConvert
+ {
+ ///
+ /// Gets or sets a function that creates default .
+ /// Default settings are automatically used by serialization methods on ,
+ /// and and on .
+ /// To serialize without using any default settings create a with
+ /// .
+ ///
+ public static Func DefaultSettings { get; set; }
+
+ ///
+ /// Represents JavaScript's boolean value true as a string. This field is read-only.
+ ///
+ public static readonly string True = "true";
+
+ ///
+ /// Represents JavaScript's boolean value false as a string. This field is read-only.
+ ///
+ public static readonly string False = "false";
+
+ ///
+ /// Represents JavaScript's null as a string. This field is read-only.
+ ///
+ public static readonly string Null = "null";
+
+ ///
+ /// Represents JavaScript's undefined as a string. This field is read-only.
+ ///
+ public static readonly string Undefined = "undefined";
+
+ ///
+ /// Represents JavaScript's positive infinity as a string. This field is read-only.
+ ///
+ public static readonly string PositiveInfinity = "Infinity";
+
+ ///
+ /// Represents JavaScript's negative infinity as a string. This field is read-only.
+ ///
+ public static readonly string NegativeInfinity = "-Infinity";
+
+ ///
+ /// Represents JavaScript's NaN as a string. This field is read-only.
+ ///
+ public static readonly string NaN = "NaN";
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(DateTime value)
+ {
+ return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind);
+ }
+
+ ///
+ /// Converts the to its JSON string representation using the specified.
+ ///
+ /// The value to convert.
+ /// The format the date will be converted to.
+ /// The time zone handling when the date is converted to a string.
+ /// A JSON string representation of the .
+ public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling)
+ {
+ DateTime updatedDateTime = DateTimeUtils.EnsureDateTime(value, timeZoneHandling);
+
+ using (StringWriter writer = StringUtils.CreateStringWriter(64))
+ {
+ writer.Write('"');
+ DateTimeUtils.WriteDateTimeString(writer, updatedDateTime, format, null, CultureInfo.InvariantCulture);
+ writer.Write('"');
+ return writer.ToString();
+ }
+ }
+
+#if !NET20
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(DateTimeOffset value)
+ {
+ return ToString(value, DateFormatHandling.IsoDateFormat);
+ }
+
+ ///
+ /// Converts the to its JSON string representation using the specified.
+ ///
+ /// The value to convert.
+ /// The format the date will be converted to.
+ /// A JSON string representation of the .
+ public static string ToString(DateTimeOffset value, DateFormatHandling format)
+ {
+ using (StringWriter writer = StringUtils.CreateStringWriter(64))
+ {
+ writer.Write('"');
+ DateTimeUtils.WriteDateTimeOffsetString(writer, value, format, null, CultureInfo.InvariantCulture);
+ writer.Write('"');
+ return writer.ToString();
+ }
+ }
+#endif
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(bool value)
+ {
+ return (value) ? True : False;
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(char value)
+ {
+ return ToString(char.ToString(value));
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(Enum value)
+ {
+ return value.ToString("D");
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(int value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(short value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ [CLSCompliant(false)]
+ public static string ToString(ushort value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ [CLSCompliant(false)]
+ public static string ToString(uint value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(long value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+ private static string ToStringInternal(BigInteger value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+#endif
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ [CLSCompliant(false)]
+ public static string ToString(ulong value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(float value)
+ {
+ return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
+ }
+
+ internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
+ {
+ return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
+ }
+
+ private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
+ {
+ if (floatFormatHandling == FloatFormatHandling.Symbol || !(double.IsInfinity(value) || double.IsNaN(value)))
+ return text;
+
+ if (floatFormatHandling == FloatFormatHandling.DefaultValue)
+ return (!nullable) ? "0.0" : Null;
+
+ return quoteChar + text + quoteChar;
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(double value)
+ {
+ return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
+ }
+
+ internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
+ {
+ return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
+ }
+
+ private static string EnsureDecimalPlace(double value, string text)
+ {
+ if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1)
+ return text;
+
+ return text + ".0";
+ }
+
+ private static string EnsureDecimalPlace(string text)
+ {
+ if (text.IndexOf('.') != -1)
+ return text;
+
+ return text + ".0";
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(byte value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ [CLSCompliant(false)]
+ public static string ToString(sbyte value)
+ {
+ return value.ToString(null, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(decimal value)
+ {
+ return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture));
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(Guid value)
+ {
+ return ToString(value, '"');
+ }
+
+ internal static string ToString(Guid value, char quoteChar)
+ {
+ string text;
+ string qc;
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ text = value.ToString("D", CultureInfo.InvariantCulture);
+ qc = quoteChar.ToString(CultureInfo.InvariantCulture);
+#else
+ text = value.ToString("D");
+ qc = quoteChar.ToString();
+#endif
+
+ return qc + text + qc;
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(TimeSpan value)
+ {
+ return ToString(value, '"');
+ }
+
+ internal static string ToString(TimeSpan value, char quoteChar)
+ {
+ return ToString(value.ToString(), quoteChar);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(Uri value)
+ {
+ if (value == null)
+ return Null;
+
+ return ToString(value, '"');
+ }
+
+ internal static string ToString(Uri value, char quoteChar)
+ {
+ return ToString(value.OriginalString, quoteChar);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(string value)
+ {
+ return ToString(value, '"');
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// The string delimiter character.
+ /// A JSON string representation of the .
+ public static string ToString(string value, char delimiter)
+ {
+ return ToString(value, delimiter, StringEscapeHandling.Default);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// The string delimiter character.
+ /// The string escape handling.
+ /// A JSON string representation of the .
+ public static string ToString(string value, char delimiter, StringEscapeHandling stringEscapeHandling)
+ {
+ if (delimiter != '"' && delimiter != '\'')
+ throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter");
+
+ return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, true, stringEscapeHandling);
+ }
+
+ ///
+ /// Converts the to its JSON string representation.
+ ///
+ /// The value to convert.
+ /// A JSON string representation of the .
+ public static string ToString(object value)
+ {
+ if (value == null)
+ return Null;
+
+ PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(value.GetType());
+
+ switch (typeCode)
+ {
+ case PrimitiveTypeCode.String:
+ return ToString((string)value);
+ case PrimitiveTypeCode.Char:
+ return ToString((char)value);
+ case PrimitiveTypeCode.Boolean:
+ return ToString((bool)value);
+ case PrimitiveTypeCode.SByte:
+ return ToString((sbyte)value);
+ case PrimitiveTypeCode.Int16:
+ return ToString((short)value);
+ case PrimitiveTypeCode.UInt16:
+ return ToString((ushort)value);
+ case PrimitiveTypeCode.Int32:
+ return ToString((int)value);
+ case PrimitiveTypeCode.Byte:
+ return ToString((byte)value);
+ case PrimitiveTypeCode.UInt32:
+ return ToString((uint)value);
+ case PrimitiveTypeCode.Int64:
+ return ToString((long)value);
+ case PrimitiveTypeCode.UInt64:
+ return ToString((ulong)value);
+ case PrimitiveTypeCode.Single:
+ return ToString((float)value);
+ case PrimitiveTypeCode.Double:
+ return ToString((double)value);
+ case PrimitiveTypeCode.DateTime:
+ return ToString((DateTime)value);
+ case PrimitiveTypeCode.Decimal:
+ return ToString((decimal)value);
+#if !(NETFX_CORE || PORTABLE)
+ case PrimitiveTypeCode.DBNull:
+ return Null;
+#endif
+#if !NET20
+ case PrimitiveTypeCode.DateTimeOffset:
+ return ToString((DateTimeOffset)value);
+#endif
+ case PrimitiveTypeCode.Guid:
+ return ToString((Guid)value);
+ case PrimitiveTypeCode.Uri:
+ return ToString((Uri)value);
+ case PrimitiveTypeCode.TimeSpan:
+ return ToString((TimeSpan)value);
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+ case PrimitiveTypeCode.BigInteger:
+ return ToStringInternal((BigInteger)value);
+#endif
+ }
+
+ throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
+ }
+
+ #region Serialize
+ ///
+ /// Serializes the specified object to a JSON string.
+ ///
+ /// The object to serialize.
+ /// A JSON string representation of the object.
+ public static string SerializeObject(object value)
+ {
+ return SerializeObject(value, null, (JsonSerializerSettings)null);
+ }
+
+ ///
+ /// Serializes the specified object to a JSON string using formatting.
+ ///
+ /// The object to serialize.
+ /// Indicates how the output is formatted.
+ ///
+ /// A JSON string representation of the object.
+ ///
+ public static string SerializeObject(object value, Formatting formatting)
+ {
+ return SerializeObject(value, formatting, (JsonSerializerSettings)null);
+ }
+
+ ///
+ /// Serializes the specified object to a JSON string using a collection of .
+ ///
+ /// The object to serialize.
+ /// A collection converters used while serializing.
+ /// A JSON string representation of the object.
+ public static string SerializeObject(object value, params JsonConverter[] converters)
+ {
+ JsonSerializerSettings settings = (converters != null && converters.Length > 0)
+ ? new JsonSerializerSettings { Converters = converters }
+ : null;
+
+ return SerializeObject(value, null, settings);
+ }
+
+ ///
+ /// Serializes the specified object to a JSON string using formatting and a collection of .
+ ///
+ /// The object to serialize.
+ /// Indicates how the output is formatted.
+ /// A collection converters used while serializing.
+ /// A JSON string representation of the object.
+ public static string SerializeObject(object value, Formatting formatting, params JsonConverter[] converters)
+ {
+ JsonSerializerSettings settings = (converters != null && converters.Length > 0)
+ ? new JsonSerializerSettings { Converters = converters }
+ : null;
+
+ return SerializeObject(value, null, formatting, settings);
+ }
+
+ ///
+ /// Serializes the specified object to a JSON string using .
+ ///
+ /// The object to serialize.
+ /// The used to serialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// A JSON string representation of the object.
+ ///
+ public static string SerializeObject(object value, JsonSerializerSettings settings)
+ {
+ return SerializeObject(value, null, settings);
+ }
+
+ ///
+ /// Serializes the specified object to a JSON string using a type, formatting and .
+ ///
+ /// The object to serialize.
+ /// The used to serialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// The type of the value being serialized.
+ /// This parameter is used when is Auto to write out the type name if the type of the value does not match.
+ /// Specifing the type is optional.
+ ///
+ ///
+ /// A JSON string representation of the object.
+ ///
+ public static string SerializeObject(object value, Type type, JsonSerializerSettings settings)
+ {
+ JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
+
+ return SerializeObjectInternal(value, type, jsonSerializer);
+ }
+
+ ///
+ /// Serializes the specified object to a JSON string using formatting and .
+ ///
+ /// The object to serialize.
+ /// Indicates how the output is formatted.
+ /// The used to serialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// A JSON string representation of the object.
+ ///
+ public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings)
+ {
+ return SerializeObject(value, null, formatting, settings);
+ }
+
+ ///
+ /// Serializes the specified object to a JSON string using a type, formatting and .
+ ///
+ /// The object to serialize.
+ /// Indicates how the output is formatted.
+ /// The used to serialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// The type of the value being serialized.
+ /// This parameter is used when is Auto to write out the type name if the type of the value does not match.
+ /// Specifing the type is optional.
+ ///
+ ///
+ /// A JSON string representation of the object.
+ ///
+ public static string SerializeObject(object value, Type type, Formatting formatting, JsonSerializerSettings settings)
+ {
+ JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
+ jsonSerializer.Formatting = formatting;
+
+ return SerializeObjectInternal(value, type, jsonSerializer);
+ }
+
+ private static string SerializeObjectInternal(object value, Type type, JsonSerializer jsonSerializer)
+ {
+ StringBuilder sb = new StringBuilder(256);
+ StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
+ using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
+ {
+ jsonWriter.Formatting = jsonSerializer.Formatting;
+
+ jsonSerializer.Serialize(jsonWriter, value, type);
+ }
+
+ return sw.ToString();
+ }
+
+#if !(NET20 || NET35 || PORTABLE40)
+ ///
+ /// Asynchronously serializes the specified object to a JSON string.
+ /// Serialization will happen on a new thread.
+ ///
+ /// The object to serialize.
+ ///
+ /// A task that represents the asynchronous serialize operation. The value of the TResult parameter contains a JSON string representation of the object.
+ ///
+ [ObsoleteAttribute("SerializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to serialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.SerializeObject(value))")]
+ public static Task SerializeObjectAsync(object value)
+ {
+ return SerializeObjectAsync(value, Formatting.None, null);
+ }
+
+ ///
+ /// Asynchronously serializes the specified object to a JSON string using formatting.
+ /// Serialization will happen on a new thread.
+ ///
+ /// The object to serialize.
+ /// Indicates how the output is formatted.
+ ///
+ /// A task that represents the asynchronous serialize operation. The value of the TResult parameter contains a JSON string representation of the object.
+ ///
+ [ObsoleteAttribute("SerializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to serialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.SerializeObject(value, formatting))")]
+ public static Task SerializeObjectAsync(object value, Formatting formatting)
+ {
+ return SerializeObjectAsync(value, formatting, null);
+ }
+
+ ///
+ /// Asynchronously serializes the specified object to a JSON string using formatting and a collection of .
+ /// Serialization will happen on a new thread.
+ ///
+ /// The object to serialize.
+ /// Indicates how the output is formatted.
+ /// The used to serialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// A task that represents the asynchronous serialize operation. The value of the TResult parameter contains a JSON string representation of the object.
+ ///
+ [ObsoleteAttribute("SerializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to serialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.SerializeObject(value, formatting, settings))")]
+ public static Task SerializeObjectAsync(object value, Formatting formatting, JsonSerializerSettings settings)
+ {
+ return Task.Factory.StartNew(() => SerializeObject(value, formatting, settings));
+ }
+#endif
+ #endregion
+
+ #region Deserialize
+ ///
+ /// Deserializes the JSON to a .NET object.
+ ///
+ /// The JSON to deserialize.
+ /// The deserialized object from the JSON string.
+ public static object DeserializeObject(string value)
+ {
+ return DeserializeObject(value, null, (JsonSerializerSettings)null);
+ }
+
+ ///
+ /// Deserializes the JSON to a .NET object using .
+ ///
+ /// The JSON to deserialize.
+ ///
+ /// The used to deserialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// The deserialized object from the JSON string.
+ public static object DeserializeObject(string value, JsonSerializerSettings settings)
+ {
+ return DeserializeObject(value, null, settings);
+ }
+
+ ///
+ /// Deserializes the JSON to the specified .NET type.
+ ///
+ /// The JSON to deserialize.
+ /// The of object being deserialized.
+ /// The deserialized object from the JSON string.
+ public static object DeserializeObject(string value, Type type)
+ {
+ return DeserializeObject(value, type, (JsonSerializerSettings)null);
+ }
+
+ ///
+ /// Deserializes the JSON to the specified .NET type.
+ ///
+ /// The type of the object to deserialize to.
+ /// The JSON to deserialize.
+ /// The deserialized object from the JSON string.
+ public static T DeserializeObject(string value)
+ {
+ return DeserializeObject(value, (JsonSerializerSettings)null);
+ }
+
+ ///
+ /// Deserializes the JSON to the given anonymous type.
+ ///
+ ///
+ /// The anonymous type to deserialize to. This can't be specified
+ /// traditionally and must be infered from the anonymous type passed
+ /// as a parameter.
+ ///
+ /// The JSON to deserialize.
+ /// The anonymous type object.
+ /// The deserialized anonymous type from the JSON string.
+ public static T DeserializeAnonymousType(string value, T anonymousTypeObject)
+ {
+ return DeserializeObject(value);
+ }
+
+ ///
+ /// Deserializes the JSON to the given anonymous type using .
+ ///
+ ///
+ /// The anonymous type to deserialize to. This can't be specified
+ /// traditionally and must be infered from the anonymous type passed
+ /// as a parameter.
+ ///
+ /// The JSON to deserialize.
+ /// The anonymous type object.
+ ///
+ /// The used to deserialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// The deserialized anonymous type from the JSON string.
+ public static T DeserializeAnonymousType(string value, T anonymousTypeObject, JsonSerializerSettings settings)
+ {
+ return DeserializeObject(value, settings);
+ }
+
+ ///
+ /// Deserializes the JSON to the specified .NET type using a collection of .
+ ///
+ /// The type of the object to deserialize to.
+ /// The JSON to deserialize.
+ /// Converters to use while deserializing.
+ /// The deserialized object from the JSON string.
+ public static T DeserializeObject(string value, params JsonConverter[] converters)
+ {
+ return (T)DeserializeObject(value, typeof(T), converters);
+ }
+
+ ///
+ /// Deserializes the JSON to the specified .NET type using .
+ ///
+ /// The type of the object to deserialize to.
+ /// The object to deserialize.
+ ///
+ /// The used to deserialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// The deserialized object from the JSON string.
+ public static T DeserializeObject(string value, JsonSerializerSettings settings)
+ {
+ return (T)DeserializeObject(value, typeof(T), settings);
+ }
+
+ ///
+ /// Deserializes the JSON to the specified .NET type using a collection of .
+ ///
+ /// The JSON to deserialize.
+ /// The type of the object to deserialize.
+ /// Converters to use while deserializing.
+ /// The deserialized object from the JSON string.
+ public static object DeserializeObject(string value, Type type, params JsonConverter[] converters)
+ {
+ JsonSerializerSettings settings = (converters != null && converters.Length > 0)
+ ? new JsonSerializerSettings { Converters = converters }
+ : null;
+
+ return DeserializeObject(value, type, settings);
+ }
+
+ ///
+ /// Deserializes the JSON to the specified .NET type using .
+ ///
+ /// The JSON to deserialize.
+ /// The type of the object to deserialize to.
+ ///
+ /// The used to deserialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ /// The deserialized object from the JSON string.
+ public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings)
+ {
+ ValidationUtils.ArgumentNotNull(value, "value");
+
+ JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
+
+ // by default DeserializeObject should check for additional content
+ if (!jsonSerializer.IsCheckAdditionalContentSet())
+ jsonSerializer.CheckAdditionalContent = true;
+
+ using (var reader = new JsonTextReader(new StringReader(value)))
+ {
+ return jsonSerializer.Deserialize(reader, type);
+ }
+ }
+
+#if !(NET20 || NET35 || PORTABLE40)
+ ///
+ /// Asynchronously deserializes the JSON to the specified .NET type.
+ /// Deserialization will happen on a new thread.
+ ///
+ /// The type of the object to deserialize to.
+ /// The JSON to deserialize.
+ ///
+ /// A task that represents the asynchronous deserialize operation. The value of the TResult parameter contains the deserialized object from the JSON string.
+ ///
+ [ObsoleteAttribute("DeserializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to deserialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.DeserializeObject(value))")]
+ public static Task DeserializeObjectAsync(string value)
+ {
+ return DeserializeObjectAsync(value, null);
+ }
+
+ ///
+ /// Asynchronously deserializes the JSON to the specified .NET type using .
+ /// Deserialization will happen on a new thread.
+ ///
+ /// The type of the object to deserialize to.
+ /// The JSON to deserialize.
+ ///
+ /// The used to deserialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ ///
+ /// A task that represents the asynchronous deserialize operation. The value of the TResult parameter contains the deserialized object from the JSON string.
+ ///
+ [ObsoleteAttribute("DeserializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to deserialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.DeserializeObject(value, settings))")]
+ public static Task DeserializeObjectAsync(string value, JsonSerializerSettings settings)
+ {
+ return Task.Factory.StartNew(() => DeserializeObject(value, settings));
+ }
+
+ ///
+ /// Asynchronously deserializes the JSON to the specified .NET type.
+ /// Deserialization will happen on a new thread.
+ ///
+ /// The JSON to deserialize.
+ ///
+ /// A task that represents the asynchronous deserialize operation. The value of the TResult parameter contains the deserialized object from the JSON string.
+ ///
+ [ObsoleteAttribute("DeserializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to deserialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.DeserializeObject(value))")]
+ public static Task DeserializeObjectAsync(string value)
+ {
+ return DeserializeObjectAsync(value, null, null);
+ }
+
+ ///
+ /// Asynchronously deserializes the JSON to the specified .NET type using .
+ /// Deserialization will happen on a new thread.
+ ///
+ /// The JSON to deserialize.
+ /// The type of the object to deserialize to.
+ ///
+ /// The used to deserialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ ///
+ /// A task that represents the asynchronous deserialize operation. The value of the TResult parameter contains the deserialized object from the JSON string.
+ ///
+ [ObsoleteAttribute("DeserializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to deserialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.DeserializeObject(value, type, settings))")]
+ public static Task DeserializeObjectAsync(string value, Type type, JsonSerializerSettings settings)
+ {
+ return Task.Factory.StartNew(() => DeserializeObject(value, type, settings));
+ }
+#endif
+ #endregion
+
+ ///
+ /// Populates the object with values from the JSON string.
+ ///
+ /// The JSON to populate values from.
+ /// The target object to populate values onto.
+ public static void PopulateObject(string value, object target)
+ {
+ PopulateObject(value, target, null);
+ }
+
+ ///
+ /// Populates the object with values from the JSON string using .
+ ///
+ /// The JSON to populate values from.
+ /// The target object to populate values onto.
+ ///
+ /// The used to deserialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ public static void PopulateObject(string value, object target, JsonSerializerSettings settings)
+ {
+ JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
+
+ using (JsonReader jsonReader = new JsonTextReader(new StringReader(value)))
+ {
+ jsonSerializer.Populate(jsonReader, target);
+
+ if (jsonReader.Read() && jsonReader.TokenType != JsonToken.Comment)
+ throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object.");
+ }
+ }
+
+#if !(NET20 || NET35 || PORTABLE40)
+ ///
+ /// Asynchronously populates the object with values from the JSON string using .
+ ///
+ /// The JSON to populate values from.
+ /// The target object to populate values onto.
+ ///
+ /// The used to deserialize the object.
+ /// If this is null, default serialization settings will be used.
+ ///
+ ///
+ /// A task that represents the asynchronous populate operation.
+ ///
+ [ObsoleteAttribute("PopulateObjectAsync is obsolete. Use the Task.Factory.StartNew method to populate an object with JSON values asynchronously: Task.Factory.StartNew(() => JsonConvert.PopulateObject(value, target, settings))")]
+ public static Task PopulateObjectAsync(string value, object target, JsonSerializerSettings settings)
+ {
+ return Task.Factory.StartNew(() => PopulateObject(value, target, settings));
+ }
+#endif
+
+#if !(PORTABLE40 || PORTABLE || NETFX_CORE)
+ ///
+ /// Serializes the XML node to a JSON string.
+ ///
+ /// The node to serialize.
+ /// A JSON string of the XmlNode.
+ public static string SerializeXmlNode(XmlNode node)
+ {
+ return SerializeXmlNode(node, Formatting.None);
+ }
+
+ ///
+ /// Serializes the XML node to a JSON string using formatting.
+ ///
+ /// The node to serialize.
+ /// Indicates how the output is formatted.
+ /// A JSON string of the XmlNode.
+ public static string SerializeXmlNode(XmlNode node, Formatting formatting)
+ {
+ XmlNodeConverter converter = new XmlNodeConverter();
+
+ return SerializeObject(node, formatting, converter);
+ }
+
+ ///
+ /// Serializes the XML node to a JSON string using formatting and omits the root object if is true .
+ ///
+ /// The node to serialize.
+ /// Indicates how the output is formatted.
+ /// Omits writing the root object.
+ /// A JSON string of the XmlNode.
+ public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool omitRootObject)
+ {
+ XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
+
+ return SerializeObject(node, formatting, converter);
+ }
+
+ ///
+ /// Deserializes the XmlNode from a JSON string.
+ ///
+ /// The JSON string.
+ /// The deserialized XmlNode
+ public static XmlDocument DeserializeXmlNode(string value)
+ {
+ return DeserializeXmlNode(value, null);
+ }
+
+ ///
+ /// Deserializes the XmlNode from a JSON string nested in a root elment specified by .
+ ///
+ /// The JSON string.
+ /// The name of the root element to append when deserializing.
+ /// The deserialized XmlNode
+ public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName)
+ {
+ return DeserializeXmlNode(value, deserializeRootElementName, false);
+ }
+
+ ///
+ /// Deserializes the XmlNode from a JSON string nested in a root elment specified by
+ /// and writes a .NET array attribute for collections.
+ ///
+ /// The JSON string.
+ /// The name of the root element to append when deserializing.
+ ///
+ /// A flag to indicate whether to write the Json.NET array attribute.
+ /// This attribute helps preserve arrays when converting the written XML back to JSON.
+ ///
+ /// The deserialized XmlNode
+ public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
+ {
+ XmlNodeConverter converter = new XmlNodeConverter();
+ converter.DeserializeRootElementName = deserializeRootElementName;
+ converter.WriteArrayAttribute = writeArrayAttribute;
+
+ return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter);
+ }
+#endif
+
+#if !NET20 && !PORTABLE40
+ ///
+ /// Serializes the to a JSON string.
+ ///
+ /// The node to convert to JSON.
+ /// A JSON string of the XNode.
+ public static string SerializeXNode(XObject node)
+ {
+ return SerializeXNode(node, Formatting.None);
+ }
+
+ ///
+ /// Serializes the to a JSON string using formatting.
+ ///
+ /// The node to convert to JSON.
+ /// Indicates how the output is formatted.
+ /// A JSON string of the XNode.
+ public static string SerializeXNode(XObject node, Formatting formatting)
+ {
+ return SerializeXNode(node, formatting, false);
+ }
+
+ ///
+ /// Serializes the to a JSON string using formatting and omits the root object if is true .
+ ///
+ /// The node to serialize.
+ /// Indicates how the output is formatted.
+ /// Omits writing the root object.
+ /// A JSON string of the XNode.
+ public static string SerializeXNode(XObject node, Formatting formatting, bool omitRootObject)
+ {
+ XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
+
+ return SerializeObject(node, formatting, converter);
+ }
+
+ ///
+ /// Deserializes the from a JSON string.
+ ///
+ /// The JSON string.
+ /// The deserialized XNode
+ public static XDocument DeserializeXNode(string value)
+ {
+ return DeserializeXNode(value, null);
+ }
+
+ ///
+ /// Deserializes the from a JSON string nested in a root elment specified by .
+ ///
+ /// The JSON string.
+ /// The name of the root element to append when deserializing.
+ /// The deserialized XNode
+ public static XDocument DeserializeXNode(string value, string deserializeRootElementName)
+ {
+ return DeserializeXNode(value, deserializeRootElementName, false);
+ }
+
+ ///
+ /// Deserializes the from a JSON string nested in a root elment specified by
+ /// and writes a .NET array attribute for collections.
+ ///
+ /// The JSON string.
+ /// The name of the root element to append when deserializing.
+ ///
+ /// A flag to indicate whether to write the Json.NET array attribute.
+ /// This attribute helps preserve arrays when converting the written XML back to JSON.
+ ///
+ /// The deserialized XNode
+ public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
+ {
+ XmlNodeConverter converter = new XmlNodeConverter();
+ converter.DeserializeRootElementName = deserializeRootElementName;
+ converter.WriteArrayAttribute = writeArrayAttribute;
+
+ return (XDocument)DeserializeObject(value, typeof(XDocument), converter);
+ }
+#endif
+ }
+}
diff --git a/Libs/JsonNet/JsonConverter.cs b/Libs/JsonNet/JsonConverter.cs
new file mode 100644
index 0000000..424b7ee
--- /dev/null
+++ b/Libs/JsonNet/JsonConverter.cs
@@ -0,0 +1,93 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Schema;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Converts an object to and from JSON.
+ ///
+ public abstract class JsonConverter
+ {
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value.
+ /// The calling serializer.
+ public abstract void WriteJson(JsonWriter writer, object value, JsonSerializer serializer);
+
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// Type of the object.
+ /// The existing value of object being read.
+ /// The calling serializer.
+ /// The object value.
+ public abstract object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer);
+
+ ///
+ /// Determines whether this instance can convert the specified object type.
+ ///
+ /// Type of the object.
+ ///
+ /// true if this instance can convert the specified object type; otherwise, false .
+ ///
+ public abstract bool CanConvert(Type objectType);
+
+ ///
+ /// Gets the of the JSON produced by the JsonConverter.
+ ///
+ /// The of the JSON produced by the JsonConverter.
+ public virtual JsonSchema GetSchema()
+ {
+ return null;
+ }
+
+ ///
+ /// Gets a value indicating whether this can read JSON.
+ ///
+ /// true if this can read JSON; otherwise, false .
+ public virtual bool CanRead
+ {
+ get { return true; }
+ }
+
+ ///
+ /// Gets a value indicating whether this can write JSON.
+ ///
+ /// true if this can write JSON; otherwise, false .
+ public virtual bool CanWrite
+ {
+ get { return true; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonConverterAttribute.cs b/Libs/JsonNet/JsonConverterAttribute.cs
new file mode 100644
index 0000000..f389780
--- /dev/null
+++ b/Libs/JsonNet/JsonConverterAttribute.cs
@@ -0,0 +1,78 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the to use the specified when serializing the member or class.
+ ///
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Parameter, AllowMultiple = false)]
+ public sealed class JsonConverterAttribute : Attribute
+ {
+ private readonly Type _converterType;
+
+ ///
+ /// Gets the type of the converter.
+ ///
+ /// The type of the converter.
+ public Type ConverterType
+ {
+ get { return _converterType; }
+ }
+
+ ///
+ /// The parameter list to use when constructing the JsonConverter described by ConverterType.
+ /// If null, the default constructor is used.
+ ///
+ public object[] ConverterParameters { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the converter.
+ public JsonConverterAttribute(Type converterType)
+ {
+ if (converterType == null)
+ throw new ArgumentNullException("converterType");
+
+ _converterType = converterType;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the converter.
+ /// Parameter list to use when constructing the JsonConverter. Can be null.
+ public JsonConverterAttribute(Type converterType, params object[] converterParameters)
+ : this(converterType)
+ {
+ ConverterParameters = converterParameters;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonConverterCollection.cs b/Libs/JsonNet/JsonConverterCollection.cs
new file mode 100644
index 0000000..b2c0492
--- /dev/null
+++ b/Libs/JsonNet/JsonConverterCollection.cs
@@ -0,0 +1,39 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections.ObjectModel;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Represents a collection of .
+ ///
+ public class JsonConverterCollection : Collection
+ {
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonDictionaryAttribute.cs b/Libs/JsonNet/JsonDictionaryAttribute.cs
new file mode 100644
index 0000000..7ddf411
--- /dev/null
+++ b/Libs/JsonNet/JsonDictionaryAttribute.cs
@@ -0,0 +1,52 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the how to serialize the collection.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
+ public sealed class JsonDictionaryAttribute : JsonContainerAttribute
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonDictionaryAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified container Id.
+ ///
+ /// The container Id.
+ public JsonDictionaryAttribute(string id)
+ : base(id)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonException.cs b/Libs/JsonNet/JsonException.cs
new file mode 100644
index 0000000..edf123e
--- /dev/null
+++ b/Libs/JsonNet/JsonException.cs
@@ -0,0 +1,92 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// The exception thrown when an error occurs during Json serialization or deserialization.
+ ///
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ [Serializable]
+#endif
+ public class JsonException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonException()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a specified error message.
+ ///
+ /// The error message that explains the reason for the exception.
+ public JsonException(string message)
+ : base(message)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+ ///
+ /// The error message that explains the reason for the exception.
+ /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.
+ public JsonException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ /// The parameter is null.
+ /// The class name is null or is zero (0).
+ public JsonException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+#endif
+
+ internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message)
+ {
+ message = JsonPosition.FormatMessage(lineInfo, path, message);
+
+ return new JsonException(message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonExtensionDataAttribute.cs b/Libs/JsonNet/JsonExtensionDataAttribute.cs
new file mode 100644
index 0000000..6bc15b7
--- /dev/null
+++ b/Libs/JsonNet/JsonExtensionDataAttribute.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the to deserialize properties with no matching class member into the specified collection
+ /// and write values during serialization.
+ ///
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
+ public class JsonExtensionDataAttribute : Attribute
+ {
+ ///
+ /// Gets or sets a value that indicates whether to write extension data when serializing the object.
+ ///
+ ///
+ /// true to write extension data when serializing the object; otherwise, false . The default is true .
+ ///
+ public bool WriteData { get; set; }
+
+ ///
+ /// Gets or sets a value that indicates whether to read extension data when deserializing the object.
+ ///
+ ///
+ /// true to read extension data when deserializing the object; otherwise, false . The default is true .
+ ///
+ public bool ReadData { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonExtensionDataAttribute()
+ {
+ WriteData = true;
+ ReadData = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonIgnoreAttribute.cs b/Libs/JsonNet/JsonIgnoreAttribute.cs
new file mode 100644
index 0000000..8229299
--- /dev/null
+++ b/Libs/JsonNet/JsonIgnoreAttribute.cs
@@ -0,0 +1,39 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the not to serialize the public field or public read/write property value.
+ ///
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
+ public sealed class JsonIgnoreAttribute : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonObjectAttribute.cs b/Libs/JsonNet/JsonObjectAttribute.cs
new file mode 100644
index 0000000..61fad92
--- /dev/null
+++ b/Libs/JsonNet/JsonObjectAttribute.cs
@@ -0,0 +1,89 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the how to serialize the object.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)]
+ public sealed class JsonObjectAttribute : JsonContainerAttribute
+ {
+ private MemberSerialization _memberSerialization = MemberSerialization.OptOut;
+
+ // yuck. can't set nullable properties on an attribute in C#
+ // have to use this approach to get an unset default state
+ internal Required? _itemRequired;
+
+ ///
+ /// Gets or sets the member serialization.
+ ///
+ /// The member serialization.
+ public MemberSerialization MemberSerialization
+ {
+ get { return _memberSerialization; }
+ set { _memberSerialization = value; }
+ }
+
+ ///
+ /// Gets or sets a value that indicates whether the object's properties are required.
+ ///
+ ///
+ /// A value indicating whether the object's properties are required.
+ ///
+ public Required ItemRequired
+ {
+ get { return _itemRequired ?? default(Required); }
+ set { _itemRequired = value; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonObjectAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified member serialization.
+ ///
+ /// The member serialization.
+ public JsonObjectAttribute(MemberSerialization memberSerialization)
+ {
+ MemberSerialization = memberSerialization;
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified container Id.
+ ///
+ /// The container Id.
+ public JsonObjectAttribute(string id)
+ : base(id)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonPosition.cs b/Libs/JsonNet/JsonPosition.cs
new file mode 100644
index 0000000..7bd879e
--- /dev/null
+++ b/Libs/JsonNet/JsonPosition.cs
@@ -0,0 +1,128 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+ internal enum JsonContainerType
+ {
+ None,
+ Object,
+ Array,
+ Constructor
+ }
+
+ internal struct JsonPosition
+ {
+ private static readonly char[] SpecialCharacters = {'.', ' ', '[', ']', '(', ')'};
+
+ internal JsonContainerType Type;
+ internal int Position;
+ internal string PropertyName;
+ internal bool HasIndex;
+
+ public JsonPosition(JsonContainerType type)
+ {
+ Type = type;
+ HasIndex = TypeHasIndex(type);
+ Position = -1;
+ PropertyName = null;
+ }
+
+ internal void WriteTo(StringBuilder sb)
+ {
+ switch (Type)
+ {
+ case JsonContainerType.Object:
+ if (sb.Length > 0)
+ sb.Append('.');
+
+ string propertyName = PropertyName;
+ if (propertyName.IndexOfAny(SpecialCharacters) != -1)
+ {
+ sb.Append(@"['");
+ sb.Append(propertyName);
+ sb.Append(@"']");
+ }
+ else
+ {
+ sb.Append(propertyName);
+ }
+ break;
+ case JsonContainerType.Array:
+ case JsonContainerType.Constructor:
+ sb.Append('[');
+ sb.Append(Position);
+ sb.Append(']');
+ break;
+ }
+ }
+
+ internal static bool TypeHasIndex(JsonContainerType type)
+ {
+ return (type == JsonContainerType.Array || type == JsonContainerType.Constructor);
+ }
+
+ internal static string BuildPath(IEnumerable positions)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ foreach (JsonPosition state in positions)
+ {
+ state.WriteTo(sb);
+ }
+
+ return sb.ToString();
+ }
+
+ internal static string FormatMessage(IJsonLineInfo lineInfo, string path, string message)
+ {
+ // don't add a fullstop and space when message ends with a new line
+ if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal))
+ {
+ message = message.Trim();
+
+ if (!message.EndsWith('.'))
+ message += ".";
+
+ message += " ";
+ }
+
+ message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path);
+
+ if (lineInfo != null && lineInfo.HasLineInfo())
+ message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition);
+
+ message += ".";
+
+ return message;
+ }
+ }
+}
diff --git a/Libs/JsonNet/JsonPropertyAttribute.cs b/Libs/JsonNet/JsonPropertyAttribute.cs
new file mode 100644
index 0000000..5175f4c
--- /dev/null
+++ b/Libs/JsonNet/JsonPropertyAttribute.cs
@@ -0,0 +1,201 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the to always serialize the member with the specified name.
+ ///
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false)]
+ public sealed class JsonPropertyAttribute : Attribute
+ {
+ // yuck. can't set nullable properties on an attribute in C#
+ // have to use this approach to get an unset default state
+ internal NullValueHandling? _nullValueHandling;
+ internal DefaultValueHandling? _defaultValueHandling;
+ internal ReferenceLoopHandling? _referenceLoopHandling;
+ internal ObjectCreationHandling? _objectCreationHandling;
+ internal TypeNameHandling? _typeNameHandling;
+ internal bool? _isReference;
+ internal int? _order;
+ internal Required? _required;
+ internal bool? _itemIsReference;
+ internal ReferenceLoopHandling? _itemReferenceLoopHandling;
+ internal TypeNameHandling? _itemTypeNameHandling;
+
+ ///
+ /// Gets or sets the converter used when serializing the property's collection items.
+ ///
+ /// The collection's items converter.
+ public Type ItemConverterType { get; set; }
+
+ ///
+ /// The parameter list to use when constructing the JsonConverter described by ItemConverterType.
+ /// If null, the default constructor is used.
+ /// When non-null, there must be a constructor defined in the JsonConverter that exactly matches the number,
+ /// order, and type of these parameters.
+ ///
+ ///
+ /// [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })]
+ ///
+ public object[] ItemConverterParameters { get; set; }
+
+ ///
+ /// Gets or sets the null value handling used when serializing this property.
+ ///
+ /// The null value handling.
+ public NullValueHandling NullValueHandling
+ {
+ get { return _nullValueHandling ?? default(NullValueHandling); }
+ set { _nullValueHandling = value; }
+ }
+
+ ///
+ /// Gets or sets the default value handling used when serializing this property.
+ ///
+ /// The default value handling.
+ public DefaultValueHandling DefaultValueHandling
+ {
+ get { return _defaultValueHandling ?? default(DefaultValueHandling); }
+ set { _defaultValueHandling = value; }
+ }
+
+ ///
+ /// Gets or sets the reference loop handling used when serializing this property.
+ ///
+ /// The reference loop handling.
+ public ReferenceLoopHandling ReferenceLoopHandling
+ {
+ get { return _referenceLoopHandling ?? default(ReferenceLoopHandling); }
+ set { _referenceLoopHandling = value; }
+ }
+
+ ///
+ /// Gets or sets the object creation handling used when deserializing this property.
+ ///
+ /// The object creation handling.
+ public ObjectCreationHandling ObjectCreationHandling
+ {
+ get { return _objectCreationHandling ?? default(ObjectCreationHandling); }
+ set { _objectCreationHandling = value; }
+ }
+
+ ///
+ /// Gets or sets the type name handling used when serializing this property.
+ ///
+ /// The type name handling.
+ public TypeNameHandling TypeNameHandling
+ {
+ get { return _typeNameHandling ?? default(TypeNameHandling); }
+ set { _typeNameHandling = value; }
+ }
+
+ ///
+ /// Gets or sets whether this property's value is serialized as a reference.
+ ///
+ /// Whether this property's value is serialized as a reference.
+ public bool IsReference
+ {
+ get { return _isReference ?? default(bool); }
+ set { _isReference = value; }
+ }
+
+ ///
+ /// Gets or sets the order of serialization and deserialization of a member.
+ ///
+ /// The numeric order of serialization or deserialization.
+ public int Order
+ {
+ get { return _order ?? default(int); }
+ set { _order = value; }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether this property is required.
+ ///
+ ///
+ /// A value indicating whether this property is required.
+ ///
+ public Required Required
+ {
+ get { return _required ?? Required.Default; }
+ set { _required = value; }
+ }
+
+ ///
+ /// Gets or sets the name of the property.
+ ///
+ /// The name of the property.
+ public string PropertyName { get; set; }
+
+ ///
+ /// Gets or sets the the reference loop handling used when serializing the property's collection items.
+ ///
+ /// The collection's items reference loop handling.
+ public ReferenceLoopHandling ItemReferenceLoopHandling
+ {
+ get { return _itemReferenceLoopHandling ?? default(ReferenceLoopHandling); }
+ set { _itemReferenceLoopHandling = value; }
+ }
+
+ ///
+ /// Gets or sets the the type name handling used when serializing the property's collection items.
+ ///
+ /// The collection's items type name handling.
+ public TypeNameHandling ItemTypeNameHandling
+ {
+ get { return _itemTypeNameHandling ?? default(TypeNameHandling); }
+ set { _itemTypeNameHandling = value; }
+ }
+
+ ///
+ /// Gets or sets whether this property's collection items are serialized as a reference.
+ ///
+ /// Whether this property's collection items are serialized as a reference.
+ public bool ItemIsReference
+ {
+ get { return _itemIsReference ?? default(bool); }
+ set { _itemIsReference = value; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonPropertyAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified name.
+ ///
+ /// Name of the property.
+ public JsonPropertyAttribute(string propertyName)
+ {
+ PropertyName = propertyName;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonReader.cs b/Libs/JsonNet/JsonReader.cs
new file mode 100644
index 0000000..c14c4da
--- /dev/null
+++ b/Libs/JsonNet/JsonReader.cs
@@ -0,0 +1,1040 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Globalization;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
+ ///
+ public abstract class JsonReader : IDisposable
+ {
+ ///
+ /// Specifies the state of the reader.
+ ///
+ protected internal enum State
+ {
+ ///
+ /// The Read method has not been called.
+ ///
+ Start,
+
+ ///
+ /// The end of the file has been reached successfully.
+ ///
+ Complete,
+
+ ///
+ /// Reader is at a property.
+ ///
+ Property,
+
+ ///
+ /// Reader is at the start of an object.
+ ///
+ ObjectStart,
+
+ ///
+ /// Reader is in an object.
+ ///
+ Object,
+
+ ///
+ /// Reader is at the start of an array.
+ ///
+ ArrayStart,
+
+ ///
+ /// Reader is in an array.
+ ///
+ Array,
+
+ ///
+ /// The Close method has been called.
+ ///
+ Closed,
+
+ ///
+ /// Reader has just read a value.
+ ///
+ PostValue,
+
+ ///
+ /// Reader is at the start of a constructor.
+ ///
+ ConstructorStart,
+
+ ///
+ /// Reader in a constructor.
+ ///
+ Constructor,
+
+ ///
+ /// An error occurred that prevents the read operation from continuing.
+ ///
+ Error,
+
+ ///
+ /// The end of the file has been reached successfully.
+ ///
+ Finished
+ }
+
+ // current Token data
+ private JsonToken _tokenType;
+ private object _value;
+ internal char _quoteChar;
+ internal State _currentState;
+ internal ReadType _readType;
+ private JsonPosition _currentPosition;
+ private CultureInfo _culture;
+ private DateTimeZoneHandling _dateTimeZoneHandling;
+ private int? _maxDepth;
+ private bool _hasExceededMaxDepth;
+ internal DateParseHandling _dateParseHandling;
+ internal FloatParseHandling _floatParseHandling;
+ private string _dateFormatString;
+ private readonly List _stack;
+
+ ///
+ /// Gets the current reader state.
+ ///
+ /// The current reader state.
+ protected State CurrentState
+ {
+ get { return _currentState; }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the underlying stream or
+ /// should be closed when the reader is closed.
+ ///
+ ///
+ /// true to close the underlying stream or when
+ /// the reader is closed; otherwise false. The default is true.
+ ///
+ public bool CloseInput { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether multiple pieces of JSON content can
+ /// be read from a continuous stream 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.
+ ///
+ public virtual char QuoteChar
+ {
+ get { return _quoteChar; }
+ protected internal set { _quoteChar = value; }
+ }
+
+ ///
+ /// Get or set how time zones are handling when reading JSON.
+ ///
+ public DateTimeZoneHandling DateTimeZoneHandling
+ {
+ get { return _dateTimeZoneHandling; }
+ set { _dateTimeZoneHandling = value; }
+ }
+
+ ///
+ /// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
+ ///
+ public DateParseHandling DateParseHandling
+ {
+ get { return _dateParseHandling; }
+ set { _dateParseHandling = value; }
+ }
+
+ ///
+ /// Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
+ ///
+ public FloatParseHandling FloatParseHandling
+ {
+ get { return _floatParseHandling; }
+ set { _floatParseHandling = value; }
+ }
+
+ ///
+ /// Get or set how custom date formatted strings are parsed when reading JSON.
+ ///
+ public string DateFormatString
+ {
+ get { return _dateFormatString; }
+ set { _dateFormatString = value; }
+ }
+
+ ///
+ /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
+ ///
+ public int? MaxDepth
+ {
+ get { return _maxDepth; }
+ set
+ {
+ if (value <= 0)
+ throw new ArgumentException("Value must be positive.", "value");
+
+ _maxDepth = value;
+ }
+ }
+
+ ///
+ /// Gets the type of the current JSON token.
+ ///
+ public virtual JsonToken TokenType
+ {
+ get { return _tokenType; }
+ }
+
+ ///
+ /// Gets the text value of the current JSON token.
+ ///
+ public virtual object Value
+ {
+ get { return _value; }
+ }
+
+ ///
+ /// Gets The Common Language Runtime (CLR) type for the current JSON token.
+ ///
+ public virtual Type ValueType
+ {
+ get { return (_value != null) ? _value.GetType() : null; }
+ }
+
+ ///
+ /// Gets the depth of the current token in the JSON document.
+ ///
+ /// The depth of the current token in the JSON document.
+ public virtual int Depth
+ {
+ get
+ {
+ int depth = _stack.Count;
+ if (IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
+ return depth;
+ else
+ return depth + 1;
+ }
+ }
+
+ ///
+ /// Gets the path of the current JSON token.
+ ///
+ public virtual string Path
+ {
+ get
+ {
+ if (_currentPosition.Type == JsonContainerType.None)
+ return string.Empty;
+
+ bool insideContainer = (_currentState != State.ArrayStart
+ && _currentState != State.ConstructorStart
+ && _currentState != State.ObjectStart);
+
+ IEnumerable positions = (!insideContainer)
+ ? _stack
+ : _stack.Concat(new[] { _currentPosition });
+
+ return JsonPosition.BuildPath(positions);
+ }
+ }
+
+ ///
+ /// Gets or sets the culture used when reading JSON. Defaults to .
+ ///
+ public CultureInfo Culture
+ {
+ get { return _culture ?? CultureInfo.InvariantCulture; }
+ set { _culture = value; }
+ }
+
+ internal JsonPosition GetPosition(int depth)
+ {
+ if (depth < _stack.Count)
+ return _stack[depth];
+
+ return _currentPosition;
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified .
+ ///
+ protected JsonReader()
+ {
+ _currentState = State.Start;
+ _stack = new List(4);
+ _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
+ _dateParseHandling = DateParseHandling.DateTime;
+ _floatParseHandling = FloatParseHandling.Double;
+
+ CloseInput = true;
+ }
+
+ private void Push(JsonContainerType value)
+ {
+ UpdateScopeWithFinishedValue();
+
+ if (_currentPosition.Type == JsonContainerType.None)
+ {
+ _currentPosition = new JsonPosition(value);
+ }
+ else
+ {
+ _stack.Add(_currentPosition);
+ _currentPosition = new JsonPosition(value);
+
+ // this is a little hacky because Depth increases when first property/value is written but only testing here is faster/simpler
+ if (_maxDepth != null && Depth + 1 > _maxDepth && !_hasExceededMaxDepth)
+ {
+ _hasExceededMaxDepth = true;
+ throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth));
+ }
+ }
+ }
+
+ private JsonContainerType Pop()
+ {
+ JsonPosition oldPosition;
+ if (_stack.Count > 0)
+ {
+ oldPosition = _currentPosition;
+ _currentPosition = _stack[_stack.Count - 1];
+ _stack.RemoveAt(_stack.Count - 1);
+ }
+ else
+ {
+ oldPosition = _currentPosition;
+ _currentPosition = new JsonPosition();
+ }
+
+ if (_maxDepth != null && Depth <= _maxDepth)
+ _hasExceededMaxDepth = false;
+
+ return oldPosition.Type;
+ }
+
+ private JsonContainerType Peek()
+ {
+ return _currentPosition.Type;
+ }
+
+ ///
+ /// Reads the next JSON token from the stream.
+ ///
+ /// true if the next token was read successfully; false if there are no more tokens to read.
+ public abstract bool Read();
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public abstract int? ReadAsInt32();
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public abstract string ReadAsString();
+
+ ///
+ /// Reads the next JSON token from the stream as a [].
+ ///
+ /// A [] or a null reference if the next JSON token is null. This method will return null at the end of an array.
+ public abstract byte[] ReadAsBytes();
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public abstract decimal? ReadAsDecimal();
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public abstract DateTime? ReadAsDateTime();
+
+#if !NET20
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public abstract DateTimeOffset? ReadAsDateTimeOffset();
+#endif
+
+ internal virtual bool ReadInternal()
+ {
+ throw new NotImplementedException();
+ }
+
+#if !NET20
+ internal DateTimeOffset? ReadAsDateTimeOffsetInternal()
+ {
+ _readType = ReadType.ReadAsDateTimeOffset;
+
+ JsonToken t;
+
+ do
+ {
+ if (!ReadInternal())
+ {
+ SetToken(JsonToken.None);
+ return null;
+ }
+ else
+ {
+ t = TokenType;
+ }
+ } while (t == JsonToken.Comment);
+
+ if (t == JsonToken.Date)
+ {
+ if (Value is DateTime)
+ SetToken(JsonToken.Date, new DateTimeOffset((DateTime)Value), false);
+
+ return (DateTimeOffset)Value;
+ }
+
+ if (t == JsonToken.Null)
+ return null;
+
+ if (t == JsonToken.String)
+ {
+ string s = (string)Value;
+ if (string.IsNullOrEmpty(s))
+ {
+ SetToken(JsonToken.Null);
+ return null;
+ }
+
+ object temp;
+ DateTimeOffset dt;
+ if (DateTimeUtils.TryParseDateTime(s, DateParseHandling.DateTimeOffset, DateTimeZoneHandling, _dateFormatString, Culture, out temp))
+ {
+ dt = (DateTimeOffset)temp;
+ SetToken(JsonToken.Date, dt, false);
+ return dt;
+ }
+
+ if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
+ {
+ SetToken(JsonToken.Date, dt, false);
+ return dt;
+ }
+
+ throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
+ }
+
+ if (t == JsonToken.EndArray)
+ return null;
+
+ throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+ }
+#endif
+
+ internal byte[] ReadAsBytesInternal()
+ {
+ _readType = ReadType.ReadAsBytes;
+
+ JsonToken t;
+
+ do
+ {
+ if (!ReadInternal())
+ {
+ SetToken(JsonToken.None);
+ return null;
+ }
+ else
+ {
+ t = TokenType;
+ }
+ } while (t == JsonToken.Comment);
+
+ if (IsWrappedInTypeObject())
+ {
+ byte[] data = ReadAsBytes();
+ ReadInternal();
+ SetToken(JsonToken.Bytes, data, false);
+ return data;
+ }
+
+ // attempt to convert possible base 64 string to bytes
+ if (t == JsonToken.String)
+ {
+ string s = (string)Value;
+
+ byte[] data;
+
+ Guid g;
+ if (s.Length == 0)
+ {
+ data = new byte[0];
+ }
+ else if (ConvertUtils.TryConvertGuid(s, out g))
+ {
+ data = g.ToByteArray();
+ }
+ else
+ {
+ data = Convert.FromBase64String(s);
+ }
+
+ SetToken(JsonToken.Bytes, data, false);
+ return data;
+ }
+
+ if (t == JsonToken.Null)
+ return null;
+
+ if (t == JsonToken.Bytes)
+ {
+ if (ValueType == typeof(Guid))
+ {
+ byte[] data = ((Guid)Value).ToByteArray();
+ SetToken(JsonToken.Bytes, data, false);
+ return data;
+ }
+
+ return (byte[])Value;
+ }
+
+ if (t == JsonToken.StartArray)
+ {
+ List data = new List();
+
+ while (ReadInternal())
+ {
+ t = TokenType;
+ switch (t)
+ {
+ case JsonToken.Integer:
+ data.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
+ break;
+ case JsonToken.EndArray:
+ byte[] d = data.ToArray();
+ SetToken(JsonToken.Bytes, d, false);
+ return d;
+ case JsonToken.Comment:
+ // skip
+ break;
+ default:
+ throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+ }
+ }
+
+ throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
+ }
+
+ if (t == JsonToken.EndArray)
+ return null;
+
+ throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+ }
+
+ internal decimal? ReadAsDecimalInternal()
+ {
+ _readType = ReadType.ReadAsDecimal;
+
+ JsonToken t;
+
+ do
+ {
+ if (!ReadInternal())
+ {
+ SetToken(JsonToken.None);
+ return null;
+ }
+ else
+ {
+ t = TokenType;
+ }
+ } while (t == JsonToken.Comment);
+
+ if (t == JsonToken.Integer || t == JsonToken.Float)
+ {
+ if (!(Value is decimal))
+ SetToken(JsonToken.Float, Convert.ToDecimal(Value, CultureInfo.InvariantCulture), false);
+
+ return (decimal)Value;
+ }
+
+ if (t == JsonToken.Null)
+ return null;
+
+ if (t == JsonToken.String)
+ {
+ string s = (string)Value;
+ if (string.IsNullOrEmpty(s))
+ {
+ SetToken(JsonToken.Null);
+ return null;
+ }
+
+ decimal d;
+ if (decimal.TryParse(s, NumberStyles.Number, Culture, out d))
+ {
+ SetToken(JsonToken.Float, d, false);
+ return d;
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
+ }
+ }
+
+ if (t == JsonToken.EndArray)
+ return null;
+
+ throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+ }
+
+ internal int? ReadAsInt32Internal()
+ {
+ _readType = ReadType.ReadAsInt32;
+
+ JsonToken t;
+
+ do
+ {
+ if (!ReadInternal())
+ {
+ SetToken(JsonToken.None);
+ return null;
+ }
+ else
+ {
+ t = TokenType;
+ }
+ } while (t == JsonToken.Comment);
+
+ if (t == JsonToken.Integer || t == JsonToken.Float)
+ {
+ if (!(Value is int))
+ SetToken(JsonToken.Integer, Convert.ToInt32(Value, CultureInfo.InvariantCulture), false);
+
+ return (int)Value;
+ }
+
+ if (t == JsonToken.Null)
+ return null;
+
+ int i;
+ if (t == JsonToken.String)
+ {
+ string s = (string)Value;
+ if (string.IsNullOrEmpty(s))
+ {
+ SetToken(JsonToken.Null);
+ return null;
+ }
+
+ if (int.TryParse(s, NumberStyles.Integer, Culture, out i))
+ {
+ SetToken(JsonToken.Integer, i, false);
+ return i;
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
+ }
+ }
+
+ if (t == JsonToken.EndArray)
+ return null;
+
+ throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
+ }
+
+ internal string ReadAsStringInternal()
+ {
+ _readType = ReadType.ReadAsString;
+
+ JsonToken t;
+
+ do
+ {
+ if (!ReadInternal())
+ {
+ SetToken(JsonToken.None);
+ return null;
+ }
+ else
+ {
+ t = TokenType;
+ }
+ } while (t == JsonToken.Comment);
+
+ if (t == JsonToken.String)
+ return (string)Value;
+
+ if (t == JsonToken.Null)
+ return null;
+
+ if (IsPrimitiveToken(t))
+ {
+ if (Value != null)
+ {
+ string s;
+ if (Value is IFormattable)
+ s = ((IFormattable)Value).ToString(null, Culture);
+ else
+ s = Value.ToString();
+
+ SetToken(JsonToken.String, s, false);
+ return s;
+ }
+ }
+
+ if (t == JsonToken.EndArray)
+ return null;
+
+ throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+ }
+
+ internal DateTime? ReadAsDateTimeInternal()
+ {
+ _readType = ReadType.ReadAsDateTime;
+
+ do
+ {
+ if (!ReadInternal())
+ {
+ SetToken(JsonToken.None);
+ return null;
+ }
+ } while (TokenType == JsonToken.Comment);
+
+ if (TokenType == JsonToken.Date)
+ return (DateTime)Value;
+
+ if (TokenType == JsonToken.Null)
+ return null;
+
+ if (TokenType == JsonToken.String)
+ {
+ string s = (string)Value;
+ if (string.IsNullOrEmpty(s))
+ {
+ SetToken(JsonToken.Null);
+ return null;
+ }
+
+ DateTime dt;
+ object temp;
+ if (DateTimeUtils.TryParseDateTime(s, DateParseHandling.DateTime, DateTimeZoneHandling, _dateFormatString, Culture, out temp))
+ {
+ dt = (DateTime)temp;
+ dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
+ SetToken(JsonToken.Date, dt, false);
+ return dt;
+ }
+
+ if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
+ {
+ dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
+ SetToken(JsonToken.Date, dt, false);
+ return dt;
+ }
+
+ throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
+ }
+
+ if (TokenType == JsonToken.EndArray)
+ return null;
+
+ throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
+ }
+
+ private bool IsWrappedInTypeObject()
+ {
+ _readType = ReadType.Read;
+
+ if (TokenType == JsonToken.StartObject)
+ {
+ if (!ReadInternal())
+ throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
+
+ if (Value.ToString() == JsonTypeReflector.TypePropertyName)
+ {
+ ReadInternal();
+ if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal))
+ {
+ ReadInternal();
+ if (Value.ToString() == JsonTypeReflector.ValuePropertyName)
+ {
+ return true;
+ }
+ }
+ }
+
+ throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject));
+ }
+
+ return false;
+ }
+
+ ///
+ /// Skips the children of the current token.
+ ///
+ public void Skip()
+ {
+ if (TokenType == JsonToken.PropertyName)
+ Read();
+
+ if (IsStartToken(TokenType))
+ {
+ int depth = Depth;
+
+ while (Read() && (depth < Depth))
+ {
+ }
+ }
+ }
+
+ ///
+ /// Sets the current token.
+ ///
+ /// The new token.
+ protected void SetToken(JsonToken newToken)
+ {
+ SetToken(newToken, null, true);
+ }
+
+ ///
+ /// Sets the current token and value.
+ ///
+ /// The new token.
+ /// The value.
+ protected void SetToken(JsonToken newToken, object value)
+ {
+ SetToken(newToken, value, true);
+ }
+
+ internal void SetToken(JsonToken newToken, object value, bool updateIndex)
+ {
+ _tokenType = newToken;
+ _value = value;
+
+ switch (newToken)
+ {
+ case JsonToken.StartObject:
+ _currentState = State.ObjectStart;
+ Push(JsonContainerType.Object);
+ break;
+ case JsonToken.StartArray:
+ _currentState = State.ArrayStart;
+ Push(JsonContainerType.Array);
+ break;
+ case JsonToken.StartConstructor:
+ _currentState = State.ConstructorStart;
+ Push(JsonContainerType.Constructor);
+ break;
+ case JsonToken.EndObject:
+ ValidateEnd(JsonToken.EndObject);
+ break;
+ case JsonToken.EndArray:
+ ValidateEnd(JsonToken.EndArray);
+ break;
+ case JsonToken.EndConstructor:
+ ValidateEnd(JsonToken.EndConstructor);
+ break;
+ case JsonToken.PropertyName:
+ _currentState = State.Property;
+
+ _currentPosition.PropertyName = (string)value;
+ break;
+ case JsonToken.Undefined:
+ case JsonToken.Integer:
+ case JsonToken.Float:
+ case JsonToken.Boolean:
+ case JsonToken.Null:
+ case JsonToken.Date:
+ case JsonToken.String:
+ case JsonToken.Raw:
+ case JsonToken.Bytes:
+ SetPostValueState(updateIndex);
+ break;
+ }
+ }
+
+ internal void SetPostValueState(bool updateIndex)
+ {
+ if (Peek() != JsonContainerType.None)
+ _currentState = State.PostValue;
+ else
+ SetFinished();
+
+ if (updateIndex)
+ UpdateScopeWithFinishedValue();
+ }
+
+ private void UpdateScopeWithFinishedValue()
+ {
+ if (_currentPosition.HasIndex)
+ _currentPosition.Position++;
+ }
+
+ private void ValidateEnd(JsonToken endToken)
+ {
+ JsonContainerType currentObject = Pop();
+
+ if (GetTypeForCloseToken(endToken) != currentObject)
+ throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, currentObject));
+
+ if (Peek() != JsonContainerType.None)
+ _currentState = State.PostValue;
+ else
+ SetFinished();
+ }
+
+ ///
+ /// Sets the state based on current token type.
+ ///
+ protected void SetStateBasedOnCurrent()
+ {
+ JsonContainerType currentObject = Peek();
+
+ switch (currentObject)
+ {
+ case JsonContainerType.Object:
+ _currentState = State.Object;
+ break;
+ case JsonContainerType.Array:
+ _currentState = State.Array;
+ break;
+ case JsonContainerType.Constructor:
+ _currentState = State.Constructor;
+ break;
+ case JsonContainerType.None:
+ 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)
+ {
+ case JsonToken.Integer:
+ case JsonToken.Float:
+ case JsonToken.String:
+ case JsonToken.Boolean:
+ case JsonToken.Undefined:
+ case JsonToken.Null:
+ case JsonToken.Date:
+ case JsonToken.Bytes:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ internal static bool IsStartToken(JsonToken token)
+ {
+ switch (token)
+ {
+ case JsonToken.StartObject:
+ case JsonToken.StartArray:
+ case JsonToken.StartConstructor:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private JsonContainerType GetTypeForCloseToken(JsonToken token)
+ {
+ switch (token)
+ {
+ case JsonToken.EndObject:
+ return JsonContainerType.Object;
+ case JsonToken.EndArray:
+ return JsonContainerType.Array;
+ case JsonToken.EndConstructor:
+ return JsonContainerType.Constructor;
+ default:
+ throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token));
+ }
+ }
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ void IDisposable.Dispose()
+ {
+ Dispose(true);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_currentState != State.Closed && disposing)
+ Close();
+ }
+
+ ///
+ /// Changes the to Closed.
+ ///
+ public virtual void Close()
+ {
+ _currentState = State.Closed;
+ _tokenType = JsonToken.None;
+ _value = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonReaderException.cs b/Libs/JsonNet/JsonReaderException.cs
new file mode 100644
index 0000000..034a7e5
--- /dev/null
+++ b/Libs/JsonNet/JsonReaderException.cs
@@ -0,0 +1,139 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using System.Runtime.Serialization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// The exception thrown when an error occurs while reading Json text.
+ ///
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+ [Serializable]
+#endif
+ public class JsonReaderException : JsonException
+ {
+ ///
+ /// Gets the line number indicating where the error occurred.
+ ///
+ /// The line number indicating where the error occurred.
+ public int LineNumber { get; private set; }
+
+ ///
+ /// Gets the line position indicating where the error occurred.
+ ///
+ /// The line position indicating where the error occurred.
+ public int LinePosition { get; private set; }
+
+ ///
+ /// Gets the path to the JSON where the error occurred.
+ ///
+ /// The path to the JSON where the error occurred.
+ public string Path { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonReaderException()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a specified error message.
+ ///
+ /// The error message that explains the reason for the exception.
+ public JsonReaderException(string message)
+ : base(message)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+ ///
+ /// The error message that explains the reason for the exception.
+ /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.
+ public JsonReaderException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ /// The parameter is null.
+ /// The class name is null or is zero (0).
+ public JsonReaderException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+#endif
+
+ internal JsonReaderException(string message, Exception innerException, string path, int lineNumber, int linePosition)
+ : base(message, innerException)
+ {
+ Path = path;
+ LineNumber = lineNumber;
+ LinePosition = linePosition;
+ }
+
+ internal static JsonReaderException Create(JsonReader reader, string message)
+ {
+ return Create(reader, message, null);
+ }
+
+ internal static JsonReaderException Create(JsonReader reader, string message, Exception ex)
+ {
+ return Create(reader as IJsonLineInfo, reader.Path, message, ex);
+ }
+
+ internal static JsonReaderException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex)
+ {
+ message = JsonPosition.FormatMessage(lineInfo, path, message);
+
+ int lineNumber;
+ int linePosition;
+ if (lineInfo != null && lineInfo.HasLineInfo())
+ {
+ lineNumber = lineInfo.LineNumber;
+ linePosition = lineInfo.LinePosition;
+ }
+ else
+ {
+ lineNumber = 0;
+ linePosition = 0;
+ }
+
+ return new JsonReaderException(message, ex, path, lineNumber, linePosition);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonSerializationException.cs b/Libs/JsonNet/JsonSerializationException.cs
new file mode 100644
index 0000000..2c1099f
--- /dev/null
+++ b/Libs/JsonNet/JsonSerializationException.cs
@@ -0,0 +1,100 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// The exception thrown when an error occurs during Json serialization or deserialization.
+ ///
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ [Serializable]
+#endif
+ public class JsonSerializationException : JsonException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonSerializationException()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a specified error message.
+ ///
+ /// The error message that explains the reason for the exception.
+ public JsonSerializationException(string message)
+ : base(message)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+ ///
+ /// The error message that explains the reason for the exception.
+ /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.
+ public JsonSerializationException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ /// The parameter is null.
+ /// The class name is null or is zero (0).
+ public JsonSerializationException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+#endif
+
+ internal static JsonSerializationException Create(JsonReader reader, string message)
+ {
+ return Create(reader, message, null);
+ }
+
+ internal static JsonSerializationException Create(JsonReader reader, string message, Exception ex)
+ {
+ return Create(reader as IJsonLineInfo, reader.Path, message, ex);
+ }
+
+ internal static JsonSerializationException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex)
+ {
+ message = JsonPosition.FormatMessage(lineInfo, path, message);
+
+ return new JsonSerializationException(message, ex);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonSerializer.cs b/Libs/JsonNet/JsonSerializer.cs
new file mode 100644
index 0000000..10c4297
--- /dev/null
+++ b/Libs/JsonNet/JsonSerializer.cs
@@ -0,0 +1,987 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Runtime.Serialization.Formatters;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+using System.Runtime.Serialization;
+using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Serializes and deserializes objects into and from the JSON format.
+ /// The enables you to control how objects are encoded into JSON.
+ ///
+ public class JsonSerializer
+ {
+ internal TypeNameHandling _typeNameHandling;
+ internal FormatterAssemblyStyle _typeNameAssemblyFormat;
+ internal PreserveReferencesHandling _preserveReferencesHandling;
+ internal ReferenceLoopHandling _referenceLoopHandling;
+ internal MissingMemberHandling _missingMemberHandling;
+ internal ObjectCreationHandling _objectCreationHandling;
+ internal NullValueHandling _nullValueHandling;
+ internal DefaultValueHandling _defaultValueHandling;
+ internal ConstructorHandling _constructorHandling;
+ internal MetadataPropertyHandling _metadataPropertyHandling;
+ internal JsonConverterCollection _converters;
+ internal IContractResolver _contractResolver;
+ internal ITraceWriter _traceWriter;
+ internal SerializationBinder _binder;
+ internal StreamingContext _context;
+ private IReferenceResolver _referenceResolver;
+
+ private Formatting? _formatting;
+ private DateFormatHandling? _dateFormatHandling;
+ private DateTimeZoneHandling? _dateTimeZoneHandling;
+ private DateParseHandling? _dateParseHandling;
+ private FloatFormatHandling? _floatFormatHandling;
+ private FloatParseHandling? _floatParseHandling;
+ private StringEscapeHandling? _stringEscapeHandling;
+ private CultureInfo _culture;
+ private int? _maxDepth;
+ private bool _maxDepthSet;
+ private bool? _checkAdditionalContent;
+ private string _dateFormatString;
+ private bool _dateFormatStringSet;
+
+ ///
+ /// Occurs when the errors during serialization and deserialization.
+ ///
+ public virtual event EventHandler Error;
+
+ ///
+ /// Gets or sets the used by the serializer when resolving references.
+ ///
+ public virtual IReferenceResolver ReferenceResolver
+ {
+ get { return GetReferenceResolver(); }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value", "Reference resolver cannot be null.");
+
+ _referenceResolver = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the used by the serializer when resolving type names.
+ ///
+ public virtual SerializationBinder Binder
+ {
+ get { return _binder; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value", "Serialization binder cannot be null.");
+
+ _binder = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the used by the serializer when writing trace messages.
+ ///
+ /// The trace writer.
+ public virtual ITraceWriter TraceWriter
+ {
+ get { return _traceWriter; }
+ set { _traceWriter = value; }
+ }
+
+ ///
+ /// Gets or sets how type name writing and reading is handled by the serializer.
+ ///
+ public virtual TypeNameHandling TypeNameHandling
+ {
+ get { return _typeNameHandling; }
+ set
+ {
+ if (value < TypeNameHandling.None || value > TypeNameHandling.Auto)
+ throw new ArgumentOutOfRangeException("value");
+
+ _typeNameHandling = value;
+ }
+ }
+
+ ///
+ /// Gets or sets how a type name assembly is written and resolved by the serializer.
+ ///
+ /// The type name assembly format.
+ public virtual FormatterAssemblyStyle TypeNameAssemblyFormat
+ {
+ get { return _typeNameAssemblyFormat; }
+ set
+ {
+ if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full)
+ throw new ArgumentOutOfRangeException("value");
+
+ _typeNameAssemblyFormat = value;
+ }
+ }
+
+ ///
+ /// Gets or sets how object references are preserved by the serializer.
+ ///
+ public virtual PreserveReferencesHandling PreserveReferencesHandling
+ {
+ get { return _preserveReferencesHandling; }
+ set
+ {
+ if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All)
+ throw new ArgumentOutOfRangeException("value");
+
+ _preserveReferencesHandling = value;
+ }
+ }
+
+ ///
+ /// Get or set how reference loops (e.g. a class referencing itself) is handled.
+ ///
+ public virtual ReferenceLoopHandling ReferenceLoopHandling
+ {
+ get { return _referenceLoopHandling; }
+ set
+ {
+ if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize)
+ throw new ArgumentOutOfRangeException("value");
+
+ _referenceLoopHandling = value;
+ }
+ }
+
+ ///
+ /// Get or set how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
+ ///
+ public virtual MissingMemberHandling MissingMemberHandling
+ {
+ get { return _missingMemberHandling; }
+ set
+ {
+ if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error)
+ throw new ArgumentOutOfRangeException("value");
+
+ _missingMemberHandling = value;
+ }
+ }
+
+ ///
+ /// Get or set how null values are handled during serialization and deserialization.
+ ///
+ public virtual NullValueHandling NullValueHandling
+ {
+ get { return _nullValueHandling; }
+ set
+ {
+ if (value < NullValueHandling.Include || value > NullValueHandling.Ignore)
+ throw new ArgumentOutOfRangeException("value");
+
+ _nullValueHandling = value;
+ }
+ }
+
+ ///
+ /// Get or set how null default are handled during serialization and deserialization.
+ ///
+ public virtual DefaultValueHandling DefaultValueHandling
+ {
+ get { return _defaultValueHandling; }
+ set
+ {
+ if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate)
+ throw new ArgumentOutOfRangeException("value");
+
+ _defaultValueHandling = value;
+ }
+ }
+
+ ///
+ /// Gets or sets how objects are created during deserialization.
+ ///
+ /// The object creation handling.
+ public virtual ObjectCreationHandling ObjectCreationHandling
+ {
+ get { return _objectCreationHandling; }
+ set
+ {
+ if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace)
+ throw new ArgumentOutOfRangeException("value");
+
+ _objectCreationHandling = value;
+ }
+ }
+
+ ///
+ /// Gets or sets how constructors are used during deserialization.
+ ///
+ /// The constructor handling.
+ public virtual ConstructorHandling ConstructorHandling
+ {
+ get { return _constructorHandling; }
+ set
+ {
+ if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor)
+ throw new ArgumentOutOfRangeException("value");
+
+ _constructorHandling = value;
+ }
+ }
+
+ ///
+ /// Gets or sets how metadata properties are used during deserialization.
+ ///
+ /// The metadata properties handling.
+ public virtual MetadataPropertyHandling MetadataPropertyHandling
+ {
+ get { return _metadataPropertyHandling; }
+ set
+ {
+ if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore)
+ throw new ArgumentOutOfRangeException("value");
+
+ _metadataPropertyHandling = value;
+ }
+ }
+
+ ///
+ /// Gets a collection that will be used during serialization.
+ ///
+ /// Collection that will be used during serialization.
+ public virtual JsonConverterCollection Converters
+ {
+ get
+ {
+ if (_converters == null)
+ _converters = new JsonConverterCollection();
+
+ return _converters;
+ }
+ }
+
+ ///
+ /// Gets or sets the contract resolver used by the serializer when
+ /// serializing .NET objects to JSON and vice versa.
+ ///
+ public virtual IContractResolver ContractResolver
+ {
+ get { return _contractResolver; }
+ set { _contractResolver = value ?? DefaultContractResolver.Instance; }
+ }
+
+ ///
+ /// Gets or sets the used by the serializer when invoking serialization callback methods.
+ ///
+ /// The context.
+ public virtual StreamingContext Context
+ {
+ get { return _context; }
+ set { _context = value; }
+ }
+
+ ///
+ /// Indicates how JSON text output is formatted.
+ ///
+ public virtual Formatting Formatting
+ {
+ get { return _formatting ?? JsonSerializerSettings.DefaultFormatting; }
+ set { _formatting = value; }
+ }
+
+ ///
+ /// Get or set how dates are written to JSON text.
+ ///
+ public virtual DateFormatHandling DateFormatHandling
+ {
+ get { return _dateFormatHandling ?? JsonSerializerSettings.DefaultDateFormatHandling; }
+ set { _dateFormatHandling = value; }
+ }
+
+ ///
+ /// Get or set how time zones are handling during serialization and deserialization.
+ ///
+ public virtual DateTimeZoneHandling DateTimeZoneHandling
+ {
+ get { return _dateTimeZoneHandling ?? JsonSerializerSettings.DefaultDateTimeZoneHandling; }
+ set { _dateTimeZoneHandling = value; }
+ }
+
+ ///
+ /// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
+ ///
+ public virtual DateParseHandling DateParseHandling
+ {
+ get { return _dateParseHandling ?? JsonSerializerSettings.DefaultDateParseHandling; }
+ set { _dateParseHandling = value; }
+ }
+
+ ///
+ /// Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
+ ///
+ public virtual FloatParseHandling FloatParseHandling
+ {
+ get { return _floatParseHandling ?? JsonSerializerSettings.DefaultFloatParseHandling; }
+ set { _floatParseHandling = value; }
+ }
+
+ ///
+ /// Get or set how special floating point numbers, e.g. ,
+ /// and ,
+ /// are written as JSON text.
+ ///
+ public virtual FloatFormatHandling FloatFormatHandling
+ {
+ get { return _floatFormatHandling ?? JsonSerializerSettings.DefaultFloatFormatHandling; }
+ set { _floatFormatHandling = value; }
+ }
+
+ ///
+ /// Get or set how strings are escaped when writing JSON text.
+ ///
+ public virtual StringEscapeHandling StringEscapeHandling
+ {
+ get { return _stringEscapeHandling ?? JsonSerializerSettings.DefaultStringEscapeHandling; }
+ set { _stringEscapeHandling = value; }
+ }
+
+ ///
+ /// Get or set how and values are formatting when writing JSON text.
+ ///
+ public virtual string DateFormatString
+ {
+ get { return _dateFormatString ?? JsonSerializerSettings.DefaultDateFormatString; }
+ set
+ {
+ _dateFormatString = value;
+ _dateFormatStringSet = true;
+ }
+ }
+
+ ///
+ /// Gets or sets the culture used when reading JSON. Defaults to .
+ ///
+ public virtual CultureInfo Culture
+ {
+ get { return _culture ?? JsonSerializerSettings.DefaultCulture; }
+ set { _culture = value; }
+ }
+
+ ///
+ /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
+ ///
+ public virtual int? MaxDepth
+ {
+ get { return _maxDepth; }
+ set
+ {
+ if (value <= 0)
+ throw new ArgumentException("Value must be positive.", "value");
+
+ _maxDepth = value;
+ _maxDepthSet = true;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether there will be a check for additional JSON content after deserializing an object.
+ ///
+ ///
+ /// true if there will be a check for additional JSON content after deserializing an object; otherwise, false .
+ ///
+ public virtual bool CheckAdditionalContent
+ {
+ get { return _checkAdditionalContent ?? JsonSerializerSettings.DefaultCheckAdditionalContent; }
+ set { _checkAdditionalContent = value; }
+ }
+
+ internal bool IsCheckAdditionalContentSet()
+ {
+ return (_checkAdditionalContent != null);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonSerializer()
+ {
+ _referenceLoopHandling = JsonSerializerSettings.DefaultReferenceLoopHandling;
+ _missingMemberHandling = JsonSerializerSettings.DefaultMissingMemberHandling;
+ _nullValueHandling = JsonSerializerSettings.DefaultNullValueHandling;
+ _defaultValueHandling = JsonSerializerSettings.DefaultDefaultValueHandling;
+ _objectCreationHandling = JsonSerializerSettings.DefaultObjectCreationHandling;
+ _preserveReferencesHandling = JsonSerializerSettings.DefaultPreserveReferencesHandling;
+ _constructorHandling = JsonSerializerSettings.DefaultConstructorHandling;
+ _typeNameHandling = JsonSerializerSettings.DefaultTypeNameHandling;
+ _metadataPropertyHandling = JsonSerializerSettings.DefaultMetadataPropertyHandling;
+ _context = JsonSerializerSettings.DefaultContext;
+ _binder = DefaultSerializationBinder.Instance;
+
+ _culture = JsonSerializerSettings.DefaultCulture;
+ _contractResolver = DefaultContractResolver.Instance;
+ }
+
+ ///
+ /// Creates a new instance.
+ /// The will not use default settings.
+ ///
+ ///
+ /// A new instance.
+ /// The will not use default settings.
+ ///
+ public static JsonSerializer Create()
+ {
+ return new JsonSerializer();
+ }
+
+ ///
+ /// Creates a new instance using the specified .
+ /// The will not use default settings.
+ ///
+ /// The settings to be applied to the .
+ ///
+ /// A new instance using the specified .
+ /// The will not use default settings.
+ ///
+ public static JsonSerializer Create(JsonSerializerSettings settings)
+ {
+ JsonSerializer serializer = Create();
+
+ if (settings != null)
+ ApplySerializerSettings(serializer, settings);
+
+ return serializer;
+ }
+
+ ///
+ /// Creates a new instance.
+ /// The will use default settings.
+ ///
+ ///
+ /// A new instance.
+ /// The will use default settings.
+ ///
+ public static JsonSerializer CreateDefault()
+ {
+ // copy static to local variable to avoid concurrency issues
+ Func defaultSettingsCreator = JsonConvert.DefaultSettings;
+ JsonSerializerSettings defaultSettings = (defaultSettingsCreator != null) ? defaultSettingsCreator() : null;
+
+ return Create(defaultSettings);
+ }
+
+ ///
+ /// Creates a new instance using the specified .
+ /// The will use default settings.
+ ///
+ /// The settings to be applied to the .
+ ///
+ /// A new instance using the specified .
+ /// The will use default settings.
+ ///
+ public static JsonSerializer CreateDefault(JsonSerializerSettings settings)
+ {
+ JsonSerializer serializer = CreateDefault();
+ if (settings != null)
+ ApplySerializerSettings(serializer, settings);
+
+ return serializer;
+ }
+
+ private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings)
+ {
+ if (!CollectionUtils.IsNullOrEmpty(settings.Converters))
+ {
+ // insert settings converters at the beginning so they take precedence
+ // if user wants to remove one of the default converters they will have to do it manually
+ for (int i = 0; i < settings.Converters.Count; i++)
+ {
+ serializer.Converters.Insert(i, settings.Converters[i]);
+ }
+ }
+
+ // serializer specific
+ if (settings._typeNameHandling != null)
+ serializer.TypeNameHandling = settings.TypeNameHandling;
+ if (settings._metadataPropertyHandling != null)
+ serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling;
+ if (settings._typeNameAssemblyFormat != null)
+ serializer.TypeNameAssemblyFormat = settings.TypeNameAssemblyFormat;
+ if (settings._preserveReferencesHandling != null)
+ serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling;
+ if (settings._referenceLoopHandling != null)
+ serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling;
+ if (settings._missingMemberHandling != null)
+ serializer.MissingMemberHandling = settings.MissingMemberHandling;
+ if (settings._objectCreationHandling != null)
+ serializer.ObjectCreationHandling = settings.ObjectCreationHandling;
+ if (settings._nullValueHandling != null)
+ serializer.NullValueHandling = settings.NullValueHandling;
+ if (settings._defaultValueHandling != null)
+ serializer.DefaultValueHandling = settings.DefaultValueHandling;
+ if (settings._constructorHandling != null)
+ serializer.ConstructorHandling = settings.ConstructorHandling;
+ if (settings._context != null)
+ serializer.Context = settings.Context;
+ if (settings._checkAdditionalContent != null)
+ serializer._checkAdditionalContent = settings._checkAdditionalContent;
+
+ if (settings.Error != null)
+ serializer.Error += settings.Error;
+
+ if (settings.ContractResolver != null)
+ serializer.ContractResolver = settings.ContractResolver;
+ if (settings.ReferenceResolver != null)
+ serializer.ReferenceResolver = settings.ReferenceResolver;
+ if (settings.TraceWriter != null)
+ serializer.TraceWriter = settings.TraceWriter;
+ if (settings.Binder != null)
+ serializer.Binder = settings.Binder;
+
+ // reader/writer specific
+ // unset values won't override reader/writer set values
+ if (settings._formatting != null)
+ serializer._formatting = settings._formatting;
+ if (settings._dateFormatHandling != null)
+ serializer._dateFormatHandling = settings._dateFormatHandling;
+ if (settings._dateTimeZoneHandling != null)
+ serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling;
+ if (settings._dateParseHandling != null)
+ serializer._dateParseHandling = settings._dateParseHandling;
+ if (settings._dateFormatStringSet)
+ {
+ serializer._dateFormatString = settings._dateFormatString;
+ serializer._dateFormatStringSet = settings._dateFormatStringSet;
+ }
+ if (settings._floatFormatHandling != null)
+ serializer._floatFormatHandling = settings._floatFormatHandling;
+ if (settings._floatParseHandling != null)
+ serializer._floatParseHandling = settings._floatParseHandling;
+ if (settings._stringEscapeHandling != null)
+ serializer._stringEscapeHandling = settings._stringEscapeHandling;
+ if (settings._culture != null)
+ serializer._culture = settings._culture;
+ if (settings._maxDepthSet)
+ {
+ serializer._maxDepth = settings._maxDepth;
+ serializer._maxDepthSet = settings._maxDepthSet;
+ }
+ }
+
+ ///
+ /// Populates the JSON values onto the target object.
+ ///
+ /// The that contains the JSON structure to reader values from.
+ /// The target object to populate values onto.
+ public void Populate(TextReader reader, object target)
+ {
+ Populate(new JsonTextReader(reader), target);
+ }
+
+ ///
+ /// Populates the JSON values onto the target object.
+ ///
+ /// The that contains the JSON structure to reader values from.
+ /// The target object to populate values onto.
+ public void Populate(JsonReader reader, object target)
+ {
+ PopulateInternal(reader, target);
+ }
+
+ internal virtual void PopulateInternal(JsonReader reader, object target)
+ {
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+ ValidationUtils.ArgumentNotNull(target, "target");
+
+ // set serialization options onto reader
+ CultureInfo previousCulture;
+ DateTimeZoneHandling? previousDateTimeZoneHandling;
+ DateParseHandling? previousDateParseHandling;
+ FloatParseHandling? previousFloatParseHandling;
+ int? previousMaxDepth;
+ string previousDateFormatString;
+ SetupReader(reader, out previousCulture, out previousDateTimeZoneHandling, out previousDateParseHandling, out previousFloatParseHandling, out previousMaxDepth, out previousDateFormatString);
+
+ TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+ ? new TraceJsonReader(reader)
+ : null;
+
+ JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
+ serializerReader.Populate(traceJsonReader ?? reader, target);
+
+ if (traceJsonReader != null)
+ TraceWriter.Trace(TraceLevel.Verbose, "Deserialized JSON: " + Environment.NewLine + traceJsonReader.GetJson(), null);
+
+ ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
+ }
+
+ ///
+ /// Deserializes the Json structure contained by the specified .
+ ///
+ /// The that contains the JSON structure to deserialize.
+ /// The being deserialized.
+ public object Deserialize(JsonReader reader)
+ {
+ return Deserialize(reader, null);
+ }
+
+ ///
+ /// Deserializes the Json structure contained by the specified
+ /// into an instance of the specified type.
+ ///
+ /// The containing the object.
+ /// The of object being deserialized.
+ /// The instance of being deserialized.
+ public object Deserialize(TextReader reader, Type objectType)
+ {
+ return Deserialize(new JsonTextReader(reader), objectType);
+ }
+
+ ///
+ /// Deserializes the Json structure contained by the specified
+ /// into an instance of the specified type.
+ ///
+ /// The containing the object.
+ /// The type of the object to deserialize.
+ /// The instance of being deserialized.
+ public T Deserialize(JsonReader reader)
+ {
+ return (T)Deserialize(reader, typeof(T));
+ }
+
+ ///
+ /// Deserializes the Json structure contained by the specified
+ /// into an instance of the specified type.
+ ///
+ /// The containing the object.
+ /// The of object being deserialized.
+ /// The instance of being deserialized.
+ public object Deserialize(JsonReader reader, Type objectType)
+ {
+ return DeserializeInternal(reader, objectType);
+ }
+
+ internal virtual object DeserializeInternal(JsonReader reader, Type objectType)
+ {
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+
+ // set serialization options onto reader
+ CultureInfo previousCulture;
+ DateTimeZoneHandling? previousDateTimeZoneHandling;
+ DateParseHandling? previousDateParseHandling;
+ FloatParseHandling? previousFloatParseHandling;
+ int? previousMaxDepth;
+ string previousDateFormatString;
+ SetupReader(reader, out previousCulture, out previousDateTimeZoneHandling, out previousDateParseHandling, out previousFloatParseHandling, out previousMaxDepth, out previousDateFormatString);
+
+ TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+ ? new TraceJsonReader(reader)
+ : null;
+
+ JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
+ object value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent);
+
+ if (traceJsonReader != null)
+ TraceWriter.Trace(TraceLevel.Verbose, "Deserialized JSON: " + Environment.NewLine + traceJsonReader.GetJson(), null);
+
+ ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
+
+ return value;
+ }
+
+ private void SetupReader(JsonReader reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString)
+ {
+ if (_culture != null && !_culture.Equals(reader.Culture))
+ {
+ previousCulture = reader.Culture;
+ reader.Culture = _culture;
+ }
+ else
+ {
+ previousCulture = null;
+ }
+
+ if (_dateTimeZoneHandling != null && reader.DateTimeZoneHandling != _dateTimeZoneHandling)
+ {
+ previousDateTimeZoneHandling = reader.DateTimeZoneHandling;
+ reader.DateTimeZoneHandling = _dateTimeZoneHandling.Value;
+ }
+ else
+ {
+ previousDateTimeZoneHandling = null;
+ }
+
+ if (_dateParseHandling != null && reader.DateParseHandling != _dateParseHandling)
+ {
+ previousDateParseHandling = reader.DateParseHandling;
+ reader.DateParseHandling = _dateParseHandling.Value;
+ }
+ else
+ {
+ previousDateParseHandling = null;
+ }
+
+ if (_floatParseHandling != null && reader.FloatParseHandling != _floatParseHandling)
+ {
+ previousFloatParseHandling = reader.FloatParseHandling;
+ reader.FloatParseHandling = _floatParseHandling.Value;
+ }
+ else
+ {
+ previousFloatParseHandling = null;
+ }
+
+ if (_maxDepthSet && reader.MaxDepth != _maxDepth)
+ {
+ previousMaxDepth = reader.MaxDepth;
+ reader.MaxDepth = _maxDepth;
+ }
+ else
+ {
+ previousMaxDepth = null;
+ }
+
+ if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString)
+ {
+ previousDateFormatString = reader.DateFormatString;
+ reader.DateFormatString = _dateFormatString;
+ }
+ else
+ {
+ previousDateFormatString = null;
+ }
+
+ JsonTextReader textReader = reader as JsonTextReader;
+ if (textReader != null)
+ {
+ DefaultContractResolver resolver = _contractResolver as DefaultContractResolver;
+ if (resolver != null)
+ textReader.NameTable = resolver.GetState().NameTable;
+ }
+ }
+
+ private void ResetReader(JsonReader reader, CultureInfo previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string previousDateFormatString)
+ {
+ // reset reader back to previous options
+ if (previousCulture != null)
+ reader.Culture = previousCulture;
+ if (previousDateTimeZoneHandling != null)
+ reader.DateTimeZoneHandling = previousDateTimeZoneHandling.Value;
+ if (previousDateParseHandling != null)
+ reader.DateParseHandling = previousDateParseHandling.Value;
+ if (previousFloatParseHandling != null)
+ reader.FloatParseHandling = previousFloatParseHandling.Value;
+ if (_maxDepthSet)
+ reader.MaxDepth = previousMaxDepth;
+ if (_dateFormatStringSet)
+ reader.DateFormatString = previousDateFormatString;
+
+ JsonTextReader textReader = reader as JsonTextReader;
+ if (textReader != null)
+ textReader.NameTable = null;
+ }
+
+ ///
+ /// Serializes the specified and writes the Json structure
+ /// to a Stream using the specified .
+ ///
+ /// The used to write the Json structure.
+ /// The to serialize.
+ public void Serialize(TextWriter textWriter, object value)
+ {
+ Serialize(new JsonTextWriter(textWriter), value);
+ }
+
+ ///
+ /// Serializes the specified and writes the Json structure
+ /// to a Stream using the specified .
+ ///
+ /// The used to write the Json structure.
+ /// The to serialize.
+ ///
+ /// The type of the value being serialized.
+ /// This parameter is used when is Auto to write out the type name if the type of the value does not match.
+ /// Specifing the type is optional.
+ ///
+ public void Serialize(JsonWriter jsonWriter, object value, Type objectType)
+ {
+ SerializeInternal(jsonWriter, value, objectType);
+ }
+
+ ///
+ /// Serializes the specified and writes the Json structure
+ /// to a Stream using the specified .
+ ///
+ /// The used to write the Json structure.
+ /// The to serialize.
+ ///
+ /// The type of the value being serialized.
+ /// This parameter is used when is Auto to write out the type name if the type of the value does not match.
+ /// Specifing the type is optional.
+ ///
+ public void Serialize(TextWriter textWriter, object value, Type objectType)
+ {
+ Serialize(new JsonTextWriter(textWriter), value, objectType);
+ }
+
+ ///
+ /// Serializes the specified and writes the Json structure
+ /// to a Stream using the specified .
+ ///
+ /// The used to write the Json structure.
+ /// The to serialize.
+ public void Serialize(JsonWriter jsonWriter, object value)
+ {
+ SerializeInternal(jsonWriter, value, null);
+ }
+
+ internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Type objectType)
+ {
+ ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter");
+
+ // set serialization options onto writer
+ Formatting? previousFormatting = null;
+ if (_formatting != null && jsonWriter.Formatting != _formatting)
+ {
+ previousFormatting = jsonWriter.Formatting;
+ jsonWriter.Formatting = _formatting.Value;
+ }
+
+ DateFormatHandling? previousDateFormatHandling = null;
+ if (_dateFormatHandling != null && jsonWriter.DateFormatHandling != _dateFormatHandling)
+ {
+ previousDateFormatHandling = jsonWriter.DateFormatHandling;
+ jsonWriter.DateFormatHandling = _dateFormatHandling.Value;
+ }
+
+ DateTimeZoneHandling? previousDateTimeZoneHandling = null;
+ if (_dateTimeZoneHandling != null && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling)
+ {
+ previousDateTimeZoneHandling = jsonWriter.DateTimeZoneHandling;
+ jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.Value;
+ }
+
+ FloatFormatHandling? previousFloatFormatHandling = null;
+ if (_floatFormatHandling != null && jsonWriter.FloatFormatHandling != _floatFormatHandling)
+ {
+ previousFloatFormatHandling = jsonWriter.FloatFormatHandling;
+ jsonWriter.FloatFormatHandling = _floatFormatHandling.Value;
+ }
+
+ StringEscapeHandling? previousStringEscapeHandling = null;
+ if (_stringEscapeHandling != null && jsonWriter.StringEscapeHandling != _stringEscapeHandling)
+ {
+ previousStringEscapeHandling = jsonWriter.StringEscapeHandling;
+ jsonWriter.StringEscapeHandling = _stringEscapeHandling.Value;
+ }
+
+ CultureInfo previousCulture = null;
+ if (_culture != null && !_culture.Equals(jsonWriter.Culture))
+ {
+ previousCulture = jsonWriter.Culture;
+ jsonWriter.Culture = _culture;
+ }
+
+ string previousDateFormatString = null;
+ if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString)
+ {
+ previousDateFormatString = jsonWriter.DateFormatString;
+ jsonWriter.DateFormatString = _dateFormatString;
+ }
+
+ TraceJsonWriter traceJsonWriter = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+ ? new TraceJsonWriter(jsonWriter)
+ : null;
+
+ JsonSerializerInternalWriter serializerWriter = new JsonSerializerInternalWriter(this);
+ serializerWriter.Serialize(traceJsonWriter ?? jsonWriter, value, objectType);
+
+ if (traceJsonWriter != null)
+ TraceWriter.Trace(TraceLevel.Verbose, "Serialized JSON: " + Environment.NewLine + traceJsonWriter.GetJson(), null);
+
+ // reset writer back to previous options
+ if (previousFormatting != null)
+ jsonWriter.Formatting = previousFormatting.Value;
+ if (previousDateFormatHandling != null)
+ jsonWriter.DateFormatHandling = previousDateFormatHandling.Value;
+ if (previousDateTimeZoneHandling != null)
+ jsonWriter.DateTimeZoneHandling = previousDateTimeZoneHandling.Value;
+ if (previousFloatFormatHandling != null)
+ jsonWriter.FloatFormatHandling = previousFloatFormatHandling.Value;
+ if (previousStringEscapeHandling != null)
+ jsonWriter.StringEscapeHandling = previousStringEscapeHandling.Value;
+ if (_dateFormatStringSet)
+ jsonWriter.DateFormatString = previousDateFormatString;
+ if (previousCulture != null)
+ jsonWriter.Culture = previousCulture;
+ }
+
+ internal IReferenceResolver GetReferenceResolver()
+ {
+ if (_referenceResolver == null)
+ _referenceResolver = new DefaultReferenceResolver();
+
+ return _referenceResolver;
+ }
+
+ internal JsonConverter GetMatchingConverter(Type type)
+ {
+ return GetMatchingConverter(_converters, type);
+ }
+
+ internal static JsonConverter GetMatchingConverter(IList converters, Type objectType)
+ {
+#if DEBUG
+ ValidationUtils.ArgumentNotNull(objectType, "objectType");
+#endif
+
+ if (converters != null)
+ {
+ for (int i = 0; i < converters.Count; i++)
+ {
+ JsonConverter converter = converters[i];
+
+ if (converter.CanConvert(objectType))
+ return converter;
+ }
+ }
+
+ return null;
+ }
+
+ internal void OnError(ErrorEventArgs e)
+ {
+ EventHandler error = Error;
+ if (error != null)
+ error(this, e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonSerializerSettings.cs b/Libs/JsonNet/JsonSerializerSettings.cs
new file mode 100644
index 0000000..96949e6
--- /dev/null
+++ b/Libs/JsonNet/JsonSerializerSettings.cs
@@ -0,0 +1,365 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.Serialization.Formatters;
+using Newtonsoft.Json.Serialization;
+using System.Runtime.Serialization;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies the settings on a object.
+ ///
+ public class JsonSerializerSettings
+ {
+ internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error;
+ internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore;
+ internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include;
+ internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include;
+ internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto;
+ internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None;
+ internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default;
+ internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None;
+ internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default;
+ internal const FormatterAssemblyStyle DefaultTypeNameAssemblyFormat = FormatterAssemblyStyle.Simple;
+ internal static readonly StreamingContext DefaultContext;
+
+ internal const Formatting DefaultFormatting = Formatting.None;
+ internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat;
+ internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
+ internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime;
+ internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double;
+ internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String;
+ internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default;
+ internal const FormatterAssemblyStyle DefaultFormatterAssemblyStyle = FormatterAssemblyStyle.Simple;
+ internal static readonly CultureInfo DefaultCulture;
+ internal const bool DefaultCheckAdditionalContent = false;
+ internal const string DefaultDateFormatString = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
+
+ internal Formatting? _formatting;
+ internal DateFormatHandling? _dateFormatHandling;
+ internal DateTimeZoneHandling? _dateTimeZoneHandling;
+ internal DateParseHandling? _dateParseHandling;
+ internal FloatFormatHandling? _floatFormatHandling;
+ internal FloatParseHandling? _floatParseHandling;
+ internal StringEscapeHandling? _stringEscapeHandling;
+ internal CultureInfo _culture;
+ internal bool? _checkAdditionalContent;
+ internal int? _maxDepth;
+ internal bool _maxDepthSet;
+ internal string _dateFormatString;
+ internal bool _dateFormatStringSet;
+ internal FormatterAssemblyStyle? _typeNameAssemblyFormat;
+ internal DefaultValueHandling? _defaultValueHandling;
+ internal PreserveReferencesHandling? _preserveReferencesHandling;
+ internal NullValueHandling? _nullValueHandling;
+ internal ObjectCreationHandling? _objectCreationHandling;
+ internal MissingMemberHandling? _missingMemberHandling;
+ internal ReferenceLoopHandling? _referenceLoopHandling;
+ internal StreamingContext? _context;
+ internal ConstructorHandling? _constructorHandling;
+ internal TypeNameHandling? _typeNameHandling;
+ internal MetadataPropertyHandling? _metadataPropertyHandling;
+
+ ///
+ /// Gets or sets how reference loops (e.g. a class referencing itself) is handled.
+ ///
+ /// Reference loop handling.
+ public ReferenceLoopHandling ReferenceLoopHandling
+ {
+ get { return _referenceLoopHandling ?? DefaultReferenceLoopHandling; }
+ set { _referenceLoopHandling = value; }
+ }
+
+ ///
+ /// Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
+ ///
+ /// Missing member handling.
+ public MissingMemberHandling MissingMemberHandling
+ {
+ get { return _missingMemberHandling ?? DefaultMissingMemberHandling; }
+ set { _missingMemberHandling = value; }
+ }
+
+ ///
+ /// Gets or sets how objects are created during deserialization.
+ ///
+ /// The object creation handling.
+ public ObjectCreationHandling ObjectCreationHandling
+ {
+ get { return _objectCreationHandling ?? DefaultObjectCreationHandling; }
+ set { _objectCreationHandling = value; }
+ }
+
+ ///
+ /// Gets or sets how null values are handled during serialization and deserialization.
+ ///
+ /// Null value handling.
+ public NullValueHandling NullValueHandling
+ {
+ get { return _nullValueHandling ?? DefaultNullValueHandling; }
+ set { _nullValueHandling = value; }
+ }
+
+ ///
+ /// Gets or sets how null default are handled during serialization and deserialization.
+ ///
+ /// The default value handling.
+ public DefaultValueHandling DefaultValueHandling
+ {
+ get { return _defaultValueHandling ?? DefaultDefaultValueHandling; }
+ set { _defaultValueHandling = value; }
+ }
+
+ ///
+ /// Gets or sets a collection that will be used during serialization.
+ ///
+ /// The converters.
+ public IList Converters { get; set; }
+
+ ///
+ /// Gets or sets how object references are preserved by the serializer.
+ ///
+ /// The preserve references handling.
+ public PreserveReferencesHandling PreserveReferencesHandling
+ {
+ get { return _preserveReferencesHandling ?? DefaultPreserveReferencesHandling; }
+ set { _preserveReferencesHandling = value; }
+ }
+
+ ///
+ /// Gets or sets how type name writing and reading is handled by the serializer.
+ ///
+ /// The type name handling.
+ public TypeNameHandling TypeNameHandling
+ {
+ get { return _typeNameHandling ?? DefaultTypeNameHandling; }
+ set { _typeNameHandling = value; }
+ }
+
+ ///
+ /// Gets or sets how metadata properties are used during deserialization.
+ ///
+ /// The metadata properties handling.
+ public MetadataPropertyHandling MetadataPropertyHandling
+ {
+ get { return _metadataPropertyHandling ?? DefaultMetadataPropertyHandling; }
+ set { _metadataPropertyHandling = value; }
+ }
+
+ ///
+ /// Gets or sets how a type name assembly is written and resolved by the serializer.
+ ///
+ /// The type name assembly format.
+ public FormatterAssemblyStyle TypeNameAssemblyFormat
+ {
+ get { return _typeNameAssemblyFormat ?? DefaultFormatterAssemblyStyle; }
+ set { _typeNameAssemblyFormat = value; }
+ }
+
+ ///
+ /// Gets or sets how constructors are used during deserialization.
+ ///
+ /// The constructor handling.
+ public ConstructorHandling ConstructorHandling
+ {
+ get { return _constructorHandling ?? DefaultConstructorHandling; }
+ set { _constructorHandling = value; }
+ }
+
+ ///
+ /// Gets or sets the contract resolver used by the serializer when
+ /// serializing .NET objects to JSON and vice versa.
+ ///
+ /// The contract resolver.
+ public IContractResolver ContractResolver { get; set; }
+
+ ///
+ /// Gets or sets the used by the serializer when resolving references.
+ ///
+ /// The reference resolver.
+ public IReferenceResolver ReferenceResolver { get; set; }
+
+ ///
+ /// Gets or sets the used by the serializer when writing trace messages.
+ ///
+ /// The trace writer.
+ public ITraceWriter TraceWriter { get; set; }
+
+ ///
+ /// Gets or sets the used by the serializer when resolving type names.
+ ///
+ /// The binder.
+ public SerializationBinder Binder { get; set; }
+
+ ///
+ /// Gets or sets the error handler called during serialization and deserialization.
+ ///
+ /// The error handler called during serialization and deserialization.
+ public EventHandler Error { get; set; }
+
+ ///
+ /// Gets or sets the used by the serializer when invoking serialization callback methods.
+ ///
+ /// The context.
+ public StreamingContext Context
+ {
+ get { return _context ?? DefaultContext; }
+ set { _context = value; }
+ }
+
+ ///
+ /// Get or set how and values are formatting when writing JSON text.
+ ///
+ public string DateFormatString
+ {
+ get { return _dateFormatString ?? DefaultDateFormatString; }
+ set
+ {
+ _dateFormatString = value;
+ _dateFormatStringSet = true;
+ }
+ }
+
+ ///
+ /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
+ ///
+ public int? MaxDepth
+ {
+ get { return _maxDepth; }
+ set
+ {
+ if (value <= 0)
+ throw new ArgumentException("Value must be positive.", "value");
+
+ _maxDepth = value;
+ _maxDepthSet = true;
+ }
+ }
+
+ ///
+ /// Indicates how JSON text output is formatted.
+ ///
+ public Formatting Formatting
+ {
+ get { return _formatting ?? DefaultFormatting; }
+ set { _formatting = value; }
+ }
+
+ ///
+ /// Get or set how dates are written to JSON text.
+ ///
+ public DateFormatHandling DateFormatHandling
+ {
+ get { return _dateFormatHandling ?? DefaultDateFormatHandling; }
+ set { _dateFormatHandling = value; }
+ }
+
+ ///
+ /// Get or set how time zones are handling during serialization and deserialization.
+ ///
+ public DateTimeZoneHandling DateTimeZoneHandling
+ {
+ get { return _dateTimeZoneHandling ?? DefaultDateTimeZoneHandling; }
+ set { _dateTimeZoneHandling = value; }
+ }
+
+ ///
+ /// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
+ ///
+ public DateParseHandling DateParseHandling
+ {
+ get { return _dateParseHandling ?? DefaultDateParseHandling; }
+ set { _dateParseHandling = value; }
+ }
+
+ ///
+ /// Get or set how special floating point numbers, e.g. ,
+ /// and ,
+ /// are written as JSON.
+ ///
+ public FloatFormatHandling FloatFormatHandling
+ {
+ get { return _floatFormatHandling ?? DefaultFloatFormatHandling; }
+ set { _floatFormatHandling = value; }
+ }
+
+ ///
+ /// Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
+ ///
+ public FloatParseHandling FloatParseHandling
+ {
+ get { return _floatParseHandling ?? DefaultFloatParseHandling; }
+ set { _floatParseHandling = value; }
+ }
+
+ ///
+ /// Get or set how strings are escaped when writing JSON text.
+ ///
+ public StringEscapeHandling StringEscapeHandling
+ {
+ get { return _stringEscapeHandling ?? DefaultStringEscapeHandling; }
+ set { _stringEscapeHandling = value; }
+ }
+
+ ///
+ /// Gets or sets the culture used when reading JSON. Defaults to .
+ ///
+ public CultureInfo Culture
+ {
+ get { return _culture ?? DefaultCulture; }
+ set { _culture = value; }
+ }
+
+ ///
+ /// Gets a value indicating whether there will be a check for additional content after deserializing an object.
+ ///
+ ///
+ /// true if there will be a check for additional content after deserializing an object; otherwise, false .
+ ///
+ public bool CheckAdditionalContent
+ {
+ get { return _checkAdditionalContent ?? DefaultCheckAdditionalContent; }
+ set { _checkAdditionalContent = value; }
+ }
+
+ static JsonSerializerSettings()
+ {
+ DefaultContext = new StreamingContext();
+ DefaultCulture = CultureInfo.InvariantCulture;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonSerializerSettings()
+ {
+ Converters = new List();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonTextReader.cs b/Libs/JsonNet/JsonTextReader.cs
new file mode 100644
index 0000000..18e9d57
--- /dev/null
+++ b/Libs/JsonNet/JsonTextReader.cs
@@ -0,0 +1,1671 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.IO;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+ internal enum ReadType
+ {
+ Read,
+ ReadAsInt32,
+ ReadAsBytes,
+ ReadAsString,
+ ReadAsDecimal,
+ ReadAsDateTime,
+#if !NET20
+ ReadAsDateTimeOffset
+#endif
+ }
+
+ ///
+ /// Represents a reader that provides fast, non-cached, forward-only access to JSON text data.
+ ///
+ public class JsonTextReader : JsonReader, IJsonLineInfo
+ {
+ private const char UnicodeReplacementChar = '\uFFFD';
+ private const int MaximumJavascriptIntegerCharacterLength = 380;
+
+ private readonly TextReader _reader;
+ private char[] _chars;
+ private int _charsUsed;
+ private int _charPos;
+ private int _lineStartPos;
+ private int _lineNumber;
+ private bool _isEndOfFile;
+ private StringBuffer _buffer;
+ private StringReference _stringReference;
+ internal PropertyNameTable NameTable;
+
+ ///
+ /// Initializes a new instance of the class with the specified .
+ ///
+ /// The TextReader containing the XML data to read.
+ public JsonTextReader(TextReader reader)
+ {
+ if (reader == null)
+ throw new ArgumentNullException("reader");
+
+ _reader = reader;
+ _lineNumber = 1;
+ _chars = new char[1025];
+ }
+
+#if DEBUG
+ internal void SetCharBuffer(char[] chars)
+ {
+ _chars = chars;
+ }
+#endif
+
+ private StringBuffer GetBuffer()
+ {
+ if (_buffer == null)
+ {
+ _buffer = new StringBuffer(1025);
+ }
+ else
+ {
+ _buffer.Position = 0;
+ }
+
+ return _buffer;
+ }
+
+ private void OnNewLine(int pos)
+ {
+ _lineNumber++;
+ _lineStartPos = pos - 1;
+ }
+
+ private void ParseString(char quote)
+ {
+ _charPos++;
+
+ ShiftBufferIfNeeded();
+ ReadStringIntoBuffer(quote);
+ SetPostValueState(true);
+
+ if (_readType == ReadType.ReadAsBytes)
+ {
+ byte[] data;
+ if (_stringReference.Length == 0)
+ {
+ data = new byte[0];
+ }
+ else
+ {
+ data = Convert.FromBase64CharArray(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length);
+ }
+
+ SetToken(JsonToken.Bytes, data, false);
+ }
+ else if (_readType == ReadType.ReadAsString)
+ {
+ string text = _stringReference.ToString();
+
+ SetToken(JsonToken.String, text, false);
+ _quoteChar = quote;
+ }
+ else
+ {
+ string text = _stringReference.ToString();
+
+ if (_dateParseHandling != DateParseHandling.None)
+ {
+ DateParseHandling dateParseHandling;
+ if (_readType == ReadType.ReadAsDateTime)
+ dateParseHandling = DateParseHandling.DateTime;
+#if !NET20
+ else if (_readType == ReadType.ReadAsDateTimeOffset)
+ dateParseHandling = DateParseHandling.DateTimeOffset;
+#endif
+ else
+ dateParseHandling = _dateParseHandling;
+
+ object dt;
+ if (DateTimeUtils.TryParseDateTime(text, dateParseHandling, DateTimeZoneHandling, DateFormatString, Culture, out dt))
+ {
+ SetToken(JsonToken.Date, dt, false);
+ return;
+ }
+ }
+
+ SetToken(JsonToken.String, text, false);
+ _quoteChar = quote;
+ }
+ }
+
+ private static void BlockCopyChars(char[] src, int srcOffset, char[] dst, int dstOffset, int count)
+ {
+ const int charByteCount = 2;
+
+ Buffer.BlockCopy(src, srcOffset * charByteCount, dst, dstOffset * charByteCount, count * charByteCount);
+ }
+
+ private void ShiftBufferIfNeeded()
+ {
+ // once in the last 10% of the buffer shift the remaining content to the start to avoid
+ // unnessesarly increasing the buffer size when reading numbers/strings
+ int length = _chars.Length;
+ if (length - _charPos <= length * 0.1)
+ {
+ int count = _charsUsed - _charPos;
+ if (count > 0)
+ BlockCopyChars(_chars, _charPos, _chars, 0, count);
+
+ _lineStartPos -= _charPos;
+ _charPos = 0;
+ _charsUsed = count;
+ _chars[_charsUsed] = '\0';
+ }
+ }
+
+ private int ReadData(bool append)
+ {
+ return ReadData(append, 0);
+ }
+
+ private int ReadData(bool append, int charsRequired)
+ {
+ if (_isEndOfFile)
+ return 0;
+
+ // char buffer is full
+ if (_charsUsed + charsRequired >= _chars.Length - 1)
+ {
+ if (append)
+ {
+ // copy to new array either double the size of the current or big enough to fit required content
+ int newArrayLength = Math.Max(_chars.Length * 2, _charsUsed + charsRequired + 1);
+
+ // increase the size of the buffer
+ char[] dst = new char[newArrayLength];
+
+ BlockCopyChars(_chars, 0, dst, 0, _chars.Length);
+
+ _chars = dst;
+ }
+ else
+ {
+ int remainingCharCount = _charsUsed - _charPos;
+
+ if (remainingCharCount + charsRequired + 1 >= _chars.Length)
+ {
+ // the remaining count plus the required is bigger than the current buffer size
+ char[] dst = new char[remainingCharCount + charsRequired + 1];
+
+ if (remainingCharCount > 0)
+ BlockCopyChars(_chars, _charPos, dst, 0, remainingCharCount);
+
+ _chars = dst;
+ }
+ else
+ {
+ // copy any remaining data to the beginning of the buffer if needed and reset positions
+ if (remainingCharCount > 0)
+ BlockCopyChars(_chars, _charPos, _chars, 0, remainingCharCount);
+ }
+
+ _lineStartPos -= _charPos;
+ _charPos = 0;
+ _charsUsed = remainingCharCount;
+ }
+ }
+
+ int attemptCharReadCount = _chars.Length - _charsUsed - 1;
+
+ int charsRead = _reader.Read(_chars, _charsUsed, attemptCharReadCount);
+
+ _charsUsed += charsRead;
+
+ if (charsRead == 0)
+ _isEndOfFile = true;
+
+ _chars[_charsUsed] = '\0';
+ return charsRead;
+ }
+
+ private bool EnsureChars(int relativePosition, bool append)
+ {
+ if (_charPos + relativePosition >= _charsUsed)
+ return ReadChars(relativePosition, append);
+
+ return true;
+ }
+
+ private bool ReadChars(int relativePosition, bool append)
+ {
+ if (_isEndOfFile)
+ return false;
+
+ int charsRequired = _charPos + relativePosition - _charsUsed + 1;
+
+ int totalCharsRead = 0;
+
+ // it is possible that the TextReader doesn't return all data at once
+ // repeat read until the required text is returned or the reader is out of content
+ do
+ {
+ int charsRead = ReadData(append, charsRequired - totalCharsRead);
+
+ // no more content
+ if (charsRead == 0)
+ break;
+
+ totalCharsRead += charsRead;
+ } while (totalCharsRead < charsRequired);
+
+ if (totalCharsRead < charsRequired)
+ return false;
+ return true;
+ }
+
+ ///
+ /// Reads the next JSON token from the stream.
+ ///
+ ///
+ /// true if the next token was read successfully; false if there are no more tokens to read.
+ ///
+ [DebuggerStepThrough]
+ public override bool Read()
+ {
+ _readType = ReadType.Read;
+ if (!ReadInternal())
+ {
+ SetToken(JsonToken.None);
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a [].
+ ///
+ ///
+ /// A [] or a null reference if the next JSON token is null. This method will return null at the end of an array.
+ ///
+ public override byte[] ReadAsBytes()
+ {
+ return ReadAsBytesInternal();
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override decimal? ReadAsDecimal()
+ {
+ return ReadAsDecimalInternal();
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override int? ReadAsInt32()
+ {
+ return ReadAsInt32Internal();
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override string ReadAsString()
+ {
+ return ReadAsStringInternal();
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override DateTime? ReadAsDateTime()
+ {
+ return ReadAsDateTimeInternal();
+ }
+
+#if !NET20
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override DateTimeOffset? ReadAsDateTimeOffset()
+ {
+ return ReadAsDateTimeOffsetInternal();
+ }
+#endif
+
+ internal override bool ReadInternal()
+ {
+ while (true)
+ {
+ switch (_currentState)
+ {
+ case State.Start:
+ case State.Property:
+ case State.Array:
+ case State.ArrayStart:
+ case State.Constructor:
+ case State.ConstructorStart:
+ return ParseValue();
+ case State.Object:
+ case State.ObjectStart:
+ return ParseObject();
+ case State.PostValue:
+ // returns true if it hits
+ // end of object or array
+ if (ParsePostValue())
+ return true;
+ break;
+ case State.Finished:
+ if (EnsureChars(0, false))
+ {
+ EatWhitespace(false);
+ if (_isEndOfFile)
+ {
+ return false;
+ }
+ if (_chars[_charPos] == '/')
+ {
+ ParseComment();
+ return true;
+ }
+
+ throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+ }
+ return false;
+ default:
+ throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState));
+ }
+ }
+ }
+
+ private void ReadStringIntoBuffer(char quote)
+ {
+ int charPos = _charPos;
+ int initialPosition = _charPos;
+ int lastWritePosition = _charPos;
+ StringBuffer buffer = null;
+
+ while (true)
+ {
+ switch (_chars[charPos++])
+ {
+ case '\0':
+ if (_charsUsed == charPos - 1)
+ {
+ charPos--;
+
+ if (ReadData(true) == 0)
+ {
+ _charPos = charPos;
+ throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote));
+ }
+ }
+ break;
+ case '\\':
+ _charPos = charPos;
+ if (!EnsureChars(0, true))
+ {
+ _charPos = charPos;
+ throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote));
+ }
+
+ // start of escape sequence
+ int escapeStartPos = charPos - 1;
+
+ char currentChar = _chars[charPos];
+
+ char writeChar;
+
+ switch (currentChar)
+ {
+ case 'b':
+ charPos++;
+ writeChar = '\b';
+ break;
+ case 't':
+ charPos++;
+ writeChar = '\t';
+ break;
+ case 'n':
+ charPos++;
+ writeChar = '\n';
+ break;
+ case 'f':
+ charPos++;
+ writeChar = '\f';
+ break;
+ case 'r':
+ charPos++;
+ writeChar = '\r';
+ break;
+ case '\\':
+ charPos++;
+ writeChar = '\\';
+ break;
+ case '"':
+ case '\'':
+ case '/':
+ writeChar = currentChar;
+ charPos++;
+ break;
+ case 'u':
+ charPos++;
+ _charPos = charPos;
+ writeChar = ParseUnicode();
+
+ if (StringUtils.IsLowSurrogate(writeChar))
+ {
+ // low surrogate with no preceding high surrogate; this char is replaced
+ writeChar = UnicodeReplacementChar;
+ }
+ else if (StringUtils.IsHighSurrogate(writeChar))
+ {
+ bool anotherHighSurrogate;
+
+ // loop for handling situations where there are multiple consecutive high surrogates
+ do
+ {
+ anotherHighSurrogate = false;
+
+ // potential start of a surrogate pair
+ if (EnsureChars(2, true) && _chars[_charPos] == '\\' && _chars[_charPos + 1] == 'u')
+ {
+ char highSurrogate = writeChar;
+
+ _charPos += 2;
+ writeChar = ParseUnicode();
+
+ if (StringUtils.IsLowSurrogate(writeChar))
+ {
+ // a valid surrogate pair!
+ }
+ else if (StringUtils.IsHighSurrogate(writeChar))
+ {
+ // another high surrogate; replace current and start check over
+ highSurrogate = UnicodeReplacementChar;
+ anotherHighSurrogate = true;
+ }
+ else
+ {
+ // high surrogate not followed by low surrogate; original char is replaced
+ highSurrogate = UnicodeReplacementChar;
+ }
+
+ if (buffer == null)
+ buffer = GetBuffer();
+
+ WriteCharToBuffer(buffer, highSurrogate, lastWritePosition, escapeStartPos);
+ lastWritePosition = _charPos;
+ }
+ else
+ {
+ // there are not enough remaining chars for the low surrogate or is not follow by unicode sequence
+ // replace high surrogate and continue on as usual
+ writeChar = UnicodeReplacementChar;
+ }
+ } while (anotherHighSurrogate);
+ }
+
+ charPos = _charPos;
+ break;
+ default:
+ charPos++;
+ _charPos = charPos;
+ throw JsonReaderException.Create(this, "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, @"\" + currentChar));
+ }
+
+ if (buffer == null)
+ buffer = GetBuffer();
+
+ WriteCharToBuffer(buffer, writeChar, lastWritePosition, escapeStartPos);
+
+ lastWritePosition = charPos;
+ break;
+ case StringUtils.CarriageReturn:
+ _charPos = charPos - 1;
+ ProcessCarriageReturn(true);
+ charPos = _charPos;
+ break;
+ case StringUtils.LineFeed:
+ _charPos = charPos - 1;
+ ProcessLineFeed();
+ charPos = _charPos;
+ break;
+ case '"':
+ case '\'':
+ if (_chars[charPos - 1] == quote)
+ {
+ charPos--;
+
+ if (initialPosition == lastWritePosition)
+ {
+ _stringReference = new StringReference(_chars, initialPosition, charPos - initialPosition);
+ }
+ else
+ {
+ if (buffer == null)
+ buffer = GetBuffer();
+
+ if (charPos > lastWritePosition)
+ buffer.Append(_chars, lastWritePosition, charPos - lastWritePosition);
+
+ _stringReference = new StringReference(buffer.GetInternalBuffer(), 0, buffer.Position);
+ }
+
+ charPos++;
+ _charPos = charPos;
+ return;
+ }
+ break;
+ }
+ }
+ }
+
+ private void WriteCharToBuffer(StringBuffer buffer, char writeChar, int lastWritePosition, int writeToPosition)
+ {
+ if (writeToPosition > lastWritePosition)
+ {
+ buffer.Append(_chars, lastWritePosition, writeToPosition - lastWritePosition);
+ }
+
+ buffer.Append(writeChar);
+ }
+
+ private char ParseUnicode()
+ {
+ char writeChar;
+ if (EnsureChars(4, true))
+ {
+ string hexValues = new string(_chars, _charPos, 4);
+ char hexChar = Convert.ToChar(int.Parse(hexValues, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo));
+ writeChar = hexChar;
+
+ _charPos += 4;
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Unexpected end while parsing unicode character.");
+ }
+ return writeChar;
+ }
+
+ private void ReadNumberIntoBuffer()
+ {
+ int charPos = _charPos;
+
+ while (true)
+ {
+ switch (_chars[charPos])
+ {
+ case '\0':
+ _charPos = charPos;
+
+ if (_charsUsed == charPos)
+ {
+ if (ReadData(true) == 0)
+ return;
+ }
+ else
+ {
+ return;
+ }
+ break;
+ case '-':
+ case '+':
+ case 'a':
+ case 'A':
+ case 'b':
+ case 'B':
+ case 'c':
+ case 'C':
+ case 'd':
+ case 'D':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'x':
+ case 'X':
+ case '.':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ charPos++;
+ break;
+ default:
+ _charPos = charPos;
+
+ char currentChar = _chars[_charPos];
+ if (char.IsWhiteSpace(currentChar)
+ || currentChar == ','
+ || currentChar == '}'
+ || currentChar == ']'
+ || currentChar == ')'
+ || currentChar == '/')
+ {
+ return;
+ }
+
+ throw JsonReaderException.Create(this, "Unexpected character encountered while parsing number: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+ }
+ }
+ }
+
+ private void ClearRecentString()
+ {
+ if (_buffer != null)
+ _buffer.Position = 0;
+
+ _stringReference = new StringReference();
+ }
+
+ private bool ParsePostValue()
+ {
+ while (true)
+ {
+ char currentChar = _chars[_charPos];
+
+ switch (currentChar)
+ {
+ case '\0':
+ if (_charsUsed == _charPos)
+ {
+ if (ReadData(false) == 0)
+ {
+ _currentState = State.Finished;
+ return false;
+ }
+ }
+ else
+ {
+ _charPos++;
+ }
+ break;
+ case '}':
+ _charPos++;
+ SetToken(JsonToken.EndObject);
+ return true;
+ case ']':
+ _charPos++;
+ SetToken(JsonToken.EndArray);
+ return true;
+ case ')':
+ _charPos++;
+ SetToken(JsonToken.EndConstructor);
+ return true;
+ case '/':
+ ParseComment();
+ return true;
+ case ',':
+ _charPos++;
+
+ // finished parsing
+ SetStateBasedOnCurrent();
+ return false;
+ case ' ':
+ case StringUtils.Tab:
+ // eat
+ _charPos++;
+ break;
+ case StringUtils.CarriageReturn:
+ ProcessCarriageReturn(false);
+ break;
+ case StringUtils.LineFeed:
+ ProcessLineFeed();
+ break;
+ default:
+ if (char.IsWhiteSpace(currentChar))
+ {
+ // eat
+ _charPos++;
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "After parsing a value an unexpected character was encountered: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+ }
+ break;
+ }
+ }
+ }
+
+ private bool ParseObject()
+ {
+ while (true)
+ {
+ char currentChar = _chars[_charPos];
+
+ switch (currentChar)
+ {
+ case '\0':
+ if (_charsUsed == _charPos)
+ {
+ if (ReadData(false) == 0)
+ return false;
+ }
+ else
+ {
+ _charPos++;
+ }
+ break;
+ case '}':
+ SetToken(JsonToken.EndObject);
+ _charPos++;
+ return true;
+ case '/':
+ ParseComment();
+ return true;
+ case StringUtils.CarriageReturn:
+ ProcessCarriageReturn(false);
+ break;
+ case StringUtils.LineFeed:
+ ProcessLineFeed();
+ break;
+ case ' ':
+ case StringUtils.Tab:
+ // eat
+ _charPos++;
+ break;
+ default:
+ if (char.IsWhiteSpace(currentChar))
+ {
+ // eat
+ _charPos++;
+ }
+ else
+ {
+ return ParseProperty();
+ }
+ break;
+ }
+ }
+ }
+
+ private bool ParseProperty()
+ {
+ char firstChar = _chars[_charPos];
+ char quoteChar;
+
+ if (firstChar == '"' || firstChar == '\'')
+ {
+ _charPos++;
+ quoteChar = firstChar;
+ ShiftBufferIfNeeded();
+ ReadStringIntoBuffer(quoteChar);
+ }
+ else if (ValidIdentifierChar(firstChar))
+ {
+ quoteChar = '\0';
+ ShiftBufferIfNeeded();
+ ParseUnquotedProperty();
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+ }
+
+ string propertyName;
+
+ if (NameTable != null)
+ {
+ propertyName = NameTable.Get(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length);
+
+ // no match in name table
+ if (propertyName == null)
+ propertyName = _stringReference.ToString();
+ }
+ else
+ {
+ propertyName = _stringReference.ToString();
+ }
+
+ EatWhitespace(false);
+
+ if (_chars[_charPos] != ':')
+ throw JsonReaderException.Create(this, "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+
+ _charPos++;
+
+ SetToken(JsonToken.PropertyName, propertyName);
+ _quoteChar = quoteChar;
+ ClearRecentString();
+
+ return true;
+ }
+
+ private bool ValidIdentifierChar(char value)
+ {
+ return (char.IsLetterOrDigit(value) || value == '_' || value == '$');
+ }
+
+ private void ParseUnquotedProperty()
+ {
+ int initialPosition = _charPos;
+
+ // parse unquoted property name until whitespace or colon
+ while (true)
+ {
+ switch (_chars[_charPos])
+ {
+ case '\0':
+ if (_charsUsed == _charPos)
+ {
+ if (ReadData(true) == 0)
+ throw JsonReaderException.Create(this, "Unexpected end while parsing unquoted property name.");
+
+ break;
+ }
+
+ _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+ return;
+ default:
+ char currentChar = _chars[_charPos];
+
+ if (ValidIdentifierChar(currentChar))
+ {
+ _charPos++;
+ break;
+ }
+ else if (char.IsWhiteSpace(currentChar) || currentChar == ':')
+ {
+ _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+ return;
+ }
+
+ throw JsonReaderException.Create(this, "Invalid JavaScript property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+ }
+ }
+ }
+
+ private bool ParseValue()
+ {
+ while (true)
+ {
+ char currentChar = _chars[_charPos];
+
+ switch (currentChar)
+ {
+ case '\0':
+ if (_charsUsed == _charPos)
+ {
+ if (ReadData(false) == 0)
+ return false;
+ }
+ else
+ {
+ _charPos++;
+ }
+ break;
+ case '"':
+ case '\'':
+ ParseString(currentChar);
+ return true;
+ case 't':
+ ParseTrue();
+ return true;
+ case 'f':
+ ParseFalse();
+ return true;
+ case 'n':
+ if (EnsureChars(1, true))
+ {
+ char next = _chars[_charPos + 1];
+
+ if (next == 'u')
+ ParseNull();
+ else if (next == 'e')
+ ParseConstructor();
+ else
+ throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Unexpected end.");
+ }
+ return true;
+ case 'N':
+ ParseNumberNaN();
+ return true;
+ case 'I':
+ ParseNumberPositiveInfinity();
+ return true;
+ case '-':
+ if (EnsureChars(1, true) && _chars[_charPos + 1] == 'I')
+ ParseNumberNegativeInfinity();
+ else
+ ParseNumber();
+ return true;
+ case '/':
+ ParseComment();
+ return true;
+ case 'u':
+ ParseUndefined();
+ return true;
+ case '{':
+ _charPos++;
+ SetToken(JsonToken.StartObject);
+ return true;
+ case '[':
+ _charPos++;
+ SetToken(JsonToken.StartArray);
+ return true;
+ case ']':
+ _charPos++;
+ SetToken(JsonToken.EndArray);
+ return true;
+ case ',':
+ // don't increment position, the next call to read will handle comma
+ // this is done to handle multiple empty comma values
+ SetToken(JsonToken.Undefined);
+ return true;
+ case ')':
+ _charPos++;
+ SetToken(JsonToken.EndConstructor);
+ return true;
+ case StringUtils.CarriageReturn:
+ ProcessCarriageReturn(false);
+ break;
+ case StringUtils.LineFeed:
+ ProcessLineFeed();
+ break;
+ case ' ':
+ case StringUtils.Tab:
+ // eat
+ _charPos++;
+ break;
+ default:
+ if (char.IsWhiteSpace(currentChar))
+ {
+ // eat
+ _charPos++;
+ break;
+ }
+ if (char.IsNumber(currentChar) || currentChar == '-' || currentChar == '.')
+ {
+ ParseNumber();
+ return true;
+ }
+
+ throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+ }
+ }
+ }
+
+ private void ProcessLineFeed()
+ {
+ _charPos++;
+ OnNewLine(_charPos);
+ }
+
+ private void ProcessCarriageReturn(bool append)
+ {
+ _charPos++;
+
+ if (EnsureChars(1, append) && _chars[_charPos] == StringUtils.LineFeed)
+ _charPos++;
+
+ OnNewLine(_charPos);
+ }
+
+ private bool EatWhitespace(bool oneOrMore)
+ {
+ bool finished = false;
+ bool ateWhitespace = false;
+ while (!finished)
+ {
+ char currentChar = _chars[_charPos];
+
+ switch (currentChar)
+ {
+ case '\0':
+ if (_charsUsed == _charPos)
+ {
+ if (ReadData(false) == 0)
+ finished = true;
+ }
+ else
+ {
+ _charPos++;
+ }
+ break;
+ case StringUtils.CarriageReturn:
+ ProcessCarriageReturn(false);
+ break;
+ case StringUtils.LineFeed:
+ ProcessLineFeed();
+ break;
+ default:
+ if (currentChar == ' ' || char.IsWhiteSpace(currentChar))
+ {
+ ateWhitespace = true;
+ _charPos++;
+ }
+ else
+ {
+ finished = true;
+ }
+ break;
+ }
+ }
+
+ return (!oneOrMore || ateWhitespace);
+ }
+
+ private void ParseConstructor()
+ {
+ if (MatchValueWithTrailingSeparator("new"))
+ {
+ EatWhitespace(false);
+
+ int initialPosition = _charPos;
+ int endPosition;
+
+ while (true)
+ {
+ char currentChar = _chars[_charPos];
+ if (currentChar == '\0')
+ {
+ if (_charsUsed == _charPos)
+ {
+ if (ReadData(true) == 0)
+ throw JsonReaderException.Create(this, "Unexpected end while parsing constructor.");
+ }
+ else
+ {
+ endPosition = _charPos;
+ _charPos++;
+ break;
+ }
+ }
+ else if (char.IsLetterOrDigit(currentChar))
+ {
+ _charPos++;
+ }
+ else if (currentChar == StringUtils.CarriageReturn)
+ {
+ endPosition = _charPos;
+ ProcessCarriageReturn(true);
+ break;
+ }
+ else if (currentChar == StringUtils.LineFeed)
+ {
+ endPosition = _charPos;
+ ProcessLineFeed();
+ break;
+ }
+ else if (char.IsWhiteSpace(currentChar))
+ {
+ endPosition = _charPos;
+ _charPos++;
+ break;
+ }
+ else if (currentChar == '(')
+ {
+ endPosition = _charPos;
+ break;
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+ }
+ }
+
+ _stringReference = new StringReference(_chars, initialPosition, endPosition - initialPosition);
+ string constructorName = _stringReference.ToString();
+
+ EatWhitespace(false);
+
+ if (_chars[_charPos] != '(')
+ throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+
+ _charPos++;
+
+ ClearRecentString();
+
+ SetToken(JsonToken.StartConstructor, constructorName);
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Unexpected content while parsing JSON.");
+ }
+ }
+
+ private void ParseNumber()
+ {
+ ShiftBufferIfNeeded();
+
+ char firstChar = _chars[_charPos];
+ int initialPosition = _charPos;
+
+ ReadNumberIntoBuffer();
+
+ // set state to PostValue now so that if there is an error parsing the number then the reader can continue
+ SetPostValueState(true);
+
+ _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+
+ object numberValue;
+ JsonToken numberType;
+
+ bool singleDigit = (char.IsDigit(firstChar) && _stringReference.Length == 1);
+ bool nonBase10 = (firstChar == '0' && _stringReference.Length > 1
+ && _stringReference.Chars[_stringReference.StartIndex + 1] != '.'
+ && _stringReference.Chars[_stringReference.StartIndex + 1] != 'e'
+ && _stringReference.Chars[_stringReference.StartIndex + 1] != 'E');
+
+ if (_readType == ReadType.ReadAsInt32)
+ {
+ if (singleDigit)
+ {
+ // digit char values start at 48
+ numberValue = firstChar - 48;
+ }
+ else if (nonBase10)
+ {
+ string number = _stringReference.ToString();
+
+ try
+ {
+ int integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
+ ? Convert.ToInt32(number, 16)
+ : Convert.ToInt32(number, 8);
+
+ numberValue = integer;
+ }
+ catch (Exception ex)
+ {
+ throw JsonReaderException.Create(this, "Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, number), ex);
+ }
+ }
+ else
+ {
+ int value;
+ ParseResult parseResult = ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value);
+ if (parseResult == ParseResult.Success)
+ numberValue = value;
+ else if (parseResult == ParseResult.Overflow)
+ throw JsonReaderException.Create(this, "JSON integer {0} is too large or small for an Int32.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+ else
+ throw JsonReaderException.Create(this, "Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+ }
+
+ numberType = JsonToken.Integer;
+ }
+ else if (_readType == ReadType.ReadAsDecimal)
+ {
+ if (singleDigit)
+ {
+ // digit char values start at 48
+ numberValue = (decimal)firstChar - 48;
+ }
+ else if (nonBase10)
+ {
+ string number = _stringReference.ToString();
+
+ try
+ {
+ // decimal.Parse doesn't support parsing hexadecimal values
+ long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
+ ? Convert.ToInt64(number, 16)
+ : Convert.ToInt64(number, 8);
+
+ numberValue = Convert.ToDecimal(integer);
+ }
+ catch (Exception ex)
+ {
+ throw JsonReaderException.Create(this, "Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, number), ex);
+ }
+ }
+ else
+ {
+ string number = _stringReference.ToString();
+
+ decimal value;
+ if (decimal.TryParse(number, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out value))
+ numberValue = value;
+ else
+ throw JsonReaderException.Create(this, "Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+ }
+
+ numberType = JsonToken.Float;
+ }
+ else
+ {
+ if (singleDigit)
+ {
+ // digit char values start at 48
+ numberValue = (long)firstChar - 48;
+ numberType = JsonToken.Integer;
+ }
+ else if (nonBase10)
+ {
+ string number = _stringReference.ToString();
+
+ try
+ {
+ numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
+ ? Convert.ToInt64(number, 16)
+ : Convert.ToInt64(number, 8);
+ }
+ catch (Exception ex)
+ {
+ throw JsonReaderException.Create(this, "Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, number), ex);
+ }
+
+ numberType = JsonToken.Integer;
+ }
+ else
+ {
+ long value;
+ ParseResult parseResult = ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value);
+ if (parseResult == ParseResult.Success)
+ {
+ numberValue = value;
+ numberType = JsonToken.Integer;
+ }
+ else if (parseResult == ParseResult.Overflow)
+ {
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+ string number = _stringReference.ToString();
+
+ if (number.Length > MaximumJavascriptIntegerCharacterLength)
+ throw JsonReaderException.Create(this, "JSON integer {0} is too large to parse.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+
+ numberValue = BigIntegerParse(number, CultureInfo.InvariantCulture);
+ numberType = JsonToken.Integer;
+#else
+ throw JsonReaderException.Create(this, "JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+#endif
+ }
+ else
+ {
+ string number = _stringReference.ToString();
+
+ if (_floatParseHandling == FloatParseHandling.Decimal)
+ {
+ decimal d;
+ if (decimal.TryParse(number, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out d))
+ numberValue = d;
+ else
+ throw JsonReaderException.Create(this, "Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, number));
+ }
+ else
+ {
+ double d;
+ if (double.TryParse(number, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out d))
+ numberValue = d;
+ else
+ throw JsonReaderException.Create(this, "Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, number));
+ }
+
+ numberType = JsonToken.Float;
+ }
+ }
+ }
+
+ ClearRecentString();
+
+ // index has already been updated
+ SetToken(numberType, numberValue, false);
+ }
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+ // By using the BigInteger type in a separate method,
+ // the runtime can execute the ParseNumber even if
+ // the System.Numerics.BigInteger.Parse method is
+ // missing, which happens in some versions of Mono
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static object BigIntegerParse(string number, CultureInfo culture)
+ {
+ return System.Numerics.BigInteger.Parse(number, culture);
+ }
+#endif
+
+ private void ParseComment()
+ {
+ // should have already parsed / character before reaching this method
+ _charPos++;
+
+ if (!EnsureChars(1, false))
+ throw JsonReaderException.Create(this, "Unexpected end while parsing comment.");
+
+ bool singlelineComment;
+
+ if (_chars[_charPos] == '*')
+ singlelineComment = false;
+ else if (_chars[_charPos] == '/')
+ singlelineComment = true;
+ else
+ throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+
+ _charPos++;
+
+ int initialPosition = _charPos;
+
+ bool commentFinished = false;
+
+ while (!commentFinished)
+ {
+ switch (_chars[_charPos])
+ {
+ case '\0':
+ if (_charsUsed == _charPos)
+ {
+ if (ReadData(true) == 0)
+ {
+ if (!singlelineComment)
+ throw JsonReaderException.Create(this, "Unexpected end while parsing comment.");
+
+ _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+ commentFinished = true;
+ }
+ }
+ else
+ {
+ _charPos++;
+ }
+ break;
+ case '*':
+ _charPos++;
+
+ if (!singlelineComment)
+ {
+ if (EnsureChars(0, true))
+ {
+ if (_chars[_charPos] == '/')
+ {
+ _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition - 1);
+
+ _charPos++;
+ commentFinished = true;
+ }
+ }
+ }
+ break;
+ case StringUtils.CarriageReturn:
+ if (singlelineComment)
+ {
+ _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+ commentFinished = true;
+ }
+ ProcessCarriageReturn(true);
+ break;
+ case StringUtils.LineFeed:
+ if (singlelineComment)
+ {
+ _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+ commentFinished = true;
+ }
+ ProcessLineFeed();
+ break;
+ default:
+ _charPos++;
+ break;
+ }
+ }
+
+ SetToken(JsonToken.Comment, _stringReference.ToString());
+
+ ClearRecentString();
+ }
+
+ private bool MatchValue(string value)
+ {
+ if (!EnsureChars(value.Length - 1, true))
+ return false;
+
+ for (int i = 0; i < value.Length; i++)
+ {
+ if (_chars[_charPos + i] != value[i])
+ {
+ return false;
+ }
+ }
+
+ _charPos += value.Length;
+
+ return true;
+ }
+
+ private bool MatchValueWithTrailingSeparator(string value)
+ {
+ // will match value and then move to the next character, checking that it is a separator character
+ bool match = MatchValue(value);
+
+ if (!match)
+ return false;
+
+ if (!EnsureChars(0, false))
+ return true;
+
+ return IsSeparator(_chars[_charPos]) || _chars[_charPos] == '\0';
+ }
+
+ private bool IsSeparator(char c)
+ {
+ switch (c)
+ {
+ case '}':
+ case ']':
+ case ',':
+ return true;
+ case '/':
+ // check next character to see if start of a comment
+ if (!EnsureChars(1, false))
+ return false;
+
+ var nextChart = _chars[_charPos + 1];
+
+ return (nextChart == '*' || nextChart == '/');
+ case ')':
+ if (CurrentState == State.Constructor || CurrentState == State.ConstructorStart)
+ return true;
+ break;
+ case ' ':
+ case StringUtils.Tab:
+ case StringUtils.LineFeed:
+ case StringUtils.CarriageReturn:
+ return true;
+ default:
+ if (char.IsWhiteSpace(c))
+ return true;
+ break;
+ }
+
+ return false;
+ }
+
+ private void ParseTrue()
+ {
+ // check characters equal 'true'
+ // and that it is followed by either a separator character
+ // or the text ends
+ if (MatchValueWithTrailingSeparator(JsonConvert.True))
+ {
+ SetToken(JsonToken.Boolean, true);
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Error parsing boolean value.");
+ }
+ }
+
+ private void ParseNull()
+ {
+ if (MatchValueWithTrailingSeparator(JsonConvert.Null))
+ {
+ SetToken(JsonToken.Null);
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Error parsing null value.");
+ }
+ }
+
+ private void ParseUndefined()
+ {
+ if (MatchValueWithTrailingSeparator(JsonConvert.Undefined))
+ {
+ SetToken(JsonToken.Undefined);
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Error parsing undefined value.");
+ }
+ }
+
+ private void ParseFalse()
+ {
+ if (MatchValueWithTrailingSeparator(JsonConvert.False))
+ {
+ SetToken(JsonToken.Boolean, false);
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Error parsing boolean value.");
+ }
+ }
+
+ private void ParseNumberNegativeInfinity()
+ {
+ if (MatchValueWithTrailingSeparator(JsonConvert.NegativeInfinity))
+ {
+ if (_floatParseHandling == FloatParseHandling.Decimal)
+ throw new JsonReaderException("Cannot read -Infinity as a decimal.");
+
+ SetToken(JsonToken.Float, double.NegativeInfinity);
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Error parsing negative infinity value.");
+ }
+ }
+
+ private void ParseNumberPositiveInfinity()
+ {
+ if (MatchValueWithTrailingSeparator(JsonConvert.PositiveInfinity))
+ {
+ if (_floatParseHandling == FloatParseHandling.Decimal)
+ throw new JsonReaderException("Cannot read Infinity as a decimal.");
+
+ SetToken(JsonToken.Float, double.PositiveInfinity);
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Error parsing positive infinity value.");
+ }
+ }
+
+ private void ParseNumberNaN()
+ {
+ if (MatchValueWithTrailingSeparator(JsonConvert.NaN))
+ {
+ if (_floatParseHandling == FloatParseHandling.Decimal)
+ throw new JsonReaderException("Cannot read NaN as a decimal.");
+
+ SetToken(JsonToken.Float, double.NaN);
+ }
+ else
+ {
+ throw JsonReaderException.Create(this, "Error parsing NaN value.");
+ }
+ }
+
+ ///
+ /// Changes the state to closed.
+ ///
+ public override void Close()
+ {
+ base.Close();
+
+ if (CloseInput && _reader != null)
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ _reader.Close();
+#else
+ _reader.Dispose();
+#endif
+
+ if (_buffer != null)
+ _buffer.Clear();
+ }
+
+ ///
+ /// Gets a value indicating whether the class can return line information.
+ ///
+ ///
+ /// true if LineNumber and LinePosition can be provided; otherwise, false .
+ ///
+ public bool HasLineInfo()
+ {
+ return true;
+ }
+
+ ///
+ /// Gets the current line number.
+ ///
+ ///
+ /// The current line number or 0 if no line information is available (for example, HasLineInfo returns false).
+ ///
+ public int LineNumber
+ {
+ get
+ {
+ if (CurrentState == State.Start && LinePosition == 0)
+ return 0;
+
+ return _lineNumber;
+ }
+ }
+
+ ///
+ /// Gets the current line position.
+ ///
+ ///
+ /// The current line position or 0 if no line information is available (for example, HasLineInfo returns false).
+ ///
+ public int LinePosition
+ {
+ get { return _charPos - _lineStartPos; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonTextWriter.cs b/Libs/JsonNet/JsonTextWriter.cs
new file mode 100644
index 0000000..7a48fec
--- /dev/null
+++ b/Libs/JsonNet/JsonTextWriter.cs
@@ -0,0 +1,758 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using System.Text;
+using System.IO;
+using System.Xml;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
+ ///
+ public class JsonTextWriter : JsonWriter
+ {
+ private readonly TextWriter _writer;
+ private Base64Encoder _base64Encoder;
+ private char _indentChar;
+ private int _indentation;
+ private char _quoteChar;
+ private bool _quoteName;
+ private bool[] _charEscapeFlags;
+ private char[] _writeBuffer;
+ private char[] _indentChars;
+
+ private Base64Encoder Base64Encoder
+ {
+ get
+ {
+ if (_base64Encoder == null)
+ _base64Encoder = new Base64Encoder(_writer);
+
+ return _base64Encoder;
+ }
+ }
+
+ ///
+ /// Gets or sets how many IndentChars to write for each level in the hierarchy when is set to Formatting.Indented .
+ ///
+ public int Indentation
+ {
+ get { return _indentation; }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException("Indentation value must be greater than 0.");
+
+ _indentation = value;
+ }
+ }
+
+ ///
+ /// Gets or sets which character to use to quote attribute values.
+ ///
+ public char QuoteChar
+ {
+ get { return _quoteChar; }
+ set
+ {
+ if (value != '"' && value != '\'')
+ throw new ArgumentException(@"Invalid JavaScript string quote character. Valid quote characters are ' and "".");
+
+ _quoteChar = value;
+ UpdateCharEscapeFlags();
+ }
+ }
+
+ ///
+ /// Gets or sets which character to use for indenting when is set to Formatting.Indented .
+ ///
+ public char IndentChar
+ {
+ get { return _indentChar; }
+ set
+ {
+ if (value != _indentChar)
+ {
+ _indentChar = value;
+ _indentChars = null;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether object names will be surrounded with quotes.
+ ///
+ public bool QuoteName
+ {
+ get { return _quoteName; }
+ set { _quoteName = value; }
+ }
+
+ ///
+ /// Creates an instance of the JsonWriter class using the specified .
+ ///
+ /// The TextWriter to write to.
+ public JsonTextWriter(TextWriter textWriter)
+ {
+ if (textWriter == null)
+ throw new ArgumentNullException("textWriter");
+
+ _writer = textWriter;
+ _quoteChar = '"';
+ _quoteName = true;
+ _indentChar = ' ';
+ _indentation = 2;
+
+ UpdateCharEscapeFlags();
+ }
+
+ ///
+ /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+ ///
+ public override void Flush()
+ {
+ _writer.Flush();
+ }
+
+ ///
+ /// Closes this stream and the underlying stream.
+ ///
+ public override void Close()
+ {
+ base.Close();
+
+ if (CloseOutput && _writer != null)
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ _writer.Close();
+#else
+ _writer.Dispose();
+#endif
+ }
+
+ ///
+ /// Writes the beginning of a Json object.
+ ///
+ public override void WriteStartObject()
+ {
+ InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object);
+
+ _writer.Write('{');
+ }
+
+ ///
+ /// Writes the beginning of a Json array.
+ ///
+ public override void WriteStartArray()
+ {
+ InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array);
+
+ _writer.Write('[');
+ }
+
+ ///
+ /// Writes the start of a constructor with the given name.
+ ///
+ /// The name of the constructor.
+ public override void WriteStartConstructor(string name)
+ {
+ InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor);
+
+ _writer.Write("new ");
+ _writer.Write(name);
+ _writer.Write('(');
+ }
+
+ ///
+ /// Writes the specified end token.
+ ///
+ /// The end token to write.
+ protected override void WriteEnd(JsonToken token)
+ {
+ switch (token)
+ {
+ case JsonToken.EndObject:
+ _writer.Write('}');
+ break;
+ case JsonToken.EndArray:
+ _writer.Write(']');
+ break;
+ case JsonToken.EndConstructor:
+ _writer.Write(')');
+ break;
+ default:
+ throw JsonWriterException.Create(this, "Invalid JsonToken: " + token, null);
+ }
+ }
+
+ ///
+ /// Writes the property name of a name/value pair on a Json object.
+ ///
+ /// The name of the property.
+ public override void WritePropertyName(string name)
+ {
+ InternalWritePropertyName(name);
+
+ WriteEscapedString(name, _quoteName);
+
+ _writer.Write(':');
+ }
+
+ ///
+ /// Writes the property name of a name/value pair on a JSON object.
+ ///
+ /// The name of the property.
+ /// A flag to indicate whether the text should be escaped when it is written as a JSON property name.
+ public override void WritePropertyName(string name, bool escape)
+ {
+ InternalWritePropertyName(name);
+
+ if (escape)
+ {
+ WriteEscapedString(name, _quoteName);
+ }
+ else
+ {
+ if (_quoteName)
+ _writer.Write(_quoteChar);
+
+ _writer.Write(name);
+
+ if (_quoteName)
+ _writer.Write(_quoteChar);
+ }
+
+ _writer.Write(':');
+ }
+
+ internal override void OnStringEscapeHandlingChanged()
+ {
+ UpdateCharEscapeFlags();
+ }
+
+ private void UpdateCharEscapeFlags()
+ {
+ _charEscapeFlags = JavaScriptUtils.GetCharEscapeFlags(StringEscapeHandling, _quoteChar);
+ }
+
+ ///
+ /// Writes indent characters.
+ ///
+ protected override void WriteIndent()
+ {
+ _writer.WriteLine();
+
+ // levels of indentation multiplied by the indent count
+ int currentIndentCount = Top * _indentation;
+
+ if (currentIndentCount > 0)
+ {
+ if (_indentChars == null)
+ _indentChars = new string(_indentChar, 10).ToCharArray();
+
+ while (currentIndentCount > 0)
+ {
+ int writeCount = Math.Min(currentIndentCount, 10);
+
+ _writer.Write(_indentChars, 0, writeCount);
+
+ currentIndentCount -= writeCount;
+ }
+ }
+ }
+
+ ///
+ /// Writes the JSON value delimiter.
+ ///
+ protected override void WriteValueDelimiter()
+ {
+ _writer.Write(',');
+ }
+
+ ///
+ /// Writes an indent space.
+ ///
+ protected override void WriteIndentSpace()
+ {
+ _writer.Write(' ');
+ }
+
+ private void WriteValueInternal(string value, JsonToken token)
+ {
+ _writer.Write(value);
+ }
+
+ #region WriteValue methods
+ ///
+ /// Writes a value.
+ /// An error will raised if the value cannot be written as a single JSON token.
+ ///
+ /// The value to write.
+ public override void WriteValue(object value)
+ {
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+ if (value is BigInteger)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteValueInternal(((BigInteger)value).ToString(CultureInfo.InvariantCulture), JsonToken.String);
+ }
+ else
+#endif
+ {
+ base.WriteValue(value);
+ }
+ }
+
+ ///
+ /// Writes a null value.
+ ///
+ public override void WriteNull()
+ {
+ InternalWriteValue(JsonToken.Null);
+ WriteValueInternal(JsonConvert.Null, JsonToken.Null);
+ }
+
+ ///
+ /// Writes an undefined value.
+ ///
+ public override void WriteUndefined()
+ {
+ InternalWriteValue(JsonToken.Undefined);
+ WriteValueInternal(JsonConvert.Undefined, JsonToken.Undefined);
+ }
+
+ ///
+ /// Writes raw JSON.
+ ///
+ /// The raw JSON to write.
+ public override void WriteRaw(string json)
+ {
+ InternalWriteRaw();
+
+ _writer.Write(json);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(string value)
+ {
+ InternalWriteValue(JsonToken.String);
+
+ if (value == null)
+ WriteValueInternal(JsonConvert.Null, JsonToken.Null);
+ else
+ WriteEscapedString(value, true);
+ }
+
+ private void WriteEscapedString(string value, bool quote)
+ {
+ EnsureWriteBuffer();
+ JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags, StringEscapeHandling, ref _writeBuffer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(int value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteIntegerValue(value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public override void WriteValue(uint value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteIntegerValue(value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(long value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteIntegerValue(value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public override void WriteValue(ulong value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteIntegerValue(value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(float value)
+ {
+ InternalWriteValue(JsonToken.Float);
+ WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, false), JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(float? value)
+ {
+ if (value == null)
+ {
+ WriteNull();
+ }
+ else
+ {
+ InternalWriteValue(JsonToken.Float);
+ WriteValueInternal(JsonConvert.ToString(value.Value, FloatFormatHandling, QuoteChar, true), JsonToken.Float);
+ }
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(double value)
+ {
+ InternalWriteValue(JsonToken.Float);
+ WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, false), JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(double? value)
+ {
+ if (value == null)
+ {
+ WriteNull();
+ }
+ else
+ {
+ InternalWriteValue(JsonToken.Float);
+ WriteValueInternal(JsonConvert.ToString(value.Value, FloatFormatHandling, QuoteChar, true), JsonToken.Float);
+ }
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(bool value)
+ {
+ InternalWriteValue(JsonToken.Boolean);
+ WriteValueInternal(JsonConvert.ToString(value), JsonToken.Boolean);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(short value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteIntegerValue(value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public override void WriteValue(ushort value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteIntegerValue(value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(char value)
+ {
+ InternalWriteValue(JsonToken.String);
+ WriteValueInternal(JsonConvert.ToString(value), JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(byte value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteIntegerValue(value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public override void WriteValue(sbyte value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ WriteIntegerValue(value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(decimal value)
+ {
+ InternalWriteValue(JsonToken.Float);
+ WriteValueInternal(JsonConvert.ToString(value), JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(DateTime value)
+ {
+ InternalWriteValue(JsonToken.Date);
+ value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
+
+ if (string.IsNullOrEmpty(DateFormatString))
+ {
+ EnsureWriteBuffer();
+
+ int pos = 0;
+ _writeBuffer[pos++] = _quoteChar;
+ pos = DateTimeUtils.WriteDateTimeString(_writeBuffer, pos, value, null, value.Kind, DateFormatHandling);
+ _writeBuffer[pos++] = _quoteChar;
+
+ _writer.Write(_writeBuffer, 0, pos);
+ }
+ else
+ {
+ _writer.Write(_quoteChar);
+ _writer.Write(value.ToString(DateFormatString, Culture));
+ _writer.Write(_quoteChar);
+ }
+ }
+
+ ///
+ /// Writes a [] value.
+ ///
+ /// The [] value to write.
+ public override void WriteValue(byte[] value)
+ {
+ if (value == null)
+ {
+ WriteNull();
+ }
+ else
+ {
+ InternalWriteValue(JsonToken.Bytes);
+ _writer.Write(_quoteChar);
+ Base64Encoder.Encode(value, 0, value.Length);
+ Base64Encoder.Flush();
+ _writer.Write(_quoteChar);
+ }
+ }
+
+#if !NET20
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(DateTimeOffset value)
+ {
+ InternalWriteValue(JsonToken.Date);
+
+ if (string.IsNullOrEmpty(DateFormatString))
+ {
+ EnsureWriteBuffer();
+
+ int pos = 0;
+ _writeBuffer[pos++] = _quoteChar;
+ pos = DateTimeUtils.WriteDateTimeString(_writeBuffer, pos, (DateFormatHandling == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, DateFormatHandling);
+ _writeBuffer[pos++] = _quoteChar;
+
+ _writer.Write(_writeBuffer, 0, pos);
+ }
+ else
+ {
+ _writer.Write(_quoteChar);
+ _writer.Write(value.ToString(DateFormatString, Culture));
+ _writer.Write(_quoteChar);
+ }
+ }
+#endif
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(Guid value)
+ {
+ InternalWriteValue(JsonToken.String);
+
+ string text = null;
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ text = value.ToString("D", CultureInfo.InvariantCulture);
+#else
+ text = value.ToString("D");
+#endif
+
+ _writer.Write(_quoteChar);
+ _writer.Write(text);
+ _writer.Write(_quoteChar);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(TimeSpan value)
+ {
+ InternalWriteValue(JsonToken.String);
+
+ string text;
+#if (NET35 || NET20)
+ text = value.ToString();
+#else
+ text = value.ToString(null, CultureInfo.InvariantCulture);
+#endif
+
+ _writer.Write(_quoteChar);
+ _writer.Write(text);
+ _writer.Write(_quoteChar);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public override void WriteValue(Uri value)
+ {
+ if (value == null)
+ {
+ WriteNull();
+ }
+ else
+ {
+ InternalWriteValue(JsonToken.String);
+ WriteEscapedString(value.OriginalString, true);
+ }
+ }
+ #endregion
+
+ ///
+ /// Writes out a comment /*...*/
containing the specified text.
+ ///
+ /// Text to place inside the comment.
+ public override void WriteComment(string text)
+ {
+ InternalWriteComment();
+
+ _writer.Write("/*");
+ _writer.Write(text);
+ _writer.Write("*/");
+ }
+
+ ///
+ /// Writes out the given white space.
+ ///
+ /// The string of white space characters.
+ public override void WriteWhitespace(string ws)
+ {
+ InternalWriteWhitespace(ws);
+
+ _writer.Write(ws);
+ }
+
+ private void EnsureWriteBuffer()
+ {
+ if (_writeBuffer == null)
+ _writeBuffer = new char[35]; // maximum buffer sized used when writing iso date
+ }
+
+ private void WriteIntegerValue(long value)
+ {
+ if (value >= 0 && value <= 9)
+ {
+ _writer.Write((char)('0' + value));
+ }
+ else
+ {
+ ulong uvalue = (value < 0) ? (ulong)-value : (ulong)value;
+
+ if (value < 0)
+ _writer.Write('-');
+
+ WriteIntegerValue(uvalue);
+ }
+ }
+
+ private void WriteIntegerValue(ulong uvalue)
+ {
+ if (uvalue <= 9)
+ {
+ _writer.Write((char)('0' + uvalue));
+ }
+ else
+ {
+ EnsureWriteBuffer();
+
+ int totalLength = MathUtils.IntLength(uvalue);
+ int length = 0;
+
+ do
+ {
+ _writeBuffer[totalLength - ++length] = (char)('0' + (uvalue % 10));
+ uvalue /= 10;
+ } while (uvalue != 0);
+
+ _writer.Write(_writeBuffer, 0, length);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonToken.cs b/Libs/JsonNet/JsonToken.cs
new file mode 100644
index 0000000..a159902
--- /dev/null
+++ b/Libs/JsonNet/JsonToken.cs
@@ -0,0 +1,127 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Specifies the type of Json token.
+ ///
+ public enum JsonToken
+ {
+ ///
+ /// This is returned by the if a method has not been called.
+ ///
+ None,
+
+ ///
+ /// An object start token.
+ ///
+ StartObject,
+
+ ///
+ /// An array start token.
+ ///
+ StartArray,
+
+ ///
+ /// A constructor start token.
+ ///
+ StartConstructor,
+
+ ///
+ /// An object property name.
+ ///
+ PropertyName,
+
+ ///
+ /// A comment.
+ ///
+ Comment,
+
+ ///
+ /// Raw JSON.
+ ///
+ Raw,
+
+ ///
+ /// An integer.
+ ///
+ Integer,
+
+ ///
+ /// A float.
+ ///
+ Float,
+
+ ///
+ /// A string.
+ ///
+ String,
+
+ ///
+ /// A boolean.
+ ///
+ Boolean,
+
+ ///
+ /// A null token.
+ ///
+ Null,
+
+ ///
+ /// An undefined token.
+ ///
+ Undefined,
+
+ ///
+ /// An object end token.
+ ///
+ EndObject,
+
+ ///
+ /// An array end token.
+ ///
+ EndArray,
+
+ ///
+ /// A constructor end token.
+ ///
+ EndConstructor,
+
+ ///
+ /// A Date.
+ ///
+ Date,
+
+ ///
+ /// Byte data.
+ ///
+ Bytes
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonValidatingReader.cs b/Libs/JsonNet/JsonValidatingReader.cs
new file mode 100644
index 0000000..a02d2de
--- /dev/null
+++ b/Libs/JsonNet/JsonValidatingReader.cs
@@ -0,0 +1,916 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+using System.Text.RegularExpressions;
+using System.IO;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Represents a reader that provides validation.
+ ///
+ public class JsonValidatingReader : JsonReader, IJsonLineInfo
+ {
+ private class SchemaScope
+ {
+ private readonly JTokenType _tokenType;
+ private readonly IList _schemas;
+ private readonly Dictionary _requiredProperties;
+
+ public string CurrentPropertyName { get; set; }
+ public int ArrayItemCount { get; set; }
+ public bool IsUniqueArray { get; set; }
+ public IList UniqueArrayItems { get; set; }
+ public JTokenWriter CurrentItemWriter { get; set; }
+
+ public IList Schemas
+ {
+ get { return _schemas; }
+ }
+
+ public Dictionary RequiredProperties
+ {
+ get { return _requiredProperties; }
+ }
+
+ public JTokenType TokenType
+ {
+ get { return _tokenType; }
+ }
+
+ public SchemaScope(JTokenType tokenType, IList schemas)
+ {
+ _tokenType = tokenType;
+ _schemas = schemas;
+
+ _requiredProperties = schemas.SelectMany(GetRequiredProperties).Distinct().ToDictionary(p => p, p => false);
+
+ if (tokenType == JTokenType.Array && schemas.Any(s => s.UniqueItems))
+ {
+ IsUniqueArray = true;
+ UniqueArrayItems = new List();
+ }
+ }
+
+ private IEnumerable GetRequiredProperties(JsonSchemaModel schema)
+ {
+ if (schema == null || schema.Properties == null)
+ return Enumerable.Empty();
+
+ return schema.Properties.Where(p => p.Value.Required).Select(p => p.Key);
+ }
+ }
+
+ private readonly JsonReader _reader;
+ private readonly Stack _stack;
+ private JsonSchema _schema;
+ private JsonSchemaModel _model;
+ private SchemaScope _currentScope;
+
+ ///
+ /// Sets an event handler for receiving schema validation errors.
+ ///
+ public event ValidationEventHandler ValidationEventHandler;
+
+ ///
+ /// Gets the text value of the current JSON token.
+ ///
+ ///
+ public override object Value
+ {
+ get { return _reader.Value; }
+ }
+
+ ///
+ /// Gets the depth of the current token in the JSON document.
+ ///
+ /// The depth of the current token in the JSON document.
+ public override int Depth
+ {
+ get { return _reader.Depth; }
+ }
+
+ ///
+ /// Gets the path of the current JSON token.
+ ///
+ public override string Path
+ {
+ get { return _reader.Path; }
+ }
+
+ ///
+ /// Gets the quotation mark character used to enclose the value of a string.
+ ///
+ ///
+ public override char QuoteChar
+ {
+ get { return _reader.QuoteChar; }
+ protected internal set { }
+ }
+
+ ///
+ /// Gets the type of the current JSON token.
+ ///
+ ///
+ public override JsonToken TokenType
+ {
+ get { return _reader.TokenType; }
+ }
+
+ ///
+ /// Gets the Common Language Runtime (CLR) type for the current JSON token.
+ ///
+ ///
+ public override Type ValueType
+ {
+ get { return _reader.ValueType; }
+ }
+
+ private void Push(SchemaScope scope)
+ {
+ _stack.Push(scope);
+ _currentScope = scope;
+ }
+
+ private SchemaScope Pop()
+ {
+ SchemaScope poppedScope = _stack.Pop();
+ _currentScope = (_stack.Count != 0)
+ ? _stack.Peek()
+ : null;
+
+ return poppedScope;
+ }
+
+ private IList CurrentSchemas
+ {
+ get { return _currentScope.Schemas; }
+ }
+
+ private static readonly IList EmptySchemaList = new List();
+
+ private IList CurrentMemberSchemas
+ {
+ get
+ {
+ if (_currentScope == null)
+ return new List(new[] { _model });
+
+ if (_currentScope.Schemas == null || _currentScope.Schemas.Count == 0)
+ return EmptySchemaList;
+
+ switch (_currentScope.TokenType)
+ {
+ case JTokenType.None:
+ return _currentScope.Schemas;
+ case JTokenType.Object:
+ {
+ if (_currentScope.CurrentPropertyName == null)
+ throw new JsonReaderException("CurrentPropertyName has not been set on scope.");
+
+ IList schemas = new List();
+
+ foreach (JsonSchemaModel schema in CurrentSchemas)
+ {
+ JsonSchemaModel propertySchema;
+ if (schema.Properties != null && schema.Properties.TryGetValue(_currentScope.CurrentPropertyName, out propertySchema))
+ {
+ schemas.Add(propertySchema);
+ }
+ if (schema.PatternProperties != null)
+ {
+ foreach (KeyValuePair patternProperty in schema.PatternProperties)
+ {
+ if (Regex.IsMatch(_currentScope.CurrentPropertyName, patternProperty.Key))
+ {
+ schemas.Add(patternProperty.Value);
+ }
+ }
+ }
+
+ if (schemas.Count == 0 && schema.AllowAdditionalProperties && schema.AdditionalProperties != null)
+ schemas.Add(schema.AdditionalProperties);
+ }
+
+ return schemas;
+ }
+ case JTokenType.Array:
+ {
+ IList schemas = new List();
+
+ foreach (JsonSchemaModel schema in CurrentSchemas)
+ {
+ if (!schema.PositionalItemsValidation)
+ {
+ if (schema.Items != null && schema.Items.Count > 0)
+ schemas.Add(schema.Items[0]);
+ }
+ else
+ {
+ if (schema.Items != null && schema.Items.Count > 0)
+ {
+ if (schema.Items.Count > (_currentScope.ArrayItemCount - 1))
+ schemas.Add(schema.Items[_currentScope.ArrayItemCount - 1]);
+ }
+
+ if (schema.AllowAdditionalItems && schema.AdditionalItems != null)
+ schemas.Add(schema.AdditionalItems);
+ }
+ }
+
+ return schemas;
+ }
+ case JTokenType.Constructor:
+ return EmptySchemaList;
+ default:
+ throw new ArgumentOutOfRangeException("TokenType", "Unexpected token type: {0}".FormatWith(CultureInfo.InvariantCulture, _currentScope.TokenType));
+ }
+ }
+ }
+
+ private void RaiseError(string message, JsonSchemaModel schema)
+ {
+ IJsonLineInfo lineInfo = this;
+
+ string exceptionMessage = (lineInfo.HasLineInfo())
+ ? message + " Line {0}, position {1}.".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition)
+ : message;
+
+ OnValidationEvent(new JsonSchemaException(exceptionMessage, null, Path, lineInfo.LineNumber, lineInfo.LinePosition));
+ }
+
+ private void OnValidationEvent(JsonSchemaException exception)
+ {
+ ValidationEventHandler handler = ValidationEventHandler;
+ if (handler != null)
+ handler(this, new ValidationEventArgs(exception));
+ else
+ throw exception;
+ }
+
+ ///
+ /// Initializes a new instance of the class that
+ /// validates the content returned from the given .
+ ///
+ /// The to read from while validating.
+ public JsonValidatingReader(JsonReader reader)
+ {
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+ _reader = reader;
+ _stack = new Stack();
+ }
+
+ ///
+ /// Gets or sets the schema.
+ ///
+ /// The schema.
+ public JsonSchema Schema
+ {
+ get { return _schema; }
+ set
+ {
+ if (TokenType != JsonToken.None)
+ throw new InvalidOperationException("Cannot change schema while validating JSON.");
+
+ _schema = value;
+ _model = null;
+ }
+ }
+
+ ///
+ /// Gets the used to construct this .
+ ///
+ /// The specified in the constructor.
+ public JsonReader Reader
+ {
+ get { return _reader; }
+ }
+
+ private void ValidateNotDisallowed(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ JsonSchemaType? currentNodeType = GetCurrentNodeSchemaType();
+ if (currentNodeType != null)
+ {
+ if (JsonSchemaGenerator.HasFlag(schema.Disallow, currentNodeType.Value))
+ RaiseError("Type {0} is disallowed.".FormatWith(CultureInfo.InvariantCulture, currentNodeType), schema);
+ }
+ }
+
+ private JsonSchemaType? GetCurrentNodeSchemaType()
+ {
+ switch (_reader.TokenType)
+ {
+ case JsonToken.StartObject:
+ return JsonSchemaType.Object;
+ case JsonToken.StartArray:
+ return JsonSchemaType.Array;
+ case JsonToken.Integer:
+ return JsonSchemaType.Integer;
+ case JsonToken.Float:
+ return JsonSchemaType.Float;
+ case JsonToken.String:
+ return JsonSchemaType.String;
+ case JsonToken.Boolean:
+ return JsonSchemaType.Boolean;
+ case JsonToken.Null:
+ return JsonSchemaType.Null;
+ default:
+ return null;
+ }
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A .
+ public override int? ReadAsInt32()
+ {
+ int? i = _reader.ReadAsInt32();
+
+ ValidateCurrentToken();
+ return i;
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a [].
+ ///
+ ///
+ /// A [] or a null reference if the next JSON token is null.
+ ///
+ public override byte[] ReadAsBytes()
+ {
+ byte[] data = _reader.ReadAsBytes();
+
+ ValidateCurrentToken();
+ return data;
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A .
+ public override decimal? ReadAsDecimal()
+ {
+ decimal? d = _reader.ReadAsDecimal();
+
+ ValidateCurrentToken();
+ return d;
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override string ReadAsString()
+ {
+ string s = _reader.ReadAsString();
+
+ ValidateCurrentToken();
+ return s;
+ }
+
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A . This method will return null at the end of an array.
+ public override DateTime? ReadAsDateTime()
+ {
+ DateTime? dateTime = _reader.ReadAsDateTime();
+
+ ValidateCurrentToken();
+ return dateTime;
+ }
+
+#if !NET20
+ ///
+ /// Reads the next JSON token from the stream as a .
+ ///
+ /// A .
+ public override DateTimeOffset? ReadAsDateTimeOffset()
+ {
+ DateTimeOffset? dateTimeOffset = _reader.ReadAsDateTimeOffset();
+
+ ValidateCurrentToken();
+ return dateTimeOffset;
+ }
+#endif
+
+ ///
+ /// Reads the next JSON token from the stream.
+ ///
+ ///
+ /// true if the next token was read successfully; false if there are no more tokens to read.
+ ///
+ public override bool Read()
+ {
+ if (!_reader.Read())
+ return false;
+
+ if (_reader.TokenType == JsonToken.Comment)
+ return true;
+
+ ValidateCurrentToken();
+ return true;
+ }
+
+ private void ValidateCurrentToken()
+ {
+ // first time validate has been called. build model
+ if (_model == null)
+ {
+ JsonSchemaModelBuilder builder = new JsonSchemaModelBuilder();
+ _model = builder.Build(_schema);
+
+ if (!JsonWriter.IsStartToken(_reader.TokenType))
+ Push(new SchemaScope(JTokenType.None, CurrentMemberSchemas));
+ }
+
+ switch (_reader.TokenType)
+ {
+ case JsonToken.StartObject:
+ ProcessValue();
+ IList objectSchemas = CurrentMemberSchemas.Where(ValidateObject).ToList();
+ Push(new SchemaScope(JTokenType.Object, objectSchemas));
+ WriteToken(CurrentSchemas);
+ break;
+ case JsonToken.StartArray:
+ ProcessValue();
+ IList arraySchemas = CurrentMemberSchemas.Where(ValidateArray).ToList();
+ Push(new SchemaScope(JTokenType.Array, arraySchemas));
+ WriteToken(CurrentSchemas);
+ break;
+ case JsonToken.StartConstructor:
+ ProcessValue();
+ Push(new SchemaScope(JTokenType.Constructor, null));
+ WriteToken(CurrentSchemas);
+ break;
+ case JsonToken.PropertyName:
+ WriteToken(CurrentSchemas);
+ foreach (JsonSchemaModel schema in CurrentSchemas)
+ {
+ ValidatePropertyName(schema);
+ }
+ break;
+ case JsonToken.Raw:
+ ProcessValue();
+ break;
+ case JsonToken.Integer:
+ ProcessValue();
+ WriteToken(CurrentMemberSchemas);
+ foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+ {
+ ValidateInteger(schema);
+ }
+ break;
+ case JsonToken.Float:
+ ProcessValue();
+ WriteToken(CurrentMemberSchemas);
+ foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+ {
+ ValidateFloat(schema);
+ }
+ break;
+ case JsonToken.String:
+ ProcessValue();
+ WriteToken(CurrentMemberSchemas);
+ foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+ {
+ ValidateString(schema);
+ }
+ break;
+ case JsonToken.Boolean:
+ ProcessValue();
+ WriteToken(CurrentMemberSchemas);
+ foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+ {
+ ValidateBoolean(schema);
+ }
+ break;
+ case JsonToken.Null:
+ ProcessValue();
+ WriteToken(CurrentMemberSchemas);
+ foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+ {
+ ValidateNull(schema);
+ }
+ break;
+ case JsonToken.EndObject:
+ WriteToken(CurrentSchemas);
+ foreach (JsonSchemaModel schema in CurrentSchemas)
+ {
+ ValidateEndObject(schema);
+ }
+ Pop();
+ break;
+ case JsonToken.EndArray:
+ WriteToken(CurrentSchemas);
+ foreach (JsonSchemaModel schema in CurrentSchemas)
+ {
+ ValidateEndArray(schema);
+ }
+ Pop();
+ break;
+ case JsonToken.EndConstructor:
+ WriteToken(CurrentSchemas);
+ Pop();
+ break;
+ case JsonToken.Undefined:
+ case JsonToken.Date:
+ case JsonToken.Bytes:
+ // these have no equivalent in JSON schema
+ WriteToken(CurrentMemberSchemas);
+ break;
+ case JsonToken.None:
+ // no content, do nothing
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ private void WriteToken(IList schemas)
+ {
+ foreach (SchemaScope schemaScope in _stack)
+ {
+ bool isInUniqueArray = (schemaScope.TokenType == JTokenType.Array && schemaScope.IsUniqueArray && schemaScope.ArrayItemCount > 0);
+
+ if (isInUniqueArray || schemas.Any(s => s.Enum != null))
+ {
+ if (schemaScope.CurrentItemWriter == null)
+ {
+ if (JsonWriter.IsEndToken(_reader.TokenType))
+ continue;
+
+ schemaScope.CurrentItemWriter = new JTokenWriter();
+ }
+
+ schemaScope.CurrentItemWriter.WriteToken(_reader, false);
+
+ // finished writing current item
+ if (schemaScope.CurrentItemWriter.Top == 0 && _reader.TokenType != JsonToken.PropertyName)
+ {
+ JToken finishedItem = schemaScope.CurrentItemWriter.Token;
+
+ // start next item with new writer
+ schemaScope.CurrentItemWriter = null;
+
+ if (isInUniqueArray)
+ {
+ if (schemaScope.UniqueArrayItems.Contains(finishedItem, JToken.EqualityComparer))
+ RaiseError("Non-unique array item at index {0}.".FormatWith(CultureInfo.InvariantCulture, schemaScope.ArrayItemCount - 1), schemaScope.Schemas.First(s => s.UniqueItems));
+
+ schemaScope.UniqueArrayItems.Add(finishedItem);
+ }
+ else if (schemas.Any(s => s.Enum != null))
+ {
+ foreach (JsonSchemaModel schema in schemas)
+ {
+ if (schema.Enum != null)
+ {
+ if (!schema.Enum.ContainsValue(finishedItem, JToken.EqualityComparer))
+ {
+ StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
+ finishedItem.WriteTo(new JsonTextWriter(sw));
+
+ RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, sw.ToString()), schema);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void ValidateEndObject(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ Dictionary requiredProperties = _currentScope.RequiredProperties;
+
+ if (requiredProperties != null)
+ {
+ List unmatchedRequiredProperties =
+ requiredProperties.Where(kv => !kv.Value).Select(kv => kv.Key).ToList();
+
+ if (unmatchedRequiredProperties.Count > 0)
+ RaiseError("Required properties are missing from object: {0}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", unmatchedRequiredProperties.ToArray())), schema);
+ }
+ }
+
+ private void ValidateEndArray(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ int arrayItemCount = _currentScope.ArrayItemCount;
+
+ if (schema.MaximumItems != null && arrayItemCount > schema.MaximumItems)
+ RaiseError("Array item count {0} exceeds maximum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MaximumItems), schema);
+
+ if (schema.MinimumItems != null && arrayItemCount < schema.MinimumItems)
+ RaiseError("Array item count {0} is less than minimum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MinimumItems), schema);
+ }
+
+ private void ValidateNull(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.Null))
+ return;
+
+ ValidateNotDisallowed(schema);
+ }
+
+ private void ValidateBoolean(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.Boolean))
+ return;
+
+ ValidateNotDisallowed(schema);
+ }
+
+ private void ValidateString(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.String))
+ return;
+
+ ValidateNotDisallowed(schema);
+
+ string value = _reader.Value.ToString();
+
+ if (schema.MaximumLength != null && value.Length > schema.MaximumLength)
+ RaiseError("String '{0}' exceeds maximum length of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.MaximumLength), schema);
+
+ if (schema.MinimumLength != null && value.Length < schema.MinimumLength)
+ RaiseError("String '{0}' is less than minimum length of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.MinimumLength), schema);
+
+ if (schema.Patterns != null)
+ {
+ foreach (string pattern in schema.Patterns)
+ {
+ if (!Regex.IsMatch(value, pattern))
+ RaiseError("String '{0}' does not match regex pattern '{1}'.".FormatWith(CultureInfo.InvariantCulture, value, pattern), schema);
+ }
+ }
+ }
+
+ private void ValidateInteger(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.Integer))
+ return;
+
+ ValidateNotDisallowed(schema);
+
+ object value = _reader.Value;
+
+ if (schema.Maximum != null)
+ {
+ if (JValue.Compare(JTokenType.Integer, value, schema.Maximum) > 0)
+ RaiseError("Integer {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema);
+ if (schema.ExclusiveMaximum && JValue.Compare(JTokenType.Integer, value, schema.Maximum) == 0)
+ RaiseError("Integer {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema);
+ }
+
+ if (schema.Minimum != null)
+ {
+ if (JValue.Compare(JTokenType.Integer, value, schema.Minimum) < 0)
+ RaiseError("Integer {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema);
+ if (schema.ExclusiveMinimum && JValue.Compare(JTokenType.Integer, value, schema.Minimum) == 0)
+ RaiseError("Integer {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema);
+ }
+
+ if (schema.DivisibleBy != null)
+ {
+ bool notDivisible;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+ if (value is BigInteger)
+ {
+ // not that this will lose any decimal point on DivisibleBy
+ // so manually raise an error if DivisibleBy is not an integer and value is not zero
+ BigInteger i = (BigInteger)value;
+ bool divisibleNonInteger = !Math.Abs(schema.DivisibleBy.Value - Math.Truncate(schema.DivisibleBy.Value)).Equals(0);
+ if (divisibleNonInteger)
+ notDivisible = i != 0;
+ else
+ notDivisible = i % new BigInteger(schema.DivisibleBy.Value) != 0;
+ }
+ else
+#endif
+ notDivisible = !IsZero(Convert.ToInt64(value, CultureInfo.InvariantCulture) % schema.DivisibleBy.Value);
+
+ if (notDivisible)
+ RaiseError("Integer {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.DivisibleBy), schema);
+ }
+ }
+
+ private void ProcessValue()
+ {
+ if (_currentScope != null && _currentScope.TokenType == JTokenType.Array)
+ {
+ _currentScope.ArrayItemCount++;
+
+ foreach (JsonSchemaModel currentSchema in CurrentSchemas)
+ {
+ // if there is positional validation and the array index is past the number of item validation schemas and there is no additonal items then error
+ if (currentSchema != null
+ && currentSchema.PositionalItemsValidation
+ && !currentSchema.AllowAdditionalItems
+ && (currentSchema.Items == null || _currentScope.ArrayItemCount - 1 >= currentSchema.Items.Count))
+ {
+ RaiseError("Index {0} has not been defined and the schema does not allow additional items.".FormatWith(CultureInfo.InvariantCulture, _currentScope.ArrayItemCount), currentSchema);
+ }
+ }
+ }
+ }
+
+ private void ValidateFloat(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.Float))
+ return;
+
+ ValidateNotDisallowed(schema);
+
+ double value = Convert.ToDouble(_reader.Value, CultureInfo.InvariantCulture);
+
+ if (schema.Maximum != null)
+ {
+ if (value > schema.Maximum)
+ RaiseError("Float {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Maximum), schema);
+ if (schema.ExclusiveMaximum && value == schema.Maximum)
+ RaiseError("Float {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Maximum), schema);
+ }
+
+ if (schema.Minimum != null)
+ {
+ if (value < schema.Minimum)
+ RaiseError("Float {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Minimum), schema);
+ if (schema.ExclusiveMinimum && value == schema.Minimum)
+ RaiseError("Float {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Minimum), schema);
+ }
+
+ if (schema.DivisibleBy != null)
+ {
+ double remainder = FloatingPointRemainder(value, schema.DivisibleBy.Value);
+
+ if (!IsZero(remainder))
+ RaiseError("Float {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.DivisibleBy), schema);
+ }
+ }
+
+ private static double FloatingPointRemainder(double dividend, double divisor)
+ {
+ return dividend - Math.Floor(dividend / divisor) * divisor;
+ }
+
+ private static bool IsZero(double value)
+ {
+ const double epsilon = 2.2204460492503131e-016;
+
+ return Math.Abs(value) < 20.0 * epsilon;
+ }
+
+ private void ValidatePropertyName(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ string propertyName = Convert.ToString(_reader.Value, CultureInfo.InvariantCulture);
+
+ if (_currentScope.RequiredProperties.ContainsKey(propertyName))
+ _currentScope.RequiredProperties[propertyName] = true;
+
+ if (!schema.AllowAdditionalProperties)
+ {
+ bool propertyDefinied = IsPropertyDefinied(schema, propertyName);
+
+ if (!propertyDefinied)
+ RaiseError("Property '{0}' has not been defined and the schema does not allow additional properties.".FormatWith(CultureInfo.InvariantCulture, propertyName), schema);
+ }
+
+ _currentScope.CurrentPropertyName = propertyName;
+ }
+
+ private bool IsPropertyDefinied(JsonSchemaModel schema, string propertyName)
+ {
+ if (schema.Properties != null && schema.Properties.ContainsKey(propertyName))
+ return true;
+
+ if (schema.PatternProperties != null)
+ {
+ foreach (string pattern in schema.PatternProperties.Keys)
+ {
+ if (Regex.IsMatch(propertyName, pattern))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private bool ValidateArray(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return true;
+
+ return (TestType(schema, JsonSchemaType.Array));
+ }
+
+ private bool ValidateObject(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return true;
+
+ return (TestType(schema, JsonSchemaType.Object));
+ }
+
+ private bool TestType(JsonSchemaModel currentSchema, JsonSchemaType currentType)
+ {
+ if (!JsonSchemaGenerator.HasFlag(currentSchema.Type, currentType))
+ {
+ RaiseError("Invalid type. Expected {0} but got {1}.".FormatWith(CultureInfo.InvariantCulture, currentSchema.Type, currentType), currentSchema);
+ return false;
+ }
+
+ return true;
+ }
+
+ bool IJsonLineInfo.HasLineInfo()
+ {
+ IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
+ return lineInfo != null && lineInfo.HasLineInfo();
+ }
+
+ int IJsonLineInfo.LineNumber
+ {
+ get
+ {
+ IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
+ return (lineInfo != null) ? lineInfo.LineNumber : 0;
+ }
+ }
+
+ int IJsonLineInfo.LinePosition
+ {
+ get
+ {
+ IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
+ return (lineInfo != null) ? lineInfo.LinePosition : 0;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonWriter.cs b/Libs/JsonNet/JsonWriter.cs
new file mode 100644
index 0000000..6f2b080
--- /dev/null
+++ b/Libs/JsonNet/JsonWriter.cs
@@ -0,0 +1,1526 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
+ ///
+ public abstract class JsonWriter : IDisposable
+ {
+ internal enum State
+ {
+ Start,
+ Property,
+ ObjectStart,
+ Object,
+ ArrayStart,
+ Array,
+ ConstructorStart,
+ Constructor,
+ Closed,
+ Error
+ }
+
+ // array that gives a new state based on the current state an the token being written
+ private static readonly State[][] StateArray;
+
+ internal static readonly State[][] StateArrayTempate = new[]
+ {
+ // Start PropertyName ObjectStart Object ArrayStart Array ConstructorStart Constructor Closed Error
+ //
+ /* None */new[] { State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
+ /* StartObject */new[] { State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.Error, State.Error },
+ /* StartArray */new[] { State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.Error, State.Error },
+ /* StartConstructor */new[] { State.ConstructorStart, State.ConstructorStart, State.Error, State.Error, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error, State.Error },
+ /* Property */new[] { State.Property, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
+ /* Comment */new[] { State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
+ /* Raw */new[] { State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error },
+ /* Value (this will be copied) */new[] { State.Start, State.Object, State.Error, State.Error, State.Array, State.Array, State.Constructor, State.Constructor, State.Error, State.Error }
+ };
+
+ internal static State[][] BuildStateArray()
+ {
+ var allStates = StateArrayTempate.ToList();
+ var errorStates = StateArrayTempate[0];
+ var valueStates = StateArrayTempate[7];
+
+ foreach (JsonToken valueToken in EnumUtils.GetValues(typeof(JsonToken)))
+ {
+ if (allStates.Count <= (int)valueToken)
+ {
+ switch (valueToken)
+ {
+ case JsonToken.Integer:
+ case JsonToken.Float:
+ case JsonToken.String:
+ case JsonToken.Boolean:
+ case JsonToken.Null:
+ case JsonToken.Undefined:
+ case JsonToken.Date:
+ case JsonToken.Bytes:
+ allStates.Add(valueStates);
+ break;
+ default:
+ allStates.Add(errorStates);
+ break;
+ }
+ }
+ }
+
+ return allStates.ToArray();
+ }
+
+ static JsonWriter()
+ {
+ StateArray = BuildStateArray();
+ }
+
+ private readonly List _stack;
+ private JsonPosition _currentPosition;
+ private State _currentState;
+ private Formatting _formatting;
+
+ ///
+ /// Gets or sets a value indicating whether the underlying stream or
+ /// should be closed when the writer is closed.
+ ///
+ ///
+ /// true to close the underlying stream or when
+ /// the writer is closed; otherwise false. The default is true.
+ ///
+ public bool CloseOutput { get; set; }
+
+ ///
+ /// Gets the top.
+ ///
+ /// The top.
+ protected internal int Top
+ {
+ get
+ {
+ int depth = _stack.Count;
+ if (Peek() != JsonContainerType.None)
+ depth++;
+
+ return depth;
+ }
+ }
+
+ ///
+ /// Gets the state of the writer.
+ ///
+ public WriteState WriteState
+ {
+ get
+ {
+ switch (_currentState)
+ {
+ case State.Error:
+ return WriteState.Error;
+ case State.Closed:
+ return WriteState.Closed;
+ case State.Object:
+ case State.ObjectStart:
+ return WriteState.Object;
+ case State.Array:
+ case State.ArrayStart:
+ return WriteState.Array;
+ case State.Constructor:
+ case State.ConstructorStart:
+ return WriteState.Constructor;
+ case State.Property:
+ return WriteState.Property;
+ case State.Start:
+ return WriteState.Start;
+ default:
+ throw JsonWriterException.Create(this, "Invalid state: " + _currentState, null);
+ }
+ }
+ }
+
+ internal string ContainerPath
+ {
+ get
+ {
+ if (_currentPosition.Type == JsonContainerType.None)
+ return string.Empty;
+
+ return JsonPosition.BuildPath(_stack);
+ }
+ }
+
+ ///
+ /// Gets the path of the writer.
+ ///
+ public string Path
+ {
+ get
+ {
+ if (_currentPosition.Type == JsonContainerType.None)
+ return string.Empty;
+
+ bool insideContainer = (_currentState != State.ArrayStart
+ && _currentState != State.ConstructorStart
+ && _currentState != State.ObjectStart);
+
+ IEnumerable positions = (!insideContainer)
+ ? _stack
+ : _stack.Concat(new[] { _currentPosition });
+
+ return JsonPosition.BuildPath(positions);
+ }
+ }
+
+ private DateFormatHandling _dateFormatHandling;
+ private DateTimeZoneHandling _dateTimeZoneHandling;
+ private StringEscapeHandling _stringEscapeHandling;
+ private FloatFormatHandling _floatFormatHandling;
+ private string _dateFormatString;
+ private CultureInfo _culture;
+
+ ///
+ /// Indicates how JSON text output is formatted.
+ ///
+ public Formatting Formatting
+ {
+ get { return _formatting; }
+ set { _formatting = value; }
+ }
+
+ ///
+ /// Get or set how dates are written to JSON text.
+ ///
+ public DateFormatHandling DateFormatHandling
+ {
+ get { return _dateFormatHandling; }
+ set { _dateFormatHandling = value; }
+ }
+
+ ///
+ /// Get or set how time zones are handling when writing JSON text.
+ ///
+ public DateTimeZoneHandling DateTimeZoneHandling
+ {
+ get { return _dateTimeZoneHandling; }
+ set { _dateTimeZoneHandling = value; }
+ }
+
+ ///
+ /// Get or set how strings are escaped when writing JSON text.
+ ///
+ public StringEscapeHandling StringEscapeHandling
+ {
+ get { return _stringEscapeHandling; }
+ set
+ {
+ _stringEscapeHandling = value;
+ OnStringEscapeHandlingChanged();
+ }
+ }
+
+ internal virtual void OnStringEscapeHandlingChanged()
+ {
+ // hacky but there is a calculated value that relies on StringEscapeHandling
+ }
+
+ ///
+ /// Get or set how special floating point numbers, e.g. ,
+ /// and ,
+ /// are written to JSON text.
+ ///
+ public FloatFormatHandling FloatFormatHandling
+ {
+ get { return _floatFormatHandling; }
+ set { _floatFormatHandling = value; }
+ }
+
+ ///
+ /// Get or set how and values are formatting when writing JSON text.
+ ///
+ public string DateFormatString
+ {
+ get { return _dateFormatString; }
+ set { _dateFormatString = value; }
+ }
+
+ ///
+ /// Gets or sets the culture used when writing JSON. Defaults to .
+ ///
+ public CultureInfo Culture
+ {
+ get { return _culture ?? CultureInfo.InvariantCulture; }
+ set { _culture = value; }
+ }
+
+ ///
+ /// Creates an instance of the JsonWriter class.
+ ///
+ protected JsonWriter()
+ {
+ _stack = new List(4);
+ _currentState = State.Start;
+ _formatting = Formatting.None;
+ _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
+
+ CloseOutput = true;
+ }
+
+ internal void UpdateScopeWithFinishedValue()
+ {
+ if (_currentPosition.HasIndex)
+ _currentPosition.Position++;
+ }
+
+ private void Push(JsonContainerType value)
+ {
+ if (_currentPosition.Type != JsonContainerType.None)
+ _stack.Add(_currentPosition);
+
+ _currentPosition = new JsonPosition(value);
+ }
+
+ private JsonContainerType Pop()
+ {
+ JsonPosition oldPosition = _currentPosition;
+
+ if (_stack.Count > 0)
+ {
+ _currentPosition = _stack[_stack.Count - 1];
+ _stack.RemoveAt(_stack.Count - 1);
+ }
+ else
+ {
+ _currentPosition = new JsonPosition();
+ }
+
+ return oldPosition.Type;
+ }
+
+ private JsonContainerType Peek()
+ {
+ return _currentPosition.Type;
+ }
+
+ ///
+ /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+ ///
+ public abstract void Flush();
+
+ ///
+ /// Closes this stream and the underlying stream.
+ ///
+ public virtual void Close()
+ {
+ AutoCompleteAll();
+ }
+
+ ///
+ /// Writes the beginning of a Json object.
+ ///
+ public virtual void WriteStartObject()
+ {
+ InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object);
+ }
+
+ ///
+ /// Writes the end of a Json object.
+ ///
+ public virtual void WriteEndObject()
+ {
+ InternalWriteEnd(JsonContainerType.Object);
+ }
+
+ ///
+ /// Writes the beginning of a Json array.
+ ///
+ public virtual void WriteStartArray()
+ {
+ InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array);
+ }
+
+ ///
+ /// Writes the end of an array.
+ ///
+ public virtual void WriteEndArray()
+ {
+ InternalWriteEnd(JsonContainerType.Array);
+ }
+
+ ///
+ /// Writes the start of a constructor with the given name.
+ ///
+ /// The name of the constructor.
+ public virtual void WriteStartConstructor(string name)
+ {
+ InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor);
+ }
+
+ ///
+ /// Writes the end constructor.
+ ///
+ public virtual void WriteEndConstructor()
+ {
+ InternalWriteEnd(JsonContainerType.Constructor);
+ }
+
+ ///
+ /// Writes the property name of a name/value pair on a JSON object.
+ ///
+ /// The name of the property.
+ public virtual void WritePropertyName(string name)
+ {
+ InternalWritePropertyName(name);
+ }
+
+ ///
+ /// Writes the property name of a name/value pair on a JSON object.
+ ///
+ /// The name of the property.
+ /// A flag to indicate whether the text should be escaped when it is written as a JSON property name.
+ public virtual void WritePropertyName(string name, bool escape)
+ {
+ WritePropertyName(name);
+ }
+
+ ///
+ /// Writes the end of the current Json object or array.
+ ///
+ public virtual void WriteEnd()
+ {
+ WriteEnd(Peek());
+ }
+
+ ///
+ /// Writes the current token and its children.
+ ///
+ /// The to read the token from.
+ public void WriteToken(JsonReader reader)
+ {
+ WriteToken(reader, true, true);
+ }
+
+ ///
+ /// Writes the current token.
+ ///
+ /// The to read the token from.
+ /// A flag indicating whether the current token's children should be written.
+ public void WriteToken(JsonReader reader, bool writeChildren)
+ {
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+
+ WriteToken(reader, writeChildren, true);
+ }
+
+ internal void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate)
+ {
+ int initialDepth;
+
+ if (reader.TokenType == JsonToken.None)
+ initialDepth = -1;
+ else if (!IsStartToken(reader.TokenType))
+ initialDepth = reader.Depth + 1;
+ else
+ initialDepth = reader.Depth;
+
+ WriteToken(reader, initialDepth, writeChildren, writeDateConstructorAsDate);
+ }
+
+ internal void WriteToken(JsonReader reader, int initialDepth, bool writeChildren, bool writeDateConstructorAsDate)
+ {
+ do
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.None:
+ // read to next
+ break;
+ case JsonToken.StartObject:
+ WriteStartObject();
+ break;
+ case JsonToken.StartArray:
+ WriteStartArray();
+ break;
+ case JsonToken.StartConstructor:
+ string constructorName = reader.Value.ToString();
+ // write a JValue date when the constructor is for a date
+ if (writeDateConstructorAsDate && string.Equals(constructorName, "Date", StringComparison.Ordinal))
+ WriteConstructorDate(reader);
+ else
+ WriteStartConstructor(reader.Value.ToString());
+ break;
+ case JsonToken.PropertyName:
+ WritePropertyName(reader.Value.ToString());
+ break;
+ case JsonToken.Comment:
+ WriteComment((reader.Value != null) ? reader.Value.ToString() : null);
+ break;
+ case JsonToken.Integer:
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+ if (reader.Value is BigInteger)
+ {
+ WriteValue((BigInteger)reader.Value);
+ }
+ else
+#endif
+ {
+ WriteValue(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture));
+ }
+ break;
+ case JsonToken.Float:
+ object value = reader.Value;
+
+ if (value is decimal)
+ WriteValue((decimal)value);
+ else if (value is double)
+ WriteValue((double)value);
+ else if (value is float)
+ WriteValue((float)value);
+ else
+ WriteValue(Convert.ToDouble(value, CultureInfo.InvariantCulture));
+ break;
+ case JsonToken.String:
+ WriteValue(reader.Value.ToString());
+ break;
+ case JsonToken.Boolean:
+ WriteValue(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
+ break;
+ case JsonToken.Null:
+ WriteNull();
+ break;
+ case JsonToken.Undefined:
+ WriteUndefined();
+ break;
+ case JsonToken.EndObject:
+ WriteEndObject();
+ break;
+ case JsonToken.EndArray:
+ WriteEndArray();
+ break;
+ case JsonToken.EndConstructor:
+ WriteEndConstructor();
+ break;
+ case JsonToken.Date:
+#if !NET20
+ if (reader.Value is DateTimeOffset)
+ WriteValue((DateTimeOffset)reader.Value);
+ else
+#endif
+ WriteValue(Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture));
+ break;
+ case JsonToken.Raw:
+ WriteRawValue((reader.Value != null) ? reader.Value.ToString() : null);
+ break;
+ case JsonToken.Bytes:
+ if (reader.Value is Guid)
+ WriteValue((Guid)reader.Value);
+ else
+ WriteValue((byte[])reader.Value);
+ break;
+ default:
+ throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", reader.TokenType, "Unexpected token type.");
+ }
+ } while (
+ // stop if we have reached the end of the token being read
+ initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0)
+ && writeChildren
+ && reader.Read());
+ }
+
+ private void WriteConstructorDate(JsonReader reader)
+ {
+ if (!reader.Read())
+ throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null);
+ if (reader.TokenType != JsonToken.Integer)
+ throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null);
+
+ long ticks = (long)reader.Value;
+ DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
+
+ if (!reader.Read())
+ throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null);
+ if (reader.TokenType != JsonToken.EndConstructor)
+ throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected EndConstructor, got " + reader.TokenType, null);
+
+ WriteValue(date);
+ }
+
+ internal static bool IsEndToken(JsonToken token)
+ {
+ switch (token)
+ {
+ case JsonToken.EndObject:
+ case JsonToken.EndArray:
+ case JsonToken.EndConstructor:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ internal static bool IsStartToken(JsonToken token)
+ {
+ switch (token)
+ {
+ case JsonToken.StartObject:
+ case JsonToken.StartArray:
+ case JsonToken.StartConstructor:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void WriteEnd(JsonContainerType type)
+ {
+ switch (type)
+ {
+ case JsonContainerType.Object:
+ WriteEndObject();
+ break;
+ case JsonContainerType.Array:
+ WriteEndArray();
+ break;
+ case JsonContainerType.Constructor:
+ WriteEndConstructor();
+ break;
+ default:
+ throw JsonWriterException.Create(this, "Unexpected type when writing end: " + type, null);
+ }
+ }
+
+ private void AutoCompleteAll()
+ {
+ while (Top > 0)
+ {
+ WriteEnd();
+ }
+ }
+
+ private JsonToken GetCloseTokenForType(JsonContainerType type)
+ {
+ switch (type)
+ {
+ case JsonContainerType.Object:
+ return JsonToken.EndObject;
+ case JsonContainerType.Array:
+ return JsonToken.EndArray;
+ case JsonContainerType.Constructor:
+ return JsonToken.EndConstructor;
+ default:
+ throw JsonWriterException.Create(this, "No close token for type: " + type, null);
+ }
+ }
+
+ private void AutoCompleteClose(JsonContainerType type)
+ {
+ // write closing symbol and calculate new state
+ int levelsToComplete = 0;
+
+ if (_currentPosition.Type == type)
+ {
+ levelsToComplete = 1;
+ }
+ else
+ {
+ int top = Top - 2;
+ for (int i = top; i >= 0; i--)
+ {
+ int currentLevel = top - i;
+
+ if (_stack[currentLevel].Type == type)
+ {
+ levelsToComplete = i + 2;
+ break;
+ }
+ }
+ }
+
+ if (levelsToComplete == 0)
+ throw JsonWriterException.Create(this, "No token to close.", null);
+
+ for (int i = 0; i < levelsToComplete; i++)
+ {
+ JsonToken token = GetCloseTokenForType(Pop());
+
+ if (_currentState == State.Property)
+ WriteNull();
+
+ if (_formatting == Formatting.Indented)
+ {
+ if (_currentState != State.ObjectStart && _currentState != State.ArrayStart)
+ WriteIndent();
+ }
+
+ WriteEnd(token);
+
+ JsonContainerType currentLevelType = Peek();
+
+ switch (currentLevelType)
+ {
+ case JsonContainerType.Object:
+ _currentState = State.Object;
+ break;
+ case JsonContainerType.Array:
+ _currentState = State.Array;
+ break;
+ case JsonContainerType.Constructor:
+ _currentState = State.Array;
+ break;
+ case JsonContainerType.None:
+ _currentState = State.Start;
+ break;
+ default:
+ throw JsonWriterException.Create(this, "Unknown JsonType: " + currentLevelType, null);
+ }
+ }
+ }
+
+ ///
+ /// Writes the specified end token.
+ ///
+ /// The end token to write.
+ protected virtual void WriteEnd(JsonToken token)
+ {
+ }
+
+ ///
+ /// Writes indent characters.
+ ///
+ protected virtual void WriteIndent()
+ {
+ }
+
+ ///
+ /// Writes the JSON value delimiter.
+ ///
+ protected virtual void WriteValueDelimiter()
+ {
+ }
+
+ ///
+ /// Writes an indent space.
+ ///
+ protected virtual void WriteIndentSpace()
+ {
+ }
+
+ internal void AutoComplete(JsonToken tokenBeingWritten)
+ {
+ // gets new state based on the current state and what is being written
+ State newState = StateArray[(int)tokenBeingWritten][(int)_currentState];
+
+ if (newState == State.Error)
+ throw JsonWriterException.Create(this, "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()), null);
+
+ if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment)
+ {
+ WriteValueDelimiter();
+ }
+
+ if (_formatting == Formatting.Indented)
+ {
+ if (_currentState == State.Property)
+ WriteIndentSpace();
+
+ // don't indent a property when it is the first token to be written (i.e. at the start)
+ if ((_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.Constructor || _currentState == State.ConstructorStart)
+ || (tokenBeingWritten == JsonToken.PropertyName && _currentState != State.Start))
+ WriteIndent();
+ }
+
+ _currentState = newState;
+ }
+
+ #region WriteValue methods
+ ///
+ /// Writes a null value.
+ ///
+ public virtual void WriteNull()
+ {
+ InternalWriteValue(JsonToken.Null);
+ }
+
+ ///
+ /// Writes an undefined value.
+ ///
+ public virtual void WriteUndefined()
+ {
+ InternalWriteValue(JsonToken.Undefined);
+ }
+
+ ///
+ /// Writes raw JSON without changing the writer's state.
+ ///
+ /// The raw JSON to write.
+ public virtual void WriteRaw(string json)
+ {
+ InternalWriteRaw();
+ }
+
+ ///
+ /// Writes raw JSON where a value is expected and updates the writer's state.
+ ///
+ /// The raw JSON to write.
+ public virtual void WriteRawValue(string json)
+ {
+ // hack. want writer to change state as if a value had been written
+ UpdateScopeWithFinishedValue();
+ AutoComplete(JsonToken.Undefined);
+ WriteRaw(json);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(string value)
+ {
+ InternalWriteValue(JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(int value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public virtual void WriteValue(uint value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(long value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public virtual void WriteValue(ulong value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(float value)
+ {
+ InternalWriteValue(JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(double value)
+ {
+ InternalWriteValue(JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(bool value)
+ {
+ InternalWriteValue(JsonToken.Boolean);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(short value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public virtual void WriteValue(ushort value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(char value)
+ {
+ InternalWriteValue(JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(byte value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public virtual void WriteValue(sbyte value)
+ {
+ InternalWriteValue(JsonToken.Integer);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(decimal value)
+ {
+ InternalWriteValue(JsonToken.Float);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(DateTime value)
+ {
+ InternalWriteValue(JsonToken.Date);
+ }
+
+#if !NET20
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(DateTimeOffset value)
+ {
+ InternalWriteValue(JsonToken.Date);
+ }
+#endif
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(Guid value)
+ {
+ InternalWriteValue(JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(TimeSpan value)
+ {
+ InternalWriteValue(JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(int? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public virtual void WriteValue(uint? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(long? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public virtual void WriteValue(ulong? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(float? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(double? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(bool? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(short? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public virtual void WriteValue(ushort? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(char? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(byte? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ [CLSCompliant(false)]
+ public virtual void WriteValue(sbyte? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(decimal? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(DateTime? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+#if !NET20
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(DateTimeOffset? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+#endif
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(Guid? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(TimeSpan? value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ WriteValue(value.Value);
+ }
+
+ ///
+ /// Writes a [] value.
+ ///
+ /// The [] value to write.
+ public virtual void WriteValue(byte[] value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ InternalWriteValue(JsonToken.Bytes);
+ }
+
+ ///
+ /// Writes a value.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(Uri value)
+ {
+ if (value == null)
+ WriteNull();
+ else
+ InternalWriteValue(JsonToken.String);
+ }
+
+ ///
+ /// Writes a value.
+ /// An error will raised if the value cannot be written as a single JSON token.
+ ///
+ /// The value to write.
+ public virtual void WriteValue(object value)
+ {
+ if (value == null)
+ {
+ WriteNull();
+ }
+ else
+ {
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+ // this is here because adding a WriteValue(BigInteger) to JsonWriter will
+ // mean the user has to add a reference to System.Numerics.dll
+ if (value is BigInteger)
+ throw CreateUnsupportedTypeException(this, value);
+#endif
+
+ WriteValue(this, ConvertUtils.GetTypeCode(value.GetType()), value);
+ }
+ }
+ #endregion
+
+ ///
+ /// Writes out a comment /*...*/
containing the specified text.
+ ///
+ /// Text to place inside the comment.
+ public virtual void WriteComment(string text)
+ {
+ InternalWriteComment();
+ }
+
+ ///
+ /// Writes out the given white space.
+ ///
+ /// The string of white space characters.
+ public virtual void WriteWhitespace(string ws)
+ {
+ InternalWriteWhitespace(ws);
+ }
+
+ void IDisposable.Dispose()
+ {
+ Dispose(true);
+ }
+
+ private void Dispose(bool disposing)
+ {
+ if (_currentState != State.Closed)
+ Close();
+ }
+
+ internal static void WriteValue(JsonWriter writer, PrimitiveTypeCode typeCode, object value)
+ {
+ switch (typeCode)
+ {
+ case PrimitiveTypeCode.Char:
+ writer.WriteValue((char)value);
+ break;
+ case PrimitiveTypeCode.CharNullable:
+ writer.WriteValue((value == null) ? (char?)null : (char)value);
+ break;
+ case PrimitiveTypeCode.Boolean:
+ writer.WriteValue((bool)value);
+ break;
+ case PrimitiveTypeCode.BooleanNullable:
+ writer.WriteValue((value == null) ? (bool?)null : (bool)value);
+ break;
+ case PrimitiveTypeCode.SByte:
+ writer.WriteValue((sbyte)value);
+ break;
+ case PrimitiveTypeCode.SByteNullable:
+ writer.WriteValue((value == null) ? (sbyte?)null : (sbyte)value);
+ break;
+ case PrimitiveTypeCode.Int16:
+ writer.WriteValue((short)value);
+ break;
+ case PrimitiveTypeCode.Int16Nullable:
+ writer.WriteValue((value == null) ? (short?)null : (short)value);
+ break;
+ case PrimitiveTypeCode.UInt16:
+ writer.WriteValue((ushort)value);
+ break;
+ case PrimitiveTypeCode.UInt16Nullable:
+ writer.WriteValue((value == null) ? (ushort?)null : (ushort)value);
+ break;
+ case PrimitiveTypeCode.Int32:
+ writer.WriteValue((int)value);
+ break;
+ case PrimitiveTypeCode.Int32Nullable:
+ writer.WriteValue((value == null) ? (int?)null : (int)value);
+ break;
+ case PrimitiveTypeCode.Byte:
+ writer.WriteValue((byte)value);
+ break;
+ case PrimitiveTypeCode.ByteNullable:
+ writer.WriteValue((value == null) ? (byte?)null : (byte)value);
+ break;
+ case PrimitiveTypeCode.UInt32:
+ writer.WriteValue((uint)value);
+ break;
+ case PrimitiveTypeCode.UInt32Nullable:
+ writer.WriteValue((value == null) ? (uint?)null : (uint)value);
+ break;
+ case PrimitiveTypeCode.Int64:
+ writer.WriteValue((long)value);
+ break;
+ case PrimitiveTypeCode.Int64Nullable:
+ writer.WriteValue((value == null) ? (long?)null : (long)value);
+ break;
+ case PrimitiveTypeCode.UInt64:
+ writer.WriteValue((ulong)value);
+ break;
+ case PrimitiveTypeCode.UInt64Nullable:
+ writer.WriteValue((value == null) ? (ulong?)null : (ulong)value);
+ break;
+ case PrimitiveTypeCode.Single:
+ writer.WriteValue((float)value);
+ break;
+ case PrimitiveTypeCode.SingleNullable:
+ writer.WriteValue((value == null) ? (float?)null : (float)value);
+ break;
+ case PrimitiveTypeCode.Double:
+ writer.WriteValue((double)value);
+ break;
+ case PrimitiveTypeCode.DoubleNullable:
+ writer.WriteValue((value == null) ? (double?)null : (double)value);
+ break;
+ case PrimitiveTypeCode.DateTime:
+ writer.WriteValue((DateTime)value);
+ break;
+ case PrimitiveTypeCode.DateTimeNullable:
+ writer.WriteValue((value == null) ? (DateTime?)null : (DateTime)value);
+ break;
+#if !NET20
+ case PrimitiveTypeCode.DateTimeOffset:
+ writer.WriteValue((DateTimeOffset)value);
+ break;
+ case PrimitiveTypeCode.DateTimeOffsetNullable:
+ writer.WriteValue((value == null) ? (DateTimeOffset?)null : (DateTimeOffset)value);
+ break;
+#endif
+ case PrimitiveTypeCode.Decimal:
+ writer.WriteValue((decimal)value);
+ break;
+ case PrimitiveTypeCode.DecimalNullable:
+ writer.WriteValue((value == null) ? (decimal?)null : (decimal)value);
+ break;
+ case PrimitiveTypeCode.Guid:
+ writer.WriteValue((Guid)value);
+ break;
+ case PrimitiveTypeCode.GuidNullable:
+ writer.WriteValue((value == null) ? (Guid?)null : (Guid)value);
+ break;
+ case PrimitiveTypeCode.TimeSpan:
+ writer.WriteValue((TimeSpan)value);
+ break;
+ case PrimitiveTypeCode.TimeSpanNullable:
+ writer.WriteValue((value == null) ? (TimeSpan?)null : (TimeSpan)value);
+ break;
+#if !(PORTABLE || PORTABLE40 || NET35 || NET20)
+ case PrimitiveTypeCode.BigInteger:
+ // this will call to WriteValue(object)
+ writer.WriteValue((BigInteger)value);
+ break;
+ case PrimitiveTypeCode.BigIntegerNullable:
+ // this will call to WriteValue(object)
+ writer.WriteValue((value == null) ? (BigInteger?)null : (BigInteger)value);
+ break;
+#endif
+ case PrimitiveTypeCode.Uri:
+ writer.WriteValue((Uri)value);
+ break;
+ case PrimitiveTypeCode.String:
+ writer.WriteValue((string)value);
+ break;
+ case PrimitiveTypeCode.Bytes:
+ writer.WriteValue((byte[])value);
+ break;
+#if !(PORTABLE || NETFX_CORE)
+ case PrimitiveTypeCode.DBNull:
+ writer.WriteNull();
+ break;
+#endif
+ default:
+#if !(PORTABLE || NETFX_CORE)
+ if (value is IConvertible)
+ {
+ // the value is a non-standard IConvertible
+ // convert to the underlying value and retry
+ IConvertible convertable = (IConvertible)value;
+
+ TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertable);
+
+ // if convertable has an underlying typecode of Object then attempt to convert it to a string
+ PrimitiveTypeCode resolvedTypeCode = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? PrimitiveTypeCode.String : typeInformation.TypeCode;
+ Type resolvedType = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? typeof(string) : typeInformation.Type;
+
+ object convertedValue = convertable.ToType(resolvedType, CultureInfo.InvariantCulture);
+
+ WriteValue(writer, resolvedTypeCode, convertedValue);
+ break;
+ }
+ else
+#endif
+ {
+ throw CreateUnsupportedTypeException(writer, value);
+ }
+ }
+ }
+
+ private static JsonWriterException CreateUnsupportedTypeException(JsonWriter writer, object value)
+ {
+ return JsonWriterException.Create(writer, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null);
+ }
+
+ ///
+ /// Sets the state of the JsonWriter,
+ ///
+ /// The JsonToken being written.
+ /// The value being written.
+ protected void SetWriteState(JsonToken token, object value)
+ {
+ switch (token)
+ {
+ case JsonToken.StartObject:
+ InternalWriteStart(token, JsonContainerType.Object);
+ break;
+ case JsonToken.StartArray:
+ InternalWriteStart(token, JsonContainerType.Array);
+ break;
+ case JsonToken.StartConstructor:
+ InternalWriteStart(token, JsonContainerType.Constructor);
+ break;
+ case JsonToken.PropertyName:
+ if (!(value is string))
+ throw new ArgumentException("A name is required when setting property name state.", "value");
+
+ InternalWritePropertyName((string)value);
+ break;
+ case JsonToken.Comment:
+ InternalWriteComment();
+ break;
+ case JsonToken.Raw:
+ InternalWriteRaw();
+ break;
+ case JsonToken.Integer:
+ case JsonToken.Float:
+ case JsonToken.String:
+ case JsonToken.Boolean:
+ case JsonToken.Date:
+ case JsonToken.Bytes:
+ case JsonToken.Null:
+ case JsonToken.Undefined:
+ InternalWriteValue(token);
+ break;
+ case JsonToken.EndObject:
+ InternalWriteEnd(JsonContainerType.Object);
+ break;
+ case JsonToken.EndArray:
+ InternalWriteEnd(JsonContainerType.Array);
+ break;
+ case JsonToken.EndConstructor:
+ InternalWriteEnd(JsonContainerType.Constructor);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("token");
+ }
+ }
+
+ internal void InternalWriteEnd(JsonContainerType container)
+ {
+ AutoCompleteClose(container);
+ }
+
+ internal void InternalWritePropertyName(string name)
+ {
+ _currentPosition.PropertyName = name;
+ AutoComplete(JsonToken.PropertyName);
+ }
+
+ internal void InternalWriteRaw()
+ {
+ }
+
+ internal void InternalWriteStart(JsonToken token, JsonContainerType container)
+ {
+ UpdateScopeWithFinishedValue();
+ AutoComplete(token);
+ Push(container);
+ }
+
+ internal void InternalWriteValue(JsonToken token)
+ {
+ UpdateScopeWithFinishedValue();
+ AutoComplete(token);
+ }
+
+ internal void InternalWriteWhitespace(string ws)
+ {
+ if (ws != null)
+ {
+ if (!StringUtils.IsWhiteSpace(ws))
+ throw JsonWriterException.Create(this, "Only white space characters should be used.", null);
+ }
+ }
+
+ internal void InternalWriteComment()
+ {
+ AutoComplete(JsonToken.Comment);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/JsonWriterException.cs b/Libs/JsonNet/JsonWriterException.cs
new file mode 100644
index 0000000..a955e22
--- /dev/null
+++ b/Libs/JsonNet/JsonWriterException.cs
@@ -0,0 +1,107 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// The exception thrown when an error occurs while reading Json text.
+ ///
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ [Serializable]
+#endif
+ public class JsonWriterException : JsonException
+ {
+ ///
+ /// Gets the path to the JSON where the error occurred.
+ ///
+ /// The path to the JSON where the error occurred.
+ public string Path { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonWriterException()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a specified error message.
+ ///
+ /// The error message that explains the reason for the exception.
+ public JsonWriterException(string message)
+ : base(message)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+ ///
+ /// The error message that explains the reason for the exception.
+ /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.
+ public JsonWriterException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ /// The parameter is null.
+ /// The class name is null or is zero (0).
+ public JsonWriterException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+#endif
+
+ internal JsonWriterException(string message, Exception innerException, string path)
+ : base(message, innerException)
+ {
+ Path = path;
+ }
+
+ internal static JsonWriterException Create(JsonWriter writer, string message, Exception ex)
+ {
+ return Create(writer.ContainerPath, message, ex);
+ }
+
+ internal static JsonWriterException Create(string path, string message, Exception ex)
+ {
+ message = JsonPosition.FormatMessage(null, path, message);
+
+ return new JsonWriterException(message, ex, path);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Linq/Extensions.cs b/Libs/JsonNet/Linq/Extensions.cs
new file mode 100644
index 0000000..f74665b
--- /dev/null
+++ b/Libs/JsonNet/Linq/Extensions.cs
@@ -0,0 +1,312 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Linq
+{
+ ///
+ /// Contains the LINQ to JSON extension methods.
+ ///
+ public static class Extensions
+ {
+ ///
+ /// Returns a collection of tokens that contains the ancestors of every token in the source collection.
+ ///
+ /// The type of the objects in source, constrained to .
+ /// An of that contains the source collection.
+ /// An of that contains the ancestors of every node in the source collection.
+ public static IJEnumerable Ancestors(this IEnumerable source) where T : JToken
+ {
+ ValidationUtils.ArgumentNotNull(source, "source");
+
+ return source.SelectMany(j => j.Ancestors()).AsJEnumerable();
+ }
+
+ //TODO
+ //public static IEnumerable AncestorsAndSelf(this IEnumerable source) where T : JObject
+ //{
+ // ValidationUtils.ArgumentNotNull(source, "source");
+
+ // return source.SelectMany(j => j.AncestorsAndSelf());
+ //}
+
+ ///
+ /// Returns a collection of tokens that contains the descendants of every token in the source collection.
+ ///
+ /// The type of the objects in source, constrained to .
+ /// An of that contains the source collection.
+ /// An of that contains the descendants of every node in the source collection.
+ public static IJEnumerable Descendants(this IEnumerable source) where T : JContainer
+ {
+ ValidationUtils.ArgumentNotNull(source, "source");
+
+ return source.SelectMany(j => j.Descendants()).AsJEnumerable();
+ }
+
+ //TODO
+ //public static IEnumerable DescendantsAndSelf(this IEnumerable source) where T : JContainer
+ //{
+ // ValidationUtils.ArgumentNotNull(source, "source");
+
+ // return source.SelectMany(j => j.DescendantsAndSelf());
+ //}
+
+ ///
+ /// Returns a collection of child properties of every object in the source collection.
+ ///
+ /// An of that contains the source collection.
+ /// An of that contains the properties of every object in the source collection.
+ public static IJEnumerable Properties(this IEnumerable source)
+ {
+ ValidationUtils.ArgumentNotNull(source, "source");
+
+ return source.SelectMany(d => d.Properties()).AsJEnumerable();
+ }
+
+ ///
+ /// Returns a collection of child values of every object in the source collection with the given key.
+ ///
+ /// An of that contains the source collection.
+ /// The token key.
+ /// An of that contains the values of every node in the source collection with the given key.
+ public static IJEnumerable Values(this IEnumerable source, object key)
+ {
+ return Values(source, key).AsJEnumerable();
+ }
+
+ ///
+ /// Returns a collection of child values of every object in the source collection.
+ ///
+ /// An of that contains the source collection.
+ /// An of that contains the values of every node in the source collection.
+ public static IJEnumerable Values(this IEnumerable source)
+ {
+ return source.Values(null);
+ }
+
+ ///
+ /// Returns a collection of converted child values of every object in the source collection with the given key.
+ ///
+ /// The type to convert the values to.
+ /// An of that contains the source collection.
+ /// The token key.
+ /// An that contains the converted values of every node in the source collection with the given key.
+ public static IEnumerable Values(this IEnumerable source, object key)
+ {
+ return Values(source, key);
+ }
+
+ ///
+ /// Returns a collection of converted child values of every object in the source collection.
+ ///
+ /// The type to convert the values to.
+ /// An of that contains the source collection.
+ /// An that contains the converted values of every node in the source collection.
+ public static IEnumerable Values(this IEnumerable source)
+ {
+ return Values(source, null);
+ }
+
+ ///
+ /// Converts the value.
+ ///
+ /// The type to convert the value to.
+ /// A cast as a of .
+ /// A converted value.
+ public static U Value(this IEnumerable value)
+ {
+ return value.Value();
+ }
+
+ ///
+ /// Converts the value.
+ ///
+ /// The source collection type.
+ /// The type to convert the value to.
+ /// A cast as a of .
+ /// A converted value.
+ public static U Value(this IEnumerable value) where T : JToken
+ {
+ ValidationUtils.ArgumentNotNull(value, "source");
+
+ JToken token = value as JToken;
+ if (token == null)
+ throw new ArgumentException("Source value must be a JToken.");
+
+ return token.Convert();
+ }
+
+
+ internal static IEnumerable Values(this IEnumerable source, object key) where T : JToken
+ {
+ ValidationUtils.ArgumentNotNull(source, "source");
+
+ foreach (JToken token in source)
+ {
+ if (key == null)
+ {
+ if (token is JValue)
+ {
+ yield return Convert((JValue)token);
+ }
+ else
+ {
+ foreach (JToken t in token.Children())
+ {
+ yield return t.Convert();
+ }
+ }
+ }
+ else
+ {
+ JToken value = token[key];
+ if (value != null)
+ yield return value.Convert();
+ }
+ }
+
+ yield break;
+ }
+
+ //TODO
+ //public static IEnumerable InDocumentOrder(this IEnumerable source) where T : JObject;
+
+ //public static IEnumerable Children(this IEnumerable source) where T : JToken
+ //{
+ // ValidationUtils.ArgumentNotNull(source, "source");
+
+ // return source.SelectMany(c => c.Children());
+ //}
+
+ ///
+ /// Returns a collection of child tokens of every array in the source collection.
+ ///
+ /// The source collection type.
+ /// An of that contains the source collection.
+ /// An of that contains the values of every node in the source collection.
+ public static IJEnumerable Children(this IEnumerable source) where T : JToken
+ {
+ return Children(source).AsJEnumerable();
+ }
+
+ ///
+ /// Returns a collection of converted child tokens of every array in the source collection.
+ ///
+ /// An of that contains the source collection.
+ /// The type to convert the values to.
+ /// The source collection type.
+ /// An that contains the converted values of every node in the source collection.
+ public static IEnumerable Children(this IEnumerable source) where T : JToken
+ {
+ ValidationUtils.ArgumentNotNull(source, "source");
+
+ return source.SelectMany(c => c.Children()).Convert();
+ }
+
+ internal static IEnumerable Convert(this IEnumerable source) where T : JToken
+ {
+ ValidationUtils.ArgumentNotNull(source, "source");
+
+ foreach (T token in source)
+ {
+ yield return Convert(token);
+ }
+ }
+
+ internal static U Convert(this T token) where T : JToken
+ {
+ if (token == null)
+ return default(U);
+
+ if (token is U
+ // don't want to cast JValue to its interfaces, want to get the internal value
+ && typeof(U) != typeof(IComparable) && typeof(U) != typeof(IFormattable))
+ {
+ // HACK
+ return (U)(object)token;
+ }
+ else
+ {
+ JValue value = token as JValue;
+ if (value == null)
+ throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T)));
+
+ if (value.Value is U)
+ return (U)value.Value;
+
+ Type targetType = typeof(U);
+
+ if (ReflectionUtils.IsNullableType(targetType))
+ {
+ if (value.Value == null)
+ return default(U);
+
+ targetType = Nullable.GetUnderlyingType(targetType);
+ }
+
+ return (U)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture);
+ }
+ }
+
+ //TODO
+ //public static void Remove(this IEnumerable source) where T : JContainer;
+
+ ///
+ /// Returns the input typed as .
+ ///
+ /// An of that contains the source collection.
+ /// The input typed as .
+ public static IJEnumerable AsJEnumerable(this IEnumerable source)
+ {
+ return source.AsJEnumerable();
+ }
+
+ ///
+ /// Returns the input typed as .
+ ///
+ /// The source collection type.
+ /// An of that contains the source collection.
+ /// The input typed as .
+ public static IJEnumerable AsJEnumerable(this IEnumerable source) where T : JToken
+ {
+ if (source == null)
+ return null;
+ else if (source is IJEnumerable)
+ return (IJEnumerable)source;
+ else
+ return new JEnumerable(source);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Linq/IJEnumerable.cs b/Libs/JsonNet/Linq/IJEnumerable.cs
new file mode 100644
index 0000000..fff8c2e
--- /dev/null
+++ b/Libs/JsonNet/Linq/IJEnumerable.cs
@@ -0,0 +1,46 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Linq
+{
+ ///
+ /// Represents a collection of objects.
+ ///
+ /// The type of token
+ public interface IJEnumerable<
+#if !(NET20 || NET35)
+ out
+#endif
+ T> : IEnumerable where T : JToken
+ {
+ ///
+ /// Gets the with the specified key.
+ ///
+ ///
+ IJEnumerable this[object key] { get; }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Linq/JArray.cs b/Libs/JsonNet/Linq/JArray.cs
new file mode 100644
index 0000000..b347eab
--- /dev/null
+++ b/Libs/JsonNet/Linq/JArray.cs
@@ -0,0 +1,368 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+using System.IO;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Linq
+{
+ ///
+ /// Represents a JSON array.
+ ///
+ ///
+ ///
+ ///
+ public class JArray : JContainer, IList
+ {
+ private readonly List _values = new List();
+
+ ///
+ /// Gets the container's children tokens.
+ ///
+ /// The container's children tokens.
+ protected override IList ChildrenTokens
+ {
+ get { return _values; }
+ }
+
+ ///
+ /// Gets the node type for this .
+ ///
+ /// The type.
+ public override JTokenType Type
+ {
+ get { return JTokenType.Array; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JArray()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class from another object.
+ ///
+ /// A object to copy from.
+ public JArray(JArray other)
+ : base(other)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified content.
+ ///
+ /// The contents of the array.
+ public JArray(params object[] content)
+ : this((object)content)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified content.
+ ///
+ /// The contents of the array.
+ public JArray(object content)
+ {
+ Add(content);
+ }
+
+ internal override bool DeepEquals(JToken node)
+ {
+ JArray t = node as JArray;
+ return (t != null && ContentsEqual(t));
+ }
+
+ internal override JToken CloneToken()
+ {
+ return new JArray(this);
+ }
+
+ ///
+ /// Loads an from a .
+ ///
+ /// A that will be read for the content of the .
+ /// A that contains the JSON that was read from the specified .
+ public new static JArray Load(JsonReader reader)
+ {
+ if (reader.TokenType == JsonToken.None)
+ {
+ if (!reader.Read())
+ throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader.");
+ }
+
+ while (reader.TokenType == JsonToken.Comment)
+ {
+ reader.Read();
+ }
+
+ if (reader.TokenType != JsonToken.StartArray)
+ throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+ JArray a = new JArray();
+ a.SetLineInfo(reader as IJsonLineInfo);
+
+ a.ReadTokenFrom(reader);
+
+ return a;
+ }
+
+ ///
+ /// Load a from a string that contains JSON.
+ ///
+ /// A that contains JSON.
+ /// A populated from the string that contains JSON.
+ ///
+ ///
+ ///
+ public new static JArray Parse(string json)
+ {
+ using (JsonReader reader = new JsonTextReader(new StringReader(json)))
+ {
+ JArray a = Load(reader);
+
+ if (reader.Read() && reader.TokenType != JsonToken.Comment)
+ throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content.");
+
+ return a;
+ }
+ }
+
+ ///
+ /// Creates a from an object.
+ ///
+ /// The object that will be used to create .
+ /// A with the values of the specified object
+ public new static JArray FromObject(object o)
+ {
+ return FromObject(o, JsonSerializer.CreateDefault());
+ }
+
+ ///
+ /// Creates a from an object.
+ ///
+ /// The object that will be used to create .
+ /// The that will be used to read the object.
+ /// A with the values of the specified object
+ public new static JArray FromObject(object o, JsonSerializer jsonSerializer)
+ {
+ JToken token = FromObjectInternal(o, jsonSerializer);
+
+ if (token.Type != JTokenType.Array)
+ throw new ArgumentException("Object serialized to {0}. JArray instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+
+ return (JArray)token;
+ }
+
+ ///
+ /// Writes this token to a .
+ ///
+ /// A into which this method will write.
+ /// A collection of which will be used when writing the token.
+ public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
+ {
+ writer.WriteStartArray();
+
+ for (int i = 0; i < _values.Count; i++)
+ {
+ _values[i].WriteTo(writer, converters);
+ }
+
+ writer.WriteEndArray();
+ }
+
+ ///
+ /// Gets the with the specified key.
+ ///
+ /// The with the specified key.
+ public override JToken this[object key]
+ {
+ get
+ {
+ ValidationUtils.ArgumentNotNull(key, "o");
+
+ if (!(key is int))
+ throw new ArgumentException("Accessed JArray values with invalid key value: {0}. Array position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+ return GetItem((int)key);
+ }
+ set
+ {
+ ValidationUtils.ArgumentNotNull(key, "o");
+
+ if (!(key is int))
+ throw new ArgumentException("Set JArray values with invalid key value: {0}. Array position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+ SetItem((int)key, value);
+ }
+ }
+
+ ///
+ /// Gets or sets the at the specified index.
+ ///
+ ///
+ public JToken this[int index]
+ {
+ get { return GetItem(index); }
+ set { SetItem(index, value); }
+ }
+
+ internal override void MergeItem(object content, JsonMergeSettings settings)
+ {
+ IEnumerable a = (IsMultiContent(content) || content is JArray)
+ ? (IEnumerable)content
+ : null;
+ if (a == null)
+ return;
+
+ MergeEnumerableContent(this, a, settings);
+ }
+
+ #region IList Members
+ ///
+ /// Determines the index of a specific item in the .
+ ///
+ /// The object to locate in the .
+ ///
+ /// The index of if found in the list; otherwise, -1.
+ ///
+ public int IndexOf(JToken item)
+ {
+ return IndexOfItem(item);
+ }
+
+ ///
+ /// Inserts an item to the at the specified index.
+ ///
+ /// The zero-based index at which should be inserted.
+ /// The object to insert into the .
+ ///
+ /// is not a valid index in the .
+ /// The is read-only.
+ public void Insert(int index, JToken item)
+ {
+ InsertItem(index, item, false);
+ }
+
+ ///
+ /// Removes the item at the specified index.
+ ///
+ /// The zero-based index of the item to remove.
+ ///
+ /// is not a valid index in the .
+ /// The is read-only.
+ public void RemoveAt(int index)
+ {
+ RemoveItemAt(index);
+ }
+
+ ///
+ /// Returns an enumerator that iterates through the collection.
+ ///
+ ///
+ /// A that can be used to iterate through the collection.
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ return Children().GetEnumerator();
+ }
+ #endregion
+
+ #region ICollection Members
+ ///
+ /// Adds an item to the .
+ ///
+ /// The object to add to the .
+ /// The is read-only.
+ public void Add(JToken item)
+ {
+ Add((object)item);
+ }
+
+ ///
+ /// Removes all items from the .
+ ///
+ /// The is read-only.
+ public void Clear()
+ {
+ ClearItems();
+ }
+
+ ///
+ /// Determines whether the contains a specific value.
+ ///
+ /// The object to locate in the .
+ ///
+ /// true if is found in the ; otherwise, false.
+ ///
+ public bool Contains(JToken item)
+ {
+ return ContainsItem(item);
+ }
+
+ ///
+ /// Copies to.
+ ///
+ /// The array.
+ /// Index of the array.
+ public void CopyTo(JToken[] array, int arrayIndex)
+ {
+ CopyItemsTo(array, arrayIndex);
+ }
+
+ ///
+ /// Gets a value indicating whether the is read-only.
+ ///
+ /// true if the is read-only; otherwise, false.
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Removes the first occurrence of a specific object from the .
+ ///
+ /// The object to remove from the .
+ ///
+ /// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
+ ///
+ /// The is read-only.
+ public bool Remove(JToken item)
+ {
+ return RemoveItem(item);
+ }
+ #endregion
+
+ internal override int GetDeepHashCode()
+ {
+ return ContentsHashCode();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Linq/JConstructor.cs b/Libs/JsonNet/Linq/JConstructor.cs
new file mode 100644
index 0000000..b267393
--- /dev/null
+++ b/Libs/JsonNet/Linq/JConstructor.cs
@@ -0,0 +1,218 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Linq
+{
+ ///
+ /// Represents a JSON constructor.
+ ///
+ public class JConstructor : JContainer
+ {
+ private string _name;
+ private readonly List _values = new List();
+
+ ///
+ /// Gets the container's children tokens.
+ ///
+ /// The container's children tokens.
+ protected override IList ChildrenTokens
+ {
+ get { return _values; }
+ }
+
+ internal override void MergeItem(object content, JsonMergeSettings settings)
+ {
+ JConstructor c = content as JConstructor;
+ if (c == null)
+ return;
+
+ if (c.Name != null)
+ Name = c.Name;
+ MergeEnumerableContent(this, c, settings);
+ }
+
+ ///
+ /// Gets or sets the name of this constructor.
+ ///
+ /// The constructor name.
+ public string Name
+ {
+ get { return _name; }
+ set { _name = value; }
+ }
+
+ ///
+ /// Gets the node type for this .
+ ///
+ /// The type.
+ public override JTokenType Type
+ {
+ get { return JTokenType.Constructor; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JConstructor()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class from another object.
+ ///
+ /// A object to copy from.
+ public JConstructor(JConstructor other)
+ : base(other)
+ {
+ _name = other.Name;
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified name and content.
+ ///
+ /// The constructor name.
+ /// The contents of the constructor.
+ public JConstructor(string name, params object[] content)
+ : this(name, (object)content)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified name and content.
+ ///
+ /// The constructor name.
+ /// The contents of the constructor.
+ public JConstructor(string name, object content)
+ : this(name)
+ {
+ Add(content);
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified name.
+ ///
+ /// The constructor name.
+ public JConstructor(string name)
+ {
+ ValidationUtils.ArgumentNotNullOrEmpty(name, "name");
+
+ _name = name;
+ }
+
+ internal override bool DeepEquals(JToken node)
+ {
+ JConstructor c = node as JConstructor;
+ return (c != null && _name == c.Name && ContentsEqual(c));
+ }
+
+ internal override JToken CloneToken()
+ {
+ return new JConstructor(this);
+ }
+
+ ///
+ /// Writes this token to a .
+ ///
+ /// A into which this method will write.
+ /// A collection of which will be used when writing the token.
+ public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
+ {
+ writer.WriteStartConstructor(_name);
+
+ foreach (JToken token in Children())
+ {
+ token.WriteTo(writer, converters);
+ }
+
+ writer.WriteEndConstructor();
+ }
+
+ ///
+ /// Gets the with the specified key.
+ ///
+ /// The with the specified key.
+ public override JToken this[object key]
+ {
+ get
+ {
+ ValidationUtils.ArgumentNotNull(key, "o");
+
+ if (!(key is int))
+ throw new ArgumentException("Accessed JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+ return GetItem((int)key);
+ }
+ set
+ {
+ ValidationUtils.ArgumentNotNull(key, "o");
+
+ if (!(key is int))
+ throw new ArgumentException("Set JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+ SetItem((int)key, value);
+ }
+ }
+
+ internal override int GetDeepHashCode()
+ {
+ return _name.GetHashCode() ^ ContentsHashCode();
+ }
+
+ ///
+ /// Loads an from a .
+ ///
+ /// A that will be read for the content of the .
+ /// A that contains the JSON that was read from the specified .
+ public new static JConstructor Load(JsonReader reader)
+ {
+ if (reader.TokenType == JsonToken.None)
+ {
+ if (!reader.Read())
+ throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader.");
+ }
+
+ while (reader.TokenType == JsonToken.Comment)
+ {
+ reader.Read();
+ }
+
+ if (reader.TokenType != JsonToken.StartConstructor)
+ throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+ JConstructor c = new JConstructor((string)reader.Value);
+ c.SetLineInfo(reader as IJsonLineInfo);
+
+ c.ReadTokenFrom(reader);
+
+ return c;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Linq/JContainer.cs b/Libs/JsonNet/Linq/JContainer.cs
new file mode 100644
index 0000000..3d16778
--- /dev/null
+++ b/Libs/JsonNet/Linq/JContainer.cs
@@ -0,0 +1,1115 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if !PORTABLE40
+using System.Collections.Specialized;
+#endif
+using System.Threading;
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+using System.Globalization;
+using System.ComponentModel;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Linq
+{
+ ///
+ /// Represents a token that can contain other tokens.
+ ///
+ public abstract class JContainer : JToken, IList
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+ , ITypedList, IBindingList
+#elif PORTABLE
+ , INotifyCollectionChanged
+#endif
+ , IList
+#if !(NET20 || NET35 || NETFX_CORE || PORTABLE40 || PORTABLE)
+ , INotifyCollectionChanged
+#endif
+ {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ internal ListChangedEventHandler _listChanged;
+ internal AddingNewEventHandler _addingNew;
+
+ ///
+ /// Occurs when the list changes or an item in the list changes.
+ ///
+ public event ListChangedEventHandler ListChanged
+ {
+ add { _listChanged += value; }
+ remove { _listChanged -= value; }
+ }
+
+ ///
+ /// Occurs before an item is added to the collection.
+ ///
+ public event AddingNewEventHandler AddingNew
+ {
+ add { _addingNew += value; }
+ remove { _addingNew -= value; }
+ }
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+ internal NotifyCollectionChangedEventHandler _collectionChanged;
+
+ ///
+ /// Occurs when the items list of the collection has changed, or the collection is reset.
+ ///
+ public event NotifyCollectionChangedEventHandler CollectionChanged
+ {
+ add { _collectionChanged += value; }
+ remove { _collectionChanged -= value; }
+ }
+#endif
+
+ ///
+ /// Gets the container's children tokens.
+ ///
+ /// The container's children tokens.
+ protected abstract IList ChildrenTokens { get; }
+
+ private object _syncRoot;
+#if !(PORTABLE40)
+ private bool _busy;
+#endif
+
+ internal JContainer()
+ {
+ }
+
+ internal JContainer(JContainer other)
+ : this()
+ {
+ ValidationUtils.ArgumentNotNull(other, "c");
+
+ int i = 0;
+ foreach (JToken child in other)
+ {
+ AddInternal(i, child, false);
+ i++;
+ }
+ }
+
+ internal void CheckReentrancy()
+ {
+#if !(PORTABLE40)
+ if (_busy)
+ throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType()));
+#endif
+ }
+
+ internal virtual IList CreateChildrenCollection()
+ {
+ return new List();
+ }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnAddingNew(AddingNewEventArgs e)
+ {
+ AddingNewEventHandler handler = _addingNew;
+ if (handler != null)
+ handler(this, e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnListChanged(ListChangedEventArgs e)
+ {
+ ListChangedEventHandler handler = _listChanged;
+
+ if (handler != null)
+ {
+ _busy = true;
+ try
+ {
+ handler(this, e);
+ }
+ finally
+ {
+ _busy = false;
+ }
+ }
+ }
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ NotifyCollectionChangedEventHandler handler = _collectionChanged;
+
+ if (handler != null)
+ {
+ _busy = true;
+ try
+ {
+ handler(this, e);
+ }
+ finally
+ {
+ _busy = false;
+ }
+ }
+ }
+#endif
+
+ ///
+ /// Gets a value indicating whether this token has child tokens.
+ ///
+ ///
+ /// true if this token has child values; otherwise, false .
+ ///
+ public override bool HasValues
+ {
+ get { return ChildrenTokens.Count > 0; }
+ }
+
+ internal bool ContentsEqual(JContainer container)
+ {
+ if (container == this)
+ return true;
+
+ IList t1 = ChildrenTokens;
+ IList t2 = container.ChildrenTokens;
+
+ if (t1.Count != t2.Count)
+ return false;
+
+ for (int i = 0; i < t1.Count; i++)
+ {
+ if (!t1[i].DeepEquals(t2[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Get the first child token of this token.
+ ///
+ ///
+ /// A containing the first child token of the .
+ ///
+ public override JToken First
+ {
+ get { return ChildrenTokens.FirstOrDefault(); }
+ }
+
+ ///
+ /// Get the last child token of this token.
+ ///
+ ///
+ /// A containing the last child token of the .
+ ///
+ public override JToken Last
+ {
+ get { return ChildrenTokens.LastOrDefault(); }
+ }
+
+ ///
+ /// Returns a collection of the child tokens of this token, in document order.
+ ///
+ ///
+ /// An of containing the child tokens of this , in document order.
+ ///
+ public override JEnumerable Children()
+ {
+ return new JEnumerable(ChildrenTokens);
+ }
+
+ ///
+ /// Returns a collection of the child values of this token, in document order.
+ ///
+ /// The type to convert the values to.
+ ///
+ /// A containing the child values of this , in document order.
+ ///
+ public override IEnumerable Values()
+ {
+ return ChildrenTokens.Convert();
+ }
+
+ ///
+ /// Returns a collection of the descendant tokens for this token in document order.
+ ///
+ /// An containing the descendant tokens of the .
+ public IEnumerable Descendants()
+ {
+ foreach (JToken o in ChildrenTokens)
+ {
+ yield return o;
+ JContainer c = o as JContainer;
+ if (c != null)
+ {
+ foreach (JToken d in c.Descendants())
+ {
+ yield return d;
+ }
+ }
+ }
+ }
+
+ internal bool IsMultiContent(object content)
+ {
+ return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[]));
+ }
+
+ internal JToken EnsureParentToken(JToken item, bool skipParentCheck)
+ {
+ if (item == null)
+ return JValue.CreateNull();
+
+ if (skipParentCheck)
+ return item;
+
+ // to avoid a token having multiple parents or creating a recursive loop, create a copy if...
+ // the item already has a parent
+ // the item is being added to itself
+ // the item is being added to the root parent of itself
+ if (item.Parent != null || item == this || (item.HasValues && Root == item))
+ item = item.CloneToken();
+
+ return item;
+ }
+
+ private class JTokenReferenceEqualityComparer : IEqualityComparer
+ {
+ public static readonly JTokenReferenceEqualityComparer Instance = new JTokenReferenceEqualityComparer();
+
+ public bool Equals(JToken x, JToken y)
+ {
+ return ReferenceEquals(x, y);
+ }
+
+ public int GetHashCode(JToken obj)
+ {
+ if (obj == null)
+ return 0;
+
+ return obj.GetHashCode();
+ }
+ }
+
+ internal int IndexOfItem(JToken item)
+ {
+ return ChildrenTokens.IndexOf(item, JTokenReferenceEqualityComparer.Instance);
+ }
+
+ internal virtual void InsertItem(int index, JToken item, bool skipParentCheck)
+ {
+ if (index > ChildrenTokens.Count)
+ throw new ArgumentOutOfRangeException("index", "Index must be within the bounds of the List.");
+
+ CheckReentrancy();
+
+ item = EnsureParentToken(item, skipParentCheck);
+
+ JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+ // haven't inserted new token yet so next token is still at the inserting index
+ JToken next = (index == ChildrenTokens.Count) ? null : ChildrenTokens[index];
+
+ ValidateToken(item, null);
+
+ item.Parent = this;
+
+ item.Previous = previous;
+ if (previous != null)
+ previous.Next = item;
+
+ item.Next = next;
+ if (next != null)
+ next.Previous = item;
+
+ ChildrenTokens.Insert(index, item);
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ if (_listChanged != null)
+ OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+ if (_collectionChanged != null)
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
+#endif
+ }
+
+ internal virtual void RemoveItemAt(int index)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", "Index is less than 0.");
+ if (index >= ChildrenTokens.Count)
+ throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count.");
+
+ CheckReentrancy();
+
+ JToken item = ChildrenTokens[index];
+ JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+ JToken next = (index == ChildrenTokens.Count - 1) ? null : ChildrenTokens[index + 1];
+
+ if (previous != null)
+ previous.Next = next;
+ if (next != null)
+ next.Previous = previous;
+
+ item.Parent = null;
+ item.Previous = null;
+ item.Next = null;
+
+ ChildrenTokens.RemoveAt(index);
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ if (_listChanged != null)
+ OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+ if (_collectionChanged != null)
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
+#endif
+ }
+
+ internal virtual bool RemoveItem(JToken item)
+ {
+ int index = IndexOfItem(item);
+ if (index >= 0)
+ {
+ RemoveItemAt(index);
+ return true;
+ }
+
+ return false;
+ }
+
+ internal virtual JToken GetItem(int index)
+ {
+ return ChildrenTokens[index];
+ }
+
+ internal virtual void SetItem(int index, JToken item)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", "Index is less than 0.");
+ if (index >= ChildrenTokens.Count)
+ throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count.");
+
+ JToken existing = ChildrenTokens[index];
+
+ if (IsTokenUnchanged(existing, item))
+ return;
+
+ CheckReentrancy();
+
+ item = EnsureParentToken(item, false);
+
+ ValidateToken(item, existing);
+
+ JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+ JToken next = (index == ChildrenTokens.Count - 1) ? null : ChildrenTokens[index + 1];
+
+ item.Parent = this;
+
+ item.Previous = previous;
+ if (previous != null)
+ previous.Next = item;
+
+ item.Next = next;
+ if (next != null)
+ next.Previous = item;
+
+ ChildrenTokens[index] = item;
+
+ existing.Parent = null;
+ existing.Previous = null;
+ existing.Next = null;
+
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+ if (_listChanged != null)
+ OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+ if (_collectionChanged != null)
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, existing, index));
+#endif
+ }
+
+ internal virtual void ClearItems()
+ {
+ CheckReentrancy();
+
+ foreach (JToken item in ChildrenTokens)
+ {
+ item.Parent = null;
+ item.Previous = null;
+ item.Next = null;
+ }
+
+ ChildrenTokens.Clear();
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ if (_listChanged != null)
+ OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+ if (_collectionChanged != null)
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+#endif
+ }
+
+ internal virtual void ReplaceItem(JToken existing, JToken replacement)
+ {
+ if (existing == null || existing.Parent != this)
+ return;
+
+ int index = IndexOfItem(existing);
+ SetItem(index, replacement);
+ }
+
+ internal virtual bool ContainsItem(JToken item)
+ {
+ return (IndexOfItem(item) != -1);
+ }
+
+ internal virtual void CopyItemsTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0.");
+ if (arrayIndex >= array.Length && arrayIndex != 0)
+ throw new ArgumentException("arrayIndex is equal to or greater than the length of array.");
+ if (Count > array.Length - arrayIndex)
+ throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.");
+
+ int index = 0;
+ foreach (JToken token in ChildrenTokens)
+ {
+ array.SetValue(token, arrayIndex + index);
+ index++;
+ }
+ }
+
+ internal static bool IsTokenUnchanged(JToken currentValue, JToken newValue)
+ {
+ JValue v1 = currentValue as JValue;
+ if (v1 != null)
+ {
+ // null will get turned into a JValue of type null
+ if (v1.Type == JTokenType.Null && newValue == null)
+ return true;
+
+ return v1.Equals(newValue);
+ }
+
+ return false;
+ }
+
+ internal virtual void ValidateToken(JToken o, JToken existing)
+ {
+ ValidationUtils.ArgumentNotNull(o, "o");
+
+ if (o.Type == JTokenType.Property)
+ throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
+ }
+
+ ///
+ /// Adds the specified content as children of this .
+ ///
+ /// The content to be added.
+ public virtual void Add(object content)
+ {
+ AddInternal(ChildrenTokens.Count, content, false);
+ }
+
+ internal void AddAndSkipParentCheck(JToken token)
+ {
+ AddInternal(ChildrenTokens.Count, token, true);
+ }
+
+ ///
+ /// Adds the specified content as the first children of this .
+ ///
+ /// The content to be added.
+ public void AddFirst(object content)
+ {
+ AddInternal(0, content, false);
+ }
+
+ internal void AddInternal(int index, object content, bool skipParentCheck)
+ {
+ if (IsMultiContent(content))
+ {
+ IEnumerable enumerable = (IEnumerable)content;
+
+ int multiIndex = index;
+ foreach (object c in enumerable)
+ {
+ AddInternal(multiIndex, c, skipParentCheck);
+ multiIndex++;
+ }
+ }
+ else
+ {
+ JToken item = CreateFromContent(content);
+
+ InsertItem(index, item, skipParentCheck);
+ }
+ }
+
+ internal static JToken CreateFromContent(object content)
+ {
+ if (content is JToken)
+ return (JToken)content;
+
+ return new JValue(content);
+ }
+
+ ///
+ /// Creates an that can be used to add tokens to the .
+ ///
+ /// An that is ready to have content written to it.
+ public JsonWriter CreateWriter()
+ {
+ return new JTokenWriter(this);
+ }
+
+ ///
+ /// Replaces the children nodes of this token with the specified content.
+ ///
+ /// The content.
+ public void ReplaceAll(object content)
+ {
+ ClearItems();
+ Add(content);
+ }
+
+ ///
+ /// Removes the child nodes from this token.
+ ///
+ public void RemoveAll()
+ {
+ ClearItems();
+ }
+
+ internal abstract void MergeItem(object content, JsonMergeSettings settings);
+
+ ///
+ /// Merge the specified content into this .
+ ///
+ /// The content to be merged.
+ public void Merge(object content)
+ {
+ MergeItem(content, new JsonMergeSettings());
+ }
+
+ ///
+ /// Merge the specified content into this using .
+ ///
+ /// The content to be merged.
+ /// The used to merge the content.
+ public void Merge(object content, JsonMergeSettings settings)
+ {
+ MergeItem(content, settings);
+ }
+
+ internal void ReadTokenFrom(JsonReader reader)
+ {
+ int startDepth = reader.Depth;
+
+ if (!reader.Read())
+ throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name));
+
+ ReadContentFrom(reader);
+
+ int endDepth = reader.Depth;
+
+ if (endDepth > startDepth)
+ throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name));
+ }
+
+ internal void ReadContentFrom(JsonReader r)
+ {
+ ValidationUtils.ArgumentNotNull(r, "r");
+ IJsonLineInfo lineInfo = r as IJsonLineInfo;
+
+ JContainer parent = this;
+
+ do
+ {
+ if (parent is JProperty && ((JProperty)parent).Value != null)
+ {
+ if (parent == this)
+ return;
+
+ parent = parent.Parent;
+ }
+
+ switch (r.TokenType)
+ {
+ case JsonToken.None:
+ // new reader. move to actual content
+ break;
+ case JsonToken.StartArray:
+ JArray a = new JArray();
+ a.SetLineInfo(lineInfo);
+ parent.Add(a);
+ parent = a;
+ break;
+
+ case JsonToken.EndArray:
+ if (parent == this)
+ return;
+
+ parent = parent.Parent;
+ break;
+ case JsonToken.StartObject:
+ JObject o = new JObject();
+ o.SetLineInfo(lineInfo);
+ parent.Add(o);
+ parent = o;
+ break;
+ case JsonToken.EndObject:
+ if (parent == this)
+ return;
+
+ parent = parent.Parent;
+ break;
+ case JsonToken.StartConstructor:
+ JConstructor constructor = new JConstructor(r.Value.ToString());
+ constructor.SetLineInfo(lineInfo);
+ parent.Add(constructor);
+ parent = constructor;
+ break;
+ case JsonToken.EndConstructor:
+ if (parent == this)
+ return;
+
+ parent = parent.Parent;
+ break;
+ case JsonToken.String:
+ case JsonToken.Integer:
+ case JsonToken.Float:
+ case JsonToken.Date:
+ case JsonToken.Boolean:
+ case JsonToken.Bytes:
+ JValue v = new JValue(r.Value);
+ v.SetLineInfo(lineInfo);
+ parent.Add(v);
+ break;
+ case JsonToken.Comment:
+ v = JValue.CreateComment(r.Value.ToString());
+ v.SetLineInfo(lineInfo);
+ parent.Add(v);
+ break;
+ case JsonToken.Null:
+ v = JValue.CreateNull();
+ v.SetLineInfo(lineInfo);
+ parent.Add(v);
+ break;
+ case JsonToken.Undefined:
+ v = JValue.CreateUndefined();
+ v.SetLineInfo(lineInfo);
+ parent.Add(v);
+ break;
+ case JsonToken.PropertyName:
+ string propertyName = r.Value.ToString();
+ JProperty property = new JProperty(propertyName);
+ property.SetLineInfo(lineInfo);
+ JObject parentObject = (JObject)parent;
+ // handle multiple properties with the same name in JSON
+ JProperty existingPropertyWithName = parentObject.Property(propertyName);
+ if (existingPropertyWithName == null)
+ parent.Add(property);
+ else
+ existingPropertyWithName.Replace(property);
+ parent = property;
+ break;
+ default:
+ throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, r.TokenType));
+ }
+ } while (r.Read());
+ }
+
+ internal int ContentsHashCode()
+ {
+ int hashCode = 0;
+ foreach (JToken item in ChildrenTokens)
+ {
+ hashCode ^= item.GetDeepHashCode();
+ }
+ return hashCode;
+ }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
+ {
+ return string.Empty;
+ }
+
+ PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
+ {
+ ICustomTypeDescriptor d = First as ICustomTypeDescriptor;
+ if (d != null)
+ return d.GetProperties();
+
+ return null;
+ }
+#endif
+
+ #region IList Members
+ int IList.IndexOf(JToken item)
+ {
+ return IndexOfItem(item);
+ }
+
+ void IList.Insert(int index, JToken item)
+ {
+ InsertItem(index, item, false);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ RemoveItemAt(index);
+ }
+
+ JToken IList.this[int index]
+ {
+ get { return GetItem(index); }
+ set { SetItem(index, value); }
+ }
+ #endregion
+
+ #region ICollection Members
+ void ICollection.Add(JToken item)
+ {
+ Add(item);
+ }
+
+ void ICollection.Clear()
+ {
+ ClearItems();
+ }
+
+ bool ICollection.Contains(JToken item)
+ {
+ return ContainsItem(item);
+ }
+
+ void ICollection.CopyTo(JToken[] array, int arrayIndex)
+ {
+ CopyItemsTo(array, arrayIndex);
+ }
+
+ bool ICollection.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ bool ICollection.Remove(JToken item)
+ {
+ return RemoveItem(item);
+ }
+ #endregion
+
+ private JToken EnsureValue(object value)
+ {
+ if (value == null)
+ return null;
+
+ if (value is JToken)
+ return (JToken)value;
+
+ throw new ArgumentException("Argument is not a JToken.");
+ }
+
+ #region IList Members
+ int IList.Add(object value)
+ {
+ Add(EnsureValue(value));
+ return Count - 1;
+ }
+
+ void IList.Clear()
+ {
+ ClearItems();
+ }
+
+ bool IList.Contains(object value)
+ {
+ return ContainsItem(EnsureValue(value));
+ }
+
+ int IList.IndexOf(object value)
+ {
+ return IndexOfItem(EnsureValue(value));
+ }
+
+ void IList.Insert(int index, object value)
+ {
+ InsertItem(index, EnsureValue(value), false);
+ }
+
+ bool IList.IsFixedSize
+ {
+ get { return false; }
+ }
+
+ bool IList.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ void IList.Remove(object value)
+ {
+ RemoveItem(EnsureValue(value));
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ RemoveItemAt(index);
+ }
+
+ object IList.this[int index]
+ {
+ get { return GetItem(index); }
+ set { SetItem(index, EnsureValue(value)); }
+ }
+ #endregion
+
+ #region ICollection Members
+ void ICollection.CopyTo(Array array, int index)
+ {
+ CopyItemsTo(array, index);
+ }
+
+ ///
+ /// Gets the count of child JSON tokens.
+ ///
+ /// The count of child JSON tokens
+ public int Count
+ {
+ get { return ChildrenTokens.Count; }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ if (_syncRoot == null)
+ Interlocked.CompareExchange(ref _syncRoot, new object(), null);
+
+ return _syncRoot;
+ }
+ }
+ #endregion
+
+ #region IBindingList Members
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+ void IBindingList.AddIndex(PropertyDescriptor property)
+ {
+ }
+
+ object IBindingList.AddNew()
+ {
+ AddingNewEventArgs args = new AddingNewEventArgs();
+ OnAddingNew(args);
+
+ if (args.NewObject == null)
+ throw new JsonException("Could not determine new value to add to '{0}'.".FormatWith(CultureInfo.InvariantCulture, GetType()));
+
+ if (!(args.NewObject is JToken))
+ throw new JsonException("New item to be added to collection must be compatible with {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JToken)));
+
+ JToken newItem = (JToken)args.NewObject;
+ Add(newItem);
+
+ return newItem;
+ }
+
+ bool IBindingList.AllowEdit
+ {
+ get { return true; }
+ }
+
+ bool IBindingList.AllowNew
+ {
+ get { return true; }
+ }
+
+ bool IBindingList.AllowRemove
+ {
+ get { return true; }
+ }
+
+ void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
+ {
+ throw new NotSupportedException();
+ }
+
+ int IBindingList.Find(PropertyDescriptor property, object key)
+ {
+ throw new NotSupportedException();
+ }
+
+ bool IBindingList.IsSorted
+ {
+ get { return false; }
+ }
+
+ void IBindingList.RemoveIndex(PropertyDescriptor property)
+ {
+ }
+
+ void IBindingList.RemoveSort()
+ {
+ throw new NotSupportedException();
+ }
+
+ ListSortDirection IBindingList.SortDirection
+ {
+ get { return ListSortDirection.Ascending; }
+ }
+
+ PropertyDescriptor IBindingList.SortProperty
+ {
+ get { return null; }
+ }
+
+ bool IBindingList.SupportsChangeNotification
+ {
+ get { return true; }
+ }
+
+ bool IBindingList.SupportsSearching
+ {
+ get { return false; }
+ }
+
+ bool IBindingList.SupportsSorting
+ {
+ get { return false; }
+ }
+#endif
+ #endregion
+
+ internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings settings)
+ {
+ switch (settings.MergeArrayHandling)
+ {
+ case MergeArrayHandling.Concat:
+ foreach (JToken item in content)
+ {
+ target.Add(item);
+ }
+ break;
+ case MergeArrayHandling.Union:
+#if !NET20
+ HashSet items = new HashSet(target, EqualityComparer);
+
+ foreach (JToken item in content)
+ {
+ if (items.Add(item))
+ {
+ target.Add(item);
+ }
+ }
+#else
+ IDictionary items = new Dictionary(EqualityComparer);
+ foreach (JToken t in target)
+ {
+ items[t] = true;
+ }
+
+ foreach (JToken item in content)
+ {
+ if (!items.ContainsKey(item))
+ {
+ items[item] = true;
+ target.Add(item);
+ }
+ }
+#endif
+ break;
+ case MergeArrayHandling.Replace:
+ target.ClearItems();
+ foreach (JToken item in content)
+ {
+ target.Add(item);
+ }
+ break;
+ case MergeArrayHandling.Merge:
+ int i = 0;
+ foreach (object targetItem in content)
+ {
+ if (i < target.Count)
+ {
+ JToken sourceItem = target[i];
+
+ JContainer existingContainer = sourceItem as JContainer;
+ if (existingContainer != null)
+ {
+ existingContainer.Merge(targetItem, settings);
+ }
+ else
+ {
+ if (targetItem != null)
+ {
+ JToken contentValue = CreateFromContent(targetItem);
+ if (contentValue.Type != JTokenType.Null)
+ target[i] = contentValue;
+ }
+ }
+ }
+ else
+ {
+ target.Add(targetItem);
+ }
+
+ i++;
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("settings", "Unexpected merge array handling when merging JSON.");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Linq/JEnumerable.cs b/Libs/JsonNet/Linq/JEnumerable.cs
new file mode 100644
index 0000000..5cf4fc8
--- /dev/null
+++ b/Libs/JsonNet/Linq/JEnumerable.cs
@@ -0,0 +1,143 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+
+namespace Newtonsoft.Json.Linq
+{
+ ///
+ /// Represents a collection of objects.
+ ///
+ /// The type of token
+ public struct JEnumerable : IJEnumerable, IEquatable> where T : JToken
+ {
+ ///
+ /// An empty collection of objects.
+ ///
+ public static readonly JEnumerable Empty = new JEnumerable(Enumerable.Empty());
+
+ private readonly IEnumerable _enumerable;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The enumerable.
+ public JEnumerable(IEnumerable enumerable)
+ {
+ ValidationUtils.ArgumentNotNull(enumerable, "enumerable");
+
+ _enumerable = enumerable;
+ }
+
+ ///
+ /// Returns an enumerator that iterates through the collection.
+ ///
+ ///
+ /// A that can be used to iterate through the collection.
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ if (_enumerable == null)
+ return Empty.GetEnumerator();
+
+ return _enumerable.GetEnumerator();
+ }
+
+ ///
+ /// Returns an enumerator that iterates through a collection.
+ ///
+ ///
+ /// An object that can be used to iterate through the collection.
+ ///
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ ///
+ /// Gets the with the specified key.
+ ///
+ ///
+ public IJEnumerable this[object key]
+ {
+ get
+ {
+ if (_enumerable == null)
+ return JEnumerable.Empty;
+
+ return new JEnumerable(_enumerable.Values(key));
+ }
+ }
+
+ ///
+ /// Determines whether the specified is equal to this instance.
+ ///
+ /// The to compare with this instance.
+ ///
+ /// true if the specified is equal to this instance; otherwise, false .
+ ///
+ public bool Equals(JEnumerable other)
+ {
+ return Equals(_enumerable, other._enumerable);
+ }
+
+ ///
+ /// Determines whether the specified is equal to this instance.
+ ///
+ /// The to compare with this instance.
+ ///
+ /// true if the specified is equal to this instance; otherwise, false .
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj is JEnumerable)
+ return Equals((JEnumerable)obj);
+
+ return false;
+ }
+
+ ///
+ /// Returns a hash code for this instance.
+ ///
+ ///
+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+ ///
+ public override int GetHashCode()
+ {
+ if (_enumerable == null)
+ return 0;
+
+ return _enumerable.GetHashCode();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/JsonNet/Linq/JObject.cs b/Libs/JsonNet/Linq/JObject.cs
new file mode 100644
index 0000000..0ef4b0e
--- /dev/null
+++ b/Libs/JsonNet/Linq/JObject.cs
@@ -0,0 +1,824 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if !PORTABLE40
+using System.Collections.Specialized;
+#endif
+using System.ComponentModel;
+#if !(NET35 || NET20 || PORTABLE40)
+using System.Dynamic;
+using System.Linq.Expressions;
+#endif
+using System.IO;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+
+namespace Newtonsoft.Json.Linq
+{
+ ///
+ /// Represents a JSON object.
+ ///
+ ///
+ ///
+ ///
+ public class JObject : JContainer, IDictionary, INotifyPropertyChanged
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ , ICustomTypeDescriptor
+#endif
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+ , INotifyPropertyChanging
+#endif
+ {
+ private readonly JPropertyKeyedCollection _properties = new JPropertyKeyedCollection();
+
+ ///
+ /// Gets the container's children tokens.
+ ///
+ /// The container's children tokens.
+ protected override IList ChildrenTokens
+ {
+ get { return _properties; }
+ }
+
+ ///
+ /// Occurs when a property value changes.
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+
+#if !(NET20 || NETFX_CORE || PORTABLE || PORTABLE40)
+ ///
+ /// Occurs when a property value is changing.
+ ///
+ public event PropertyChangingEventHandler PropertyChanging;
+#endif
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JObject()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class from another object.
+ ///
+ /// A object to copy from.
+ public JObject(JObject other)
+ : base(other)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified content.
+ ///
+ /// The contents of the object.
+ public JObject(params object[] content)
+ : this((object)content)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified content.
+ ///
+ /// The contents of the object.
+ public JObject(object content)
+ {
+ Add(content);
+ }
+
+ internal override bool DeepEquals(JToken node)
+ {
+ JObject t = node as JObject;
+ if (t == null)
+ return false;
+
+ return _properties.Compare(t._properties);
+ }
+
+ internal override void InsertItem(int index, JToken item, bool skipParentCheck)
+ {
+ // don't add comments to JObject, no name to reference comment by
+ if (item != null && item.Type == JTokenType.Comment)
+ return;
+
+ base.InsertItem(index, item, skipParentCheck);
+ }
+
+ internal override void ValidateToken(JToken o, JToken existing)
+ {
+ ValidationUtils.ArgumentNotNull(o, "o");
+
+ if (o.Type != JTokenType.Property)
+ throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
+
+ JProperty newProperty = (JProperty)o;
+
+ if (existing != null)
+ {
+ JProperty existingProperty = (JProperty)existing;
+
+ if (newProperty.Name == existingProperty.Name)
+ return;
+ }
+
+ if (_properties.TryGetValue(newProperty.Name, out existing))
+ throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, newProperty.Name, GetType()));
+ }
+
+ internal override void MergeItem(object content, JsonMergeSettings settings)
+ {
+ JObject o = content as JObject;
+ if (o == null)
+ return;
+
+ foreach (KeyValuePair contentItem in o)
+ {
+ JProperty existingProperty = Property(contentItem.Key);
+
+ if (existingProperty == null)
+ {
+ Add(contentItem.Key, contentItem.Value);
+ }
+ else if (contentItem.Value != null)
+ {
+ JContainer existingContainer = existingProperty.Value as JContainer;
+ if (existingContainer == null)
+ {
+ if (contentItem.Value.Type != JTokenType.Null)
+ existingProperty.Value = contentItem.Value;
+ }
+ else if (existingContainer.Type != contentItem.Value.Type)
+ {
+ existingProperty.Value = contentItem.Value;
+ }
+ else
+ {
+ existingContainer.Merge(contentItem.Value, settings);
+ }
+ }
+ }
+ }
+
+ internal void InternalPropertyChanged(JProperty childProperty)
+ {
+ OnPropertyChanged(childProperty.Name);
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+ if (_listChanged != null)
+ OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty)));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+ if (_collectionChanged != null)
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty)));
+#endif
+ }
+
+ internal void InternalPropertyChanging(JProperty childProperty)
+ {
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+ OnPropertyChanging(childProperty.Name);
+#endif
+ }
+
+ internal override JToken CloneToken()
+ {
+ return new JObject(this);
+ }
+
+ ///
+ /// Gets the node type for this