/// <summary>
        /// Serializes an object into a JSON string based on discriminator
        /// field and object name. If JsonObject attribute is available, its value is used instead.
        /// </summary>
        /// <param name="writer">The JSON writer.</param>
        /// <param name="value">The value to serialize.</param>
        /// <param name="serializer">The JSON serializer.</param>
        public override void WriteJson(JsonWriter writer,
                                       object value, JsonSerializer serializer)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            if (serializer == null)
            {
                throw new ArgumentNullException("serializer");
            }

            string typeName = value.GetType().Name;

            if (value.GetType().GetTypeInfo().GetCustomAttributes <JsonObjectAttribute>().Any())
            {
                typeName = value.GetType().GetTypeInfo().GetCustomAttribute <JsonObjectAttribute>().Id;
            }

            // Add discriminator field
            writer.WriteStartObject();
            writer.WritePropertyName(Discriminator);
            writer.WriteValue(typeName);
            JsonConverterHelper.SerializeProperties(writer, value, serializer);
            writer.WriteEndObject();
        }
        /// <summary>
        /// Serializes an object into a JSON string based on discriminator
        /// field and object name. If JsonObject attribute is available, its value is used instead.
        /// </summary>
        /// <param name="writer">The JSON writer.</param>
        /// <param name="value">The value to serialize.</param>
        /// <param name="serializer">The JSON serializer.</param>
        public override void WriteJson(JsonWriter writer,
                                       object value, JsonSerializer serializer)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            if (serializer == null)
            {
                throw new ArgumentNullException("serializer");
            }

            string typeName = value.GetType().Name;
            // check if the jsonobject attribute was inherited from basetype, if yes, we don't want to use it to serialize the object
            var baseTypeAttribute    = value.GetType().GetTypeInfo().BaseType.GetTypeInfo().GetCustomAttribute <JsonObjectAttribute>()?.Id;
            var derivedTypeAttribute = value.GetType().GetTypeInfo().GetCustomAttribute <JsonObjectAttribute>()?.Id;

            if (!string.IsNullOrEmpty(derivedTypeAttribute) && derivedTypeAttribute != baseTypeAttribute)
            {
                typeName = derivedTypeAttribute;
            }

            // Add discriminator field
            writer.WriteStartObject();
            writer.WritePropertyName(Discriminator);
            writer.WriteValue(typeName);
            JsonConverterHelper.SerializeProperties(writer, value, serializer);
            writer.WriteEndObject();
        }