Inheritance: IDisposable
        private object Read(JsonReader reader, IJsonSerializeOperationInfo info)
        {
            string value;

            switch (reader.NodeType)
            {
                case JsonNodeType.Number:
                case JsonNodeType.String:
                    value = (string)reader.Value;
                    break;
                case JsonNodeType.Boolean:
                    value = (bool)reader.Value ? "true" : "false";
                    break;
                default:
                    if (_nullable && reader.NodeType == JsonNodeType.Null)
                    {
                        value = null;
                    }
                    else
                    {
                        throw new XSerializerException(string.Format(
                            "Unexpected node type '{0}' encountered in '{1}.DeserializeObject' method.",
                            reader.NodeType,
                            typeof(StringJsonSerializer)));
                    }
                    break;
            }

            return _read(value, info);
        }
        private object Read(JsonReader reader)
        {
            if (reader.NodeType != JsonNodeType.Boolean)
            {
                if (reader.NodeType == JsonNodeType.String)
                {
                    var value = (string)reader.Value;

                    if (value == "true")
                    {
                        return true;
                    }

                    if (value == "false")
                    {
                        return false;
                    }

                    if (_nullable && value == "")
                    {
                        return null;
                    }
                }
                else if (!_nullable && reader.NodeType != JsonNodeType.Null)
                {
                    throw new XSerializerException(string.Format(
                        "Unexpected node type '{0}' encountered in '{1}.DeserializeObject' method.",
                        reader.NodeType,
                        typeof(BooleanJsonSerializer)));
                }
            }

            return reader.Value;
        }
        public object DeserializeObject(
            JsonReader reader, IJsonSerializeOperationInfo info, string path)
        {
            if (!reader.ReadContent(path))
            {
                if (reader.NodeType == JsonNodeType.Invalid)
                {
                    throw new MalformedDocumentException(MalformedDocumentError.InvalidValue,
                        path, reader.Value, reader.Line, reader.Position);
                }

                Debug.Assert(reader.NodeType == JsonNodeType.EndOfString);

                throw new MalformedDocumentException(MalformedDocumentError.MissingValue,
                    path, reader.Value, reader.Line, reader.Position);
            }

            if (_encrypt)
            {
                var toggler = new DecryptReadsToggler(reader, path);
                if (toggler.Toggle())
                {
                    if (reader.NodeType == JsonNodeType.Invalid)
                    {
                        throw new MalformedDocumentException(MalformedDocumentError.InvalidValue,
                            path, reader.Value, reader.Line, reader.Position);
                    }

                    var exception = false;

                    try
                    {
                        return Read(reader, info, path);
                    }
                    catch (MalformedDocumentException)
                    {
                        exception = true;
                        throw;
                    }
                    finally
                    {
                        if (!exception)
                        {
                            if (reader.ReadContent(path) || reader.NodeType == JsonNodeType.Invalid)
                            {
                                throw new MalformedDocumentException(MalformedDocumentError.ExpectedEndOfDecryptedString,
                                    path, reader.Value, reader.Line, reader.Position, null, reader.NodeType);
                            }

                            toggler.Revert();
                        }
                    }
                }
            }

            return Read(reader, info, path);
        }
        public object DeserializeObject(JsonReader reader, IJsonSerializeOperationInfo info, string path)
        {
            if (!reader.ReadContent(path))
            {
                if (reader.NodeType == JsonNodeType.EndOfString)
                {
                    throw new MalformedDocumentException(MalformedDocumentError.MissingValue,
                        path, reader.Line, reader.Position);
                }

                Debug.Assert(reader.NodeType == JsonNodeType.Invalid);

                if (reader.Value is string)
                {
                    throw GetMissingCloseQuoteException(reader, path);
                }

                throw GetMissingOpenQuoteException(reader, path);
            }

            if (_encrypt)
            {
                var toggler = new DecryptReadsToggler(reader, path);
                toggler.Toggle();

                switch (reader.NodeType)
                {
                    case JsonNodeType.Number:
                    case JsonNodeType.String:
                    case JsonNodeType.Boolean:
                        break;
                    case JsonNodeType.EndOfString:
                        throw new MalformedDocumentException(MalformedDocumentError.MissingValue,
                            path, reader.Line, reader.Position);
                    case JsonNodeType.Invalid:
                        if (reader.Value is string)
                        {
                            throw GetMissingCloseQuoteException(reader, path);
                        }

                        throw GetMissingOpenQuoteException(reader, path);
                    default:
                        throw GetMissingOpenQuoteException(reader, path);
                }

                try
                {
                    return Read(reader, info, path);
                }
                finally
                {
                    toggler.Revert();
                }
            }

            return Read(reader, info, path);
        }
        private object Read(JsonReader reader)
        {
            if (reader.NodeType != JsonNodeType.Number
                && reader.NodeType != JsonNodeType.String)
            {
                if (!_nullable && reader.NodeType != JsonNodeType.Null)
                {
                    throw new XSerializerException(string.Format(
                        "Unexpected node type '{0}' encountered in '{1}.DeserializeObject' method.",
                        reader.NodeType,
                        typeof(NumberJsonSerializer)));
                }
            }

            return _read((string)reader.Value);
        }
        public object DeserializeObject(JsonReader reader, IJsonSerializeOperationInfo info)
        {
            if (!reader.ReadContent())
            {
                throw new XSerializerException("Reached end of stream while parsing string value.");
            }

            if (_encrypt)
            {
                var toggler = new DecryptReadsToggler(reader);
                toggler.Toggle();

                try
                {
                    return Read(reader, info);
                }
                finally
                {
                    toggler.Revert();
                }
            }

            return Read(reader, info);
        }
            public bool SetValue(JsonReader reader, string propertyName, IJsonSerializeOperationInfo info, string path)
            {
                SerializableJsonProperty property;

                if (_serializablePropertiesMap.TryGetValue(propertyName, out property))
                {
                    property.SetValue(_instance, reader, info, path);
                    return true;
                }

                return false;
            }
        private object Read(JsonReader reader, IJsonSerializeOperationInfo info, string path)
        {
            var factory = _createObjectFactory.Value.Invoke();

            foreach (var propertyName in reader.ReadProperties(path))
            {
                var propertyPath = path.AppendProperty(propertyName);

                if (!factory.SetValue(reader, propertyName, info, propertyPath))
                {
                    reader.Discard(propertyPath);
                }
            }

            return factory.GetInstance();
        }
        private object DeserializeJsonArray(JsonReader reader, IJsonSerializeOperationInfo info)
        {
            var jsonArray = new JsonArray(info);

            while (true)
            {
                if (reader.PeekNextNodeType() == JsonNodeType.CloseArray)
                {
                    // If the next content is CloseArray, read it and return the empty list.
                    reader.Read();
                    return jsonArray;
                }

                jsonArray.Add(DeserializeObject(reader, info));

                if (!reader.ReadContent())
                {
                    throw new XSerializerException("Unexpected end of input while attempting to parse ',' character.");
                }

                if (reader.NodeType == JsonNodeType.CloseArray)
                {
                    break;
                }

                if (reader.NodeType != JsonNodeType.ItemSeparator)
                {
                    throw new XSerializerException("Unexpected node type found while attempting to parse ',' character: " +
                                                   reader.NodeType + ".");
                }
            }

            return jsonArray;
        }
        private object Read(JsonReader reader, IJsonSerializeOperationInfo info)
        {
            var factory = _createObjectFactory.Value.Invoke();

            foreach (var propertyName in reader.ReadProperties())
            {
                if (!factory.SetValue(reader, propertyName, info))
                {
                    reader.Discard();
                }
            }

            return factory.GetInstance();
        }
 private static MalformedDocumentException GetMissingOpenQuoteException(JsonReader reader, string path)
 {
     return new MalformedDocumentException(MalformedDocumentError.StringMissingOpenQuote,
         path, reader.Value, reader.Line, reader.Position);
 }
        public object DeserializeObject(JsonReader reader, IJsonSerializeOperationInfo info)
        {
            if (!reader.ReadContent())
            {
                throw new XSerializerException("Unexpected end of input while attempting to parse '{' character.");
            }

            if (reader.NodeType == JsonNodeType.Null)
            {
                return null;
            }

            if (_encrypt)
            {
                var toggler = new DecryptReadsToggler(reader);
                toggler.Toggle();

                try
                {
                    return Read(reader, info);
                }
                finally
                {
                    toggler.Revert();
                }
            }

            return Read(reader, info);
        }
 private object Read(JsonReader reader, IJsonSerializeOperationInfo info, string path)
 {
     switch (reader.NodeType)
     {
         case JsonNodeType.Null:
         case JsonNodeType.String:
         case JsonNodeType.Boolean:
             return reader.Value;
         case JsonNodeType.Number:
             try
             {
                 return new JsonNumber((string)reader.Value);
             }
             catch (ArgumentException ex)
             {
                 throw new MalformedDocumentException(MalformedDocumentError.InvalidValue,
                     path, reader.Value, reader.Line, reader.Position, ex);
             }
         case JsonNodeType.OpenObject:
             return DeserializeJsonObject(reader, info, path);
         case JsonNodeType.OpenArray:
             return DeserializeJsonArray(reader, info, path);
         case JsonNodeType.EndOfString:
             throw new MalformedDocumentException(MalformedDocumentError.MissingValue,
                 path, reader.Line, reader.Position);
         default:
             throw new MalformedDocumentException(MalformedDocumentError.InvalidValue,
                 path, reader.Value, reader.Line, reader.Position);
     }
 }
        private object Read(JsonReader reader, IJsonSerializeOperationInfo info)
        {
            if (reader.NodeType == JsonNodeType.Null)
            {
                return null;
            }

            var list = _createList();

            while (true)
            {
                if (reader.PeekNextNodeType() == JsonNodeType.CloseArray)
                {
                    // If the next content is CloseArray, read it and return the empty list.
                    reader.Read();
                    return list;
                }

                var item = _itemSerializer.DeserializeObject(reader, info);
                _addItem(list, item);

                if (!reader.ReadContent())
                {
                    throw new XSerializerException("Unexpected end of input while attempting to parse ',' character.");
                }

                if (reader.NodeType == JsonNodeType.CloseArray)
                {
                    break;
                }

                if (reader.NodeType != JsonNodeType.ItemSeparator)
                {
                    throw new XSerializerException("Unexpected node type found while attempting to parse ',' character: " +
                                                   reader.NodeType + ".");
                }
            }

            return list;
        }
        private Func<string, IJsonSerializeOperationInfo, object> GetDeserializeKeyFunc(Type type)
        {
            if (type == typeof(string))
            {
                return (keyString, info) => keyString;
            }

            var serializer = JsonSerializerFactory.GetSerializer(type, _encrypt, _mappings);

            return (keyString, info) =>
            {
                try
                {
                    using (var stringReader = new StringReader(keyString))
                    {
                        using (var reader = new JsonReader(stringReader, info))
                        {
                            return serializer.DeserializeObject(reader, info);
                        }
                    }
                }
                catch (XSerializerException)
                {
                    return keyString;
                }
            };
        }
        private object DeserializeJsonArray(JsonReader reader, IJsonSerializeOperationInfo info, string path)
        {
            var jsonArray = new JsonArray(info);

            if (reader.PeekContent() == JsonNodeType.CloseArray)
            {
                // If the next content node is CloseArray, we're reading an empty
                // array. Read the CloseArray node and return the empty array.
                reader.Read(path);
                return jsonArray;
            }

            var index = 0;

            while (true)
            {
                jsonArray.Add(DeserializeObject(reader, info, path + "[" + index++ + "]"));

                if (!reader.ReadContent(path))
                {
                    throw new MalformedDocumentException(MalformedDocumentError.ArrayMissingCommaOrCloseSquareBracket,
                        path, reader.Line, reader.Position);
                }

                if (reader.NodeType == JsonNodeType.CloseArray)
                {
                    break;
                }

                if (reader.NodeType != JsonNodeType.ItemSeparator)
                {
                    throw new MalformedDocumentException(MalformedDocumentError.ArrayMissingCommaOrCloseSquareBracket,
                        path, reader.Line, reader.Position);
                }
            }

            return jsonArray;
        }
        private object Read(JsonReader reader, IJsonSerializeOperationInfo info)
        {
            var dictionary = _createDictionary();

            foreach (var keyString in reader.ReadProperties())
            {
                var key = _deserializeKey(keyString, info);
                var value = _valueSerializer.DeserializeObject(reader, info);

                var jsonNumber = value as JsonNumber;
                if (jsonNumber != null)
                {
                    value = jsonNumber.DoubleValue;
                }

                _addToDictionary(dictionary, key, value);
            }

            return dictionary;
        }
        private object Read(JsonReader reader, string path)
        {
            if (reader.NodeType == JsonNodeType.Number || reader.NodeType == JsonNodeType.String)
            {
                return _read((string)reader.Value, path, reader.Line, reader.Position);
            }

            if (_nullable && reader.NodeType == JsonNodeType.Null)
            {
                return null;
            }

            throw GetNumberInvalidValueException(reader, path);
        }
        private MalformedDocumentException GetNumberInvalidValueException(JsonReader reader, string path)
        {
            var invalidValue = reader.Value;

            if (invalidValue is bool)
            {
                invalidValue = invalidValue.ToString().ToLower();
            }

            return new MalformedDocumentException(MalformedDocumentError.NumberInvalidValue,
                path, invalidValue, reader.Line, reader.Position, null, _type);
        }
            public bool SetValue(JsonReader reader, string propertyName, IJsonSerializeOperationInfo info, string path)
            {
                var serializerAndArgIndex = _getSerializerAndArgIndex(propertyName);

                if (serializerAndArgIndex != null)
                {
                    var value = serializerAndArgIndex.Item1.DeserializeObject(reader, info, path + "." + propertyName);
                    _constructorArguments[serializerAndArgIndex.Item2] = value;
                    return true;
                }

                SerializableJsonProperty property;
                if (_serializablePropertiesMap.TryGetValue(propertyName, out property))
                {
                    var value = property.ReadValue(reader, info, path + "." + propertyName);
                    _setPropertyValueActions.Add(instance => property.SetValue(instance, value));
                    return true;
                }

                return false;
            }
 private object Read(JsonReader reader, IJsonSerializeOperationInfo info)
 {
     switch (reader.NodeType)
     {
         case JsonNodeType.Null:
         case JsonNodeType.String:
         case JsonNodeType.Boolean:
             return reader.Value;
         case JsonNodeType.Number:
             return new JsonNumber((string)reader.Value);
         case JsonNodeType.OpenObject:
             return DeserializeJsonObject(reader, info);
         case JsonNodeType.OpenArray:
             return DeserializeJsonArray(reader, info);
         default:
             throw new XSerializerException("Invalid json.");
     }
 }
        private object Read(JsonReader reader, string path)
        {
            if (reader.NodeType == JsonNodeType.Boolean)
            {
                return reader.Value;
            }

            if (_nullable && reader.NodeType == JsonNodeType.Null)
            {
                return null;
            }

            if (reader.NodeType == JsonNodeType.String)
            {
                var value = (string)reader.Value;

                if (value == "true")
                {
                    return true;
                }

                if (value == "false")
                {
                    return false;
                }

                if (_nullable && value == "")
                {
                    return null;
                }
            }

            throw new MalformedDocumentException(MalformedDocumentError.BooleanInvalidValue,
                path, reader.Value, reader.Line, reader.Position);
        }
        private object Read(JsonReader reader, IJsonSerializeOperationInfo info, string path)
        {
            string value;

            switch (reader.NodeType)
            {
                case JsonNodeType.Number:
                case JsonNodeType.String:
                    value = (string)reader.Value;
                    break;
                case JsonNodeType.Boolean:
                    value = (bool)reader.Value ? "true" : "false";
                    break;
                default:
                    if (_nullable && reader.NodeType == JsonNodeType.Null)
                    {
                        value = null;
                    }
                    else
                    {
                        throw GetMissingOpenQuoteException(reader, path);
                    }
                    break;
            }

            return _read(value, info, path, reader.Line, reader.Position);
        }
        private object DeserializeJsonObject(JsonReader reader, IJsonSerializeOperationInfo info, string path)
        {
            var jsonObject = new JsonObject(info);

            foreach (var propertyName in reader.ReadProperties(path))
            {
                jsonObject.Add(propertyName, DeserializeObject(reader, info, path.AppendProperty(propertyName)));
            }

            return jsonObject;
        }
 public object ReadValue(JsonReader reader, IJsonSerializeOperationInfo info, string path)
 {
     return _serializer.Value.DeserializeObject(reader, info, path);
 }
 public object DeserializeObject(JsonReader reader, IJsonSerializeOperationInfo info, string path)
 {
     throw new NotImplementedException();
 }
 public void SetValue(object instance, JsonReader reader, IJsonSerializeOperationInfo info, string path)
 {
     var value = ReadValue(reader, info, path);
     _setValue(instance, value);
 }
        private object Read(JsonReader reader, IJsonSerializeOperationInfo info, string path)
        {
            if (reader.NodeType == JsonNodeType.Null)
            {
                return null;
            }

            var list = _createList();

            if (reader.PeekContent() == JsonNodeType.CloseArray)
            {
                // If the next content node is CloseArray, we're reading an empty
                // array. Read the CloseArray node and return the empty list.
                reader.Read(path);
                return _transformList(list);
            }

            var index = 0;

            while (true)
            {
                var item = _itemSerializer.DeserializeObject(reader, info, path + "[" + index++ + "]");
                _addItem(list, item);

                if (!reader.ReadContent(path))
                {
                    Debug.Assert(reader.NodeType == JsonNodeType.EndOfString);

                    throw new MalformedDocumentException(MalformedDocumentError.ArrayMissingCommaOrCloseSquareBracket,
                        path, reader.Line, reader.Position);
                }

                if (reader.NodeType == JsonNodeType.CloseArray)
                {
                    break;
                }

                if (reader.NodeType != JsonNodeType.ItemSeparator)
                {
                    throw new MalformedDocumentException(MalformedDocumentError.ArrayMissingCommaOrCloseSquareBracket,
                        path, reader.Value, reader.Line, reader.Position);
                }
            }

            return _transformList(list);
        }
        public object DeserializeObject(JsonReader reader, IJsonSerializeOperationInfo info)
        {
            if (!reader.ReadContent())
            {
                throw new XSerializerException("Unexpected end of input while attempting to parse beginning of value.");
            }

            if (_encrypt)
            {
                var toggler = new DecryptReadsToggler(reader);
                toggler.Toggle();

                try
                {
                    return Read(reader, info);
                }
                finally
                {
                    toggler.Revert();
                }
            }

            return Read(reader, info);
        }