Beispiel #1
0
    /// <summary>
    /// Objects the type of the string to.
    /// </summary>
    /// <param name="strType">Type of the string.</param>
    /// <returns>System.Object.</returns>
    public static object ObjectStringToType(ReadOnlySpan <char> strType)
    {
        var type = ExtractType(strType);

        if (type != null)
        {
            var parseFn       = Serializer.GetParseStringSpanFn(type);
            var propertyValue = parseFn(strType);
            return(propertyValue);
        }

        var config = JsConfig.GetConfig();

        if (config.ConvertObjectTypesIntoStringDictionary && !strType.IsNullOrEmpty())
        {
            var firstChar = strType[0];
            var endChar   = strType[strType.Length - 1];
            switch (firstChar)
            {
            case JsWriter.MapStartChar when endChar == JsWriter.MapEndChar:
            {
                var dynamicMatch = DeserializeDictionary <TSerializer> .ParseDictionary <string, object>(strType, null, v => Serializer.UnescapeString(v).ToString(), v => Serializer.UnescapeString(v).ToString());

                if (dynamicMatch is { Count : > 0 })
                {
                    return(dynamicMatch);
                }

                break;
            }
Beispiel #2
0
    /// <summary>
    /// Parses the dictionary.
    /// </summary>
    /// <typeparam name="TKey">The type of the t key.</typeparam>
    /// <typeparam name="TValue">The type of the t value.</typeparam>
    /// <param name="value">The value.</param>
    /// <param name="createMapType">Type of the create map.</param>
    /// <param name="parseKeyFn">The parse key function.</param>
    /// <param name="parseValueFn">The parse value function.</param>
    /// <returns>IDictionary&lt;TKey, TValue&gt;.</returns>
    public static IDictionary <TKey, TValue> ParseDictionary <TKey, TValue>(
        ReadOnlySpan <char> value, Type createMapType,
        ParseStringSpanDelegate parseKeyFn, ParseStringSpanDelegate parseValueFn)
    {
        if (value.IsEmpty)
        {
            return(null);
        }

        var to = createMapType == null
                     ? new Dictionary <TKey, TValue>()
                     : (IDictionary <TKey, TValue>)createMapType.CreateInstance();

        var objDeserializer = Json.JsonTypeSerializer.Instance.ObjectDeserializer;

        if (to is Dictionary <string, object> && objDeserializer != null && typeof(TSerializer) == typeof(Json.JsonTypeSerializer))
        {
            return((IDictionary <TKey, TValue>)objDeserializer(value));
        }

        var config = JsConfig.GetConfig();

        var tryToParseItemsAsDictionaries =
            config.ConvertObjectTypesIntoStringDictionary && typeof(TValue) == typeof(object);
        var tryToParseItemsAsPrimitiveTypes =
            config.TryToParsePrimitiveTypeValues && typeof(TValue) == typeof(object);

        var index = VerifyAndGetStartIndex(value, createMapType);

        if (Json.JsonTypeSerializer.IsEmptyMap(value, index))
        {
            return(to);
        }

        var valueLength = value.Length;

        while (index < valueLength)
        {
            var keyValue = Serializer.EatMapKey(value, ref index);
            Serializer.EatMapKeySeperator(value, ref index);
            var elementStartIndex = index;
            var elementValue      = Serializer.EatTypeValue(value, ref index);
            if (keyValue.IsNullOrEmpty())
            {
                continue;
            }

            TKey mapKey = (TKey)parseKeyFn(keyValue);

            if (tryToParseItemsAsDictionaries)
            {
                Serializer.EatWhitespace(value, ref elementStartIndex);
                if (elementStartIndex < valueLength && value[elementStartIndex] == JsWriter.MapStartChar)
                {
                    var tmpMap = ParseDictionary <TKey, TValue>(elementValue, createMapType, parseKeyFn, parseValueFn);
                    if (tmpMap is { Count : > 0 })
Beispiel #3
0
        public static void WriteWcfJsonDate(TextWriter writer, DateTime dateTime)
        {
            var config = JsConfig.GetConfig();

            dateTime = dateTime.UseConfigSpecifiedSetting();
            switch (config.DateHandler)
            {
            case DateHandler.ISO8601:
                writer.Write(dateTime.ToString("o", CultureInfo.InvariantCulture));
                return;

            case DateHandler.ISO8601DateOnly:
                writer.Write(dateTime.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
                return;

            case DateHandler.ISO8601DateTime:
                writer.Write(dateTime.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture));
                return;

            case DateHandler.RFC1123:
                writer.Write(dateTime.ToUniversalTime().ToString("R", CultureInfo.InvariantCulture));
                return;
            }

            var    timestamp = dateTime.ToUnixTimeMs();
            string offset    = null;

            if (dateTime.Kind != DateTimeKind.Utc)
            {
                if (config.DateHandler == DateHandler.TimestampOffset && dateTime.Kind == DateTimeKind.Unspecified)
                {
                    offset = UnspecifiedOffset;
                }
                else
                {
                    offset = LocalTimeZone.GetUtcOffset(dateTime).ToTimeOffsetString();
                }
            }
            else
            {
                // Normally the JsonDateHandler.TimestampOffset doesn't append an offset for Utc dates, but if
                // the config.AppendUtcOffset is set then we will
                if (config.DateHandler == DateHandler.TimestampOffset && config.AppendUtcOffset)
                {
                    offset = UtcOffset;
                }
            }

            writer.Write(EscapedWcfJsonPrefix);
            writer.Write(timestamp);
            if (offset != null)
            {
                writer.Write(offset);
            }
            writer.Write(EscapedWcfJsonSuffix);
        }
        public static object ParseQuotedPrimitive(string value)
        {
            var config = JsConfig.GetConfig();
            var fn     = config.ParsePrimitiveFn;
            var result = fn?.Invoke(value);

            if (result != null)
            {
                return(result);
            }

            if (string.IsNullOrEmpty(value))
            {
                return(null);
            }

            if (Guid.TryParse(value, out Guid guidValue))
            {
                return(guidValue);
            }

            if (value.StartsWith(DateTimeSerializer.EscapedWcfJsonPrefix, StringComparison.Ordinal) || value.StartsWith(DateTimeSerializer.WcfJsonPrefix, StringComparison.Ordinal))
            {
                return(DateTimeSerializer.ParseWcfJsonDate(value));
            }

            if (JsConfig.DateHandler == DateHandler.ISO8601)
            {
                // check that we have UTC ISO8601 date:
                // YYYY-MM-DDThh:mm:ssZ
                // YYYY-MM-DDThh:mm:ss+02:00
                // YYYY-MM-DDThh:mm:ss-02:00
                if (value.Length > 14 && value[10] == 'T' &&
                    (value.EndsWithInvariant("Z") ||
                     value[value.Length - 6] == '+' ||
                     value[value.Length - 6] == '-'))
                {
                    return(DateTimeSerializer.ParseShortestXsdDateTime(value));
                }
            }

            if (config.DateHandler == DateHandler.RFC1123)
            {
                // check that we have RFC1123 date:
                // ddd, dd MMM yyyy HH:mm:ss GMT
                if (value.Length == 29 && (value.EndsWithInvariant("GMT")))
                {
                    return(DateTimeSerializer.ParseRFC1123DateTime(value));
                }
            }

            return(Serializer.UnescapeString(value));
        }
Beispiel #5
0
        public static string ToShortestXsdDateTimeString(DateTime dateTime)
        {
            var config = JsConfig.GetConfig();

            dateTime = dateTime.UseConfigSpecifiedSetting();
            if (!string.IsNullOrEmpty(config.DateTimeFormat))
            {
                return(dateTime.ToString(config.DateTimeFormat, CultureInfo.InvariantCulture));
            }

            var timeOfDay    = dateTime.TimeOfDay;
            var isStartOfDay = timeOfDay.Ticks == 0;

            if (isStartOfDay && !config.SkipDateTimeConversion)
            {
                return(dateTime.ToString(ShortDateTimeFormat, CultureInfo.InvariantCulture));
            }

            var hasFractionalSecs = (timeOfDay.Milliseconds != 0) ||
                                    (timeOfDay.Ticks % TimeSpan.TicksPerMillisecond != 0);

            if (config.SkipDateTimeConversion)
            {
                if (!hasFractionalSecs)
                {
                    return(dateTime.Kind == DateTimeKind.Local
                        ? dateTime.ToString(DateTimeFormatSecondsUtcOffset, CultureInfo.InvariantCulture)
                        : dateTime.Kind == DateTimeKind.Unspecified
                        ? dateTime.ToString(DateTimeFormatSecondsNoOffset, CultureInfo.InvariantCulture)
                        : dateTime.ToStableUniversalTime().ToString(XsdDateTimeFormatSeconds, CultureInfo.InvariantCulture));
                }

                return(dateTime.Kind == DateTimeKind.Local
                    ? dateTime.ToString(DateTimeFormatTicksUtcOffset, CultureInfo.InvariantCulture)
                    : dateTime.Kind == DateTimeKind.Unspecified
                    ? dateTime.ToString(DateTimeFormatTicksNoUtcOffset, CultureInfo.InvariantCulture)
                    : PclExport.Instance.ToXsdDateTimeString(dateTime));
            }

            if (!hasFractionalSecs)
            {
                return(dateTime.Kind != DateTimeKind.Utc
                    ? dateTime.ToString(DateTimeFormatSecondsUtcOffset, CultureInfo.InvariantCulture)
                    : dateTime.ToStableUniversalTime().ToString(XsdDateTimeFormatSeconds, CultureInfo.InvariantCulture));
            }

            return(dateTime.Kind != DateTimeKind.Utc
                ? dateTime.ToString(DateTimeFormatTicksUtcOffset, CultureInfo.InvariantCulture)
                : PclExport.Instance.ToXsdDateTimeString(dateTime));
        }
Beispiel #6
0
    /// <summary>
    /// Tries the write type information.
    /// </summary>
    /// <param name="writer">The writer.</param>
    /// <param name="obj">The object.</param>
    /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
    private static bool TryWriteTypeInfo(TextWriter writer, object obj)
    {
        if (obj == null || ShouldSkipType())
        {
            return(false);
        }

        var config = JsConfig.GetConfig();

        Serializer.WriteRawString(writer, config.TypeAttr);
        writer.Write(JsWriter.MapKeySeperator);
        Serializer.WriteRawString(writer, config.TypeWriter(obj.GetType()));
        return(true);
    }
Beispiel #7
0
    /// <summary>
    /// Tries the type of the write self.
    /// </summary>
    /// <param name="writer">The writer.</param>
    /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
    private static bool TryWriteSelfType(TextWriter writer)
    {
        if (ShouldSkipType())
        {
            return(false);
        }

        var config = JsConfig.GetConfig();

        Serializer.WriteRawString(writer, config.TypeAttr);
        writer.Write(JsWriter.MapKeySeperator);
        Serializer.WriteRawString(writer, config.TypeWriter(typeof(T)));
        return(true);
    }
        public static object ObjectStringToType(ReadOnlySpan <char> strType)
        {
            var type = ExtractType(strType);

            if (type != null)
            {
                var parseFn       = Serializer.GetParseStringSpanFn(type);
                var propertyValue = parseFn(strType);
                return(propertyValue);
            }

            var config = JsConfig.GetConfig();

            if (config.ConvertObjectTypesIntoStringDictionary && !strType.IsNullOrEmpty())
            {
                var firstChar = strType[0];
                var endChar   = strType[strType.Length - 1];
                if (firstChar == JsWriter.MapStartChar && endChar == JsWriter.MapEndChar)
                {
                    var dynamicMatch = DeserializeDictionary <TSerializer> .ParseDictionary <string, object>(strType, null, v => Serializer.UnescapeString(v).ToString(), v => Serializer.UnescapeString(v).ToString());

                    if (dynamicMatch != null && dynamicMatch.Count > 0)
                    {
                        return(dynamicMatch);
                    }
                }

                if (firstChar == JsWriter.ListStartChar && endChar == JsWriter.ListEndChar)
                {
                    return(DeserializeList <List <object>, TSerializer> .ParseStringSpan(strType));
                }
            }

            var primitiveType = config.TryToParsePrimitiveTypeValues ? ParsePrimitive(strType) : null;

            if (primitiveType != null)
            {
                return(primitiveType);
            }

            if (Serializer.ObjectDeserializer != null && typeof(TSerializer) == typeof(Json.JsonTypeSerializer))
            {
                return(!strType.IsNullOrEmpty()
                    ? Serializer.ObjectDeserializer(strType)
                    : strType.Value());
            }

            return(Serializer.UnescapeString(strType).Value());
        }
Beispiel #9
0
        /// <summary>
        /// If AlwaysUseUtc is set to true then convert all DateTime to UTC. If PreserveUtc is set to true then UTC dates will not convert to local
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTime Prepare(this DateTime dateTime, bool parsedAsUtc = false)
        {
            var config = JsConfig.GetConfig();

            if (config.SkipDateTimeConversion)
            {
                return(dateTime);
            }

            if (config.AlwaysUseUtc)
            {
                return(dateTime.Kind != DateTimeKind.Utc ? dateTime.ToStableUniversalTime() : dateTime);
            }

            return(parsedAsUtc ? dateTime.ToLocalTime() : dateTime);
        }
Beispiel #10
0
        public static DateTime?ParseManual(string dateTimeStr)
        {
            var config   = JsConfig.GetConfig();
            var dateKind = config.AssumeUtc || config.AlwaysUseUtc
                ? DateTimeKind.Utc
                : DateTimeKind.Local;

            var date = ParseManual(dateTimeStr, dateKind);

            if (date == null)
            {
                return(null);
            }

            return(dateKind == DateTimeKind.Local
                ? date.Value.ToLocalTime().Prepare()
                : date);
        }
        public static FieldInfo[] GetSerializableFields(this Type type)
        {
            if (type.IsDto())
            {
                return(type.GetAllFields().Where(f =>
                                                 f.HasAttribute <DataMemberAttribute>()).ToArray());
            }

            var config = JsConfig.GetConfig();

            if (!config.IncludePublicFields)
            {
                return(TypeConstants.EmptyFieldInfoArray);
            }

            var publicFields = type.GetPublicFields();

            // else return those properties that are not decorated with IgnoreDataMember
            return(publicFields
                   .Where(prop => prop.GetAllAttributes()
                          .All(attr => !IgnoreAttributesNamed.Contains(attr.GetType().Name)))
                   .Where(prop => !config.ExcludeTypes.Contains(prop.FieldType))
                   .ToArray());
        }
Beispiel #12
0
        public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
        {
            try
            {
                if (string.IsNullOrEmpty(dateTimeStr))
                {
                    return(DateTime.MinValue);
                }

                if (dateTimeStr.StartsWith(EscapedWcfJsonPrefix, StringComparison.Ordinal) || dateTimeStr.StartsWith(WcfJsonPrefix, StringComparison.Ordinal))
                {
                    return(ParseWcfJsonDate(dateTimeStr).Prepare());
                }

                var config = JsConfig.GetConfig();
                if (dateTimeStr.Length == DefaultDateTimeFormat.Length)
                {
                    var unspecifiedDate = DateTime.Parse(dateTimeStr, CultureInfo.InvariantCulture);

                    if (config.AssumeUtc)
                    {
                        unspecifiedDate = DateTime.SpecifyKind(unspecifiedDate, DateTimeKind.Utc);
                    }

                    return(unspecifiedDate.Prepare());
                }

                if (dateTimeStr.Length == DefaultDateTimeFormatWithFraction.Length)
                {
                    var unspecifiedDate = config.AssumeUtc
                        ? DateTime.Parse(dateTimeStr, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal)
                        : DateTime.Parse(dateTimeStr, CultureInfo.InvariantCulture);

                    return(unspecifiedDate.Prepare());
                }

                var kind = DateTimeKind.Unspecified;
                switch (config.DateHandler)
                {
                case DateHandler.UnixTime:
                    if (int.TryParse(dateTimeStr, out var unixTime))
                    {
                        return(unixTime.FromUnixTime());
                    }
                    break;

                case DateHandler.UnixTimeMs:
                    if (long.TryParse(dateTimeStr, out var unixTimeMs))
                    {
                        return(unixTimeMs.FromUnixTimeMs());
                    }
                    break;

                case DateHandler.ISO8601:
                case DateHandler.ISO8601DateOnly:
                case DateHandler.ISO8601DateTime:
                    if (config.SkipDateTimeConversion)
                    {
                        dateTimeStr = RemoveUtcOffsets(dateTimeStr, out kind);
                    }
                    break;
                }

                dateTimeStr = RepairXsdTimeSeparator(dateTimeStr);

                if (dateTimeStr.Length == XsdDateTimeFormatSeconds.Length)
                {
                    return(DateTime.ParseExact(dateTimeStr, XsdDateTimeFormatSeconds, null, DateTimeStyles.AdjustToUniversal).Prepare(parsedAsUtc: true));
                }

                if (dateTimeStr.Length >= XsdDateTimeFormat3F.Length &&
                    dateTimeStr.Length <= XsdDateTimeFormat.Length &&
                    dateTimeStr.EndsWith(XsdUtcSuffix))
                {
                    var dateTime = Env.IsMono ? ParseManual(dateTimeStr) : null;
                    if (dateTime != null)
                    {
                        return(dateTime.Value);
                    }

                    return(PclExport.Instance.ParseXsdDateTimeAsUtc(dateTimeStr));
                }

                if (dateTimeStr.Length == CondensedDateTimeFormat.Length && dateTimeStr.IndexOfAny(DateTimeSeperators) == -1)
                {
                    return(DateTime.ParseExact(dateTimeStr, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None));
                }

                if (dateTimeStr.Length == ShortDateTimeFormat.Length)
                {
                    try
                    {
                        var manualDate = ParseManual(dateTimeStr);
                        if (manualDate != null)
                        {
                            return(manualDate.Value);
                        }
                    }
                    catch { }
                }

                try
                {
                    if (config.SkipDateTimeConversion)
                    {
                        return(DateTime.Parse(dateTimeStr, null,
                                              kind == DateTimeKind.Unspecified
                                ? DateTimeStyles.None
                                : kind == DateTimeKind.Local
                                    ? DateTimeStyles.AssumeLocal
                                    : DateTimeStyles.AssumeUniversal));
                    }

                    var assumeKind = config.AssumeUtc ? DateTimeStyles.AssumeUniversal : DateTimeStyles.AssumeLocal;
                    var dateTime   = DateTime.Parse(dateTimeStr, CultureInfo.InvariantCulture, assumeKind);
                    return(dateTime.Prepare());
                }
                catch (FormatException)
                {
                    var manualDate = ParseManual(dateTimeStr);
                    if (manualDate != null)
                    {
                        return(manualDate.Value);
                    }

                    throw;
                }
            }
            catch (Exception ex)
            {
                if (OnParseErrorFn != null)
                {
                    return(OnParseErrorFn(dateTimeStr, ex));
                }

                throw;
            }
        }
        public static void WriteComplexQueryStringProperties(string typeName, TextWriter writer, object instance)
        {
            var i = 0;

            if (PropertyWriters != null)
            {
                var config = JsConfig <T> .GetConfig();

                var typedInstance = (T)instance;
                var len           = PropertyWriters.Length;
                for (var index = 0; index < len; index++)
                {
                    var propertyWriter = PropertyWriters[index];
                    if (propertyWriter.shouldSerialize != null && !propertyWriter.shouldSerialize(typedInstance))
                    {
                        continue;
                    }

                    var propertyValue = instance != null?propertyWriter.GetterFn(typedInstance) : null;

                    if (propertyWriter.propertySuppressDefaultAttribute && Equals(propertyWriter.DefaultValue, propertyValue))
                    {
                        continue;
                    }

                    if ((propertyValue == null ||
                         propertyWriter.propertySuppressDefaultConfig && Equals(propertyWriter.DefaultValue, propertyValue)) &&
                        !Serializer.IncludeNullValues)
                    {
                        continue;
                    }

                    if (config.ExcludePropertyReferences != null && config.ExcludePropertyReferences.Contains(propertyWriter.propertyReferenceName))
                    {
                        continue;
                    }

                    if (i++ > 0)
                    {
                        writer.Write('&');
                    }

                    var propertyValueType = propertyValue?.GetType();
                    if (propertyValueType != null &&
                        propertyValueType.IsUserType() &&
                        !propertyValueType.HasInterface(typeof(IEnumerable)))
                    {
                        //Nested Complex Type: legal_entity[dob][day]=1
                        var prefix = $"{typeName}[{propertyWriter.GetPropertyName(config)}]";
                        var props  = propertyValueType.GetSerializableProperties();
                        for (int j = 0; j < props.Length; j++)
                        {
                            var pi     = props[j];
                            var pValue = pi.GetValue(propertyValue, TypeConstants.EmptyObjectArray);
                            if (pValue == null && !Serializer.IncludeNullValues)
                            {
                                continue;
                            }

                            if (j > 0)
                            {
                                writer.Write('&');
                            }

                            writer.Write(prefix);
                            writer.Write('[');
                            writer.Write(GetPropertyName(pi.Name, config));
                            writer.Write("]=");

                            if (pValue == null)
                            {
                                writer.Write(JsonUtils.Null);
                            }
                            else
                            {
                                JsvWriter.GetWriteFn(pValue.GetType())(writer, pValue);
                            }
                        }
                    }
                    else
                    {
                        writer.Write(typeName);
                        writer.Write('[');
                        writer.Write(propertyWriter.GetPropertyName(config));
                        writer.Write("]=");

                        if (propertyValue == null)
                        {
                            writer.Write(JsonUtils.Null);
                        }
                        else
                        {
                            propertyWriter.WriteFn(writer, propertyValue);
                        }
                    }
                }
            }
        }
Beispiel #14
0
        public static IDictionary <TKey, TValue> ParseDictionary <TKey, TValue>(
            ReadOnlySpan <char> value, Type createMapType,
            ParseStringSpanDelegate parseKeyFn, ParseStringSpanDelegate parseValueFn)
        {
            if (value.IsEmpty)
            {
                return(null);
            }

            var config = JsConfig.GetConfig();

            var tryToParseItemsAsDictionaries =
                config.ConvertObjectTypesIntoStringDictionary && typeof(TValue) == typeof(object);
            var tryToParseItemsAsPrimitiveTypes =
                config.TryToParsePrimitiveTypeValues && typeof(TValue) == typeof(object);

            var index = VerifyAndGetStartIndex(value, createMapType);

            var to = (createMapType == null)
                ? new Dictionary <TKey, TValue>()
                : (IDictionary <TKey, TValue>)createMapType.CreateInstance();

            if (JsonTypeSerializer.IsEmptyMap(value, index))
            {
                return(to);
            }

            var valueLength = value.Length;

            while (index < valueLength)
            {
                var keyValue = Serializer.EatMapKey(value, ref index);
                Serializer.EatMapKeySeperator(value, ref index);
                var elementStartIndex = index;
                var elementValue      = Serializer.EatTypeValue(value, ref index);
                if (keyValue.IsNullOrEmpty())
                {
                    continue;
                }

                TKey mapKey = (TKey)parseKeyFn(keyValue);

                if (tryToParseItemsAsDictionaries)
                {
                    Serializer.EatWhitespace(value, ref elementStartIndex);
                    if (elementStartIndex < valueLength && value[elementStartIndex] == JsWriter.MapStartChar)
                    {
                        var tmpMap = ParseDictionary <TKey, TValue>(elementValue, createMapType, parseKeyFn, parseValueFn);
                        if (tmpMap != null && tmpMap.Count > 0)
                        {
                            to[mapKey] = (TValue)tmpMap;
                        }
                    }
                    else if (elementStartIndex < valueLength && value[elementStartIndex] == JsWriter.ListStartChar)
                    {
                        to[mapKey] = (TValue)DeserializeList <List <object>, TSerializer> .ParseStringSpan(elementValue);
                    }
                    else
                    {
                        to[mapKey] = (TValue)(tryToParseItemsAsPrimitiveTypes && elementStartIndex < valueLength
                            ? DeserializeType <TSerializer> .ParsePrimitive(elementValue.Value(), value[elementStartIndex])
                            : parseValueFn(elementValue));
                    }
                }
                else
                {
                    if (tryToParseItemsAsPrimitiveTypes && elementStartIndex < valueLength)
                    {
                        Serializer.EatWhitespace(value, ref elementStartIndex);
                        to[mapKey] = (TValue)DeserializeType <TSerializer> .ParsePrimitive(elementValue.Value(), value[elementStartIndex]);
                    }
                    else
                    {
                        to[mapKey] = (TValue)parseValueFn(elementValue);
                    }
                }

                Serializer.EatItemSeperatorOrMapEndChar(value, ref index);
            }

            return(to);
        }
Beispiel #15
0
    /// <summary>
    /// Writes the string.
    /// </summary>
    /// <param name="writer">The writer.</param>
    /// <param name="value">The value.</param>
    public static void WriteString(TextWriter writer, string value)
    {
        if (value == null)
        {
            writer.Write(Null);
            return;
        }

        var config          = JsConfig.GetConfig();
        var escapeHtmlChars = config.EscapeHtmlChars;
        var escapeUnicode   = config.EscapeUnicode;

        if (!HasAnyEscapeChars(value, escapeHtmlChars))
        {
            writer.Write(QuoteChar);
            writer.Write(value);
            writer.Write(QuoteChar);
            return;
        }

        var hexSeqBuffer = new char[4];

        writer.Write(QuoteChar);

        var len = value.Length;

        for (var i = 0; i < len; i++)
        {
            char c = value[i];

            switch (c)
            {
            case LineFeedChar:
                writer.Write(EscapedLineFeed);
                continue;

            case CarriageReturnChar:
                writer.Write(EscapedCarriageReturn);
                continue;

            case TabChar:
                writer.Write(EscapedTab);
                continue;

            case QuoteChar:
                writer.Write(EscapedQuote);
                continue;

            case EscapeChar:
                writer.Write(EscapedBackslash);
                continue;

            case FormFeedChar:
                writer.Write(EscapedFormFeed);
                continue;

            case BackspaceChar:
                writer.Write(EscapedBackspace);
                continue;
            }

            if (escapeHtmlChars)
            {
                switch (c)
                {
                case '<':
                    writer.Write("\\u003c");
                    continue;

                case '>':
                    writer.Write("\\u003e");
                    continue;

                case '&':
                    writer.Write("\\u0026");
                    continue;

                case '=':
                    writer.Write("\\u003d");
                    continue;

                case '\'':
                    writer.Write("\\u0027");
                    continue;
                }
            }

            if (c.IsPrintable())
            {
                writer.Write(c);
                continue;
            }

            // http://json.org/ spec requires any control char to be escaped
            if (escapeUnicode || char.IsControl(c))
            {
                // Default, turn into a \uXXXX sequence
                IntToHex(c, hexSeqBuffer);
                writer.Write("\\u");
                writer.Write(hexSeqBuffer);
            }
            else
            {
                writer.Write(c);
            }
        }

        writer.Write(QuoteChar);
    }
Beispiel #16
0
        internal static object StringToType(ReadOnlySpan <char> strType,
                                            TypeConfig typeConfig,
                                            EmptyCtorDelegate ctorFn,
                                            KeyValuePair <string, TypeAccessor>[] typeAccessors)
        {
            var index = 0;
            var type  = typeConfig.Type;

            if (strType.IsEmpty)
            {
                return(null);
            }

            var buffer        = strType;
            var strTypeLength = strType.Length;

            //if (!Serializer.EatMapStartChar(strType, ref index))
            for (; index < strTypeLength; index++)
            {
                if (!JsonUtils.IsWhiteSpace(buffer[index]))
                {
                    break;
                }
            }                                                                                             //Whitespace inline
            if (buffer[index] != JsWriter.MapStartChar)
            {
                throw DeserializeTypeRef.CreateSerializationError(type, strType.ToString());
            }

            index++;
            if (JsonTypeSerializer.IsEmptyMap(strType, index))
            {
                return(ctorFn());
            }

            var config = JsConfig.GetConfig();

            object instance = null;
            var    lenient  = config.PropertyConvention == PropertyConvention.Lenient;

            for (; index < strTypeLength; index++)
            {
                if (!JsonUtils.IsWhiteSpace(buffer[index]))
                {
                    break;
                }
            }                                                                                             //Whitespace inline

            while (index < strTypeLength)
            {
                var propertyName = JsonTypeSerializer.UnescapeJsString(strType, JsonUtils.QuoteChar, removeQuotes: true, ref index);

                //Serializer.EatMapKeySeperator(strType, ref index);
                for (; index < strTypeLength; index++)
                {
                    if (!JsonUtils.IsWhiteSpace(buffer[index]))
                    {
                        break;
                    }
                }                                                                                             //Whitespace inline
                if (strTypeLength != index)
                {
                    index++;
                }

                var propertyValueStr = Serializer.EatValue(strType, ref index);
                var possibleTypeInfo = propertyValueStr != null && propertyValueStr.Length > 1;

                //if we already have an instance don't check type info, because then we will have a half deserialized object
                //we could throw here or just use the existing instance.
                if (instance == null && possibleTypeInfo && propertyName.Equals(typeAttr.Span, StringComparison.OrdinalIgnoreCase))
                {
                    var explicitTypeName = Serializer.ParseString(propertyValueStr);
                    var explicitType     = config.TypeFinder(explicitTypeName);

                    if (explicitType == null || explicitType.IsInterface || explicitType.IsAbstract)
                    {
                        Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr.ToString());
                    }
                    else if (!type.IsAssignableFrom(explicitType))
                    {
                        Tracer.Instance.WriteWarning("Could not assign type: " + propertyValueStr.ToString());
                    }
                    else
                    {
                        JsWriter.AssertAllowedRuntimeType(explicitType);
                        instance = explicitType.CreateInstance();
                    }

                    if (instance != null)
                    {
                        //If __type info doesn't match, ignore it.
                        if (!type.IsInstanceOfType(instance))
                        {
                            instance = null;
                        }
                        else
                        {
                            var derivedType = instance.GetType();
                            if (derivedType != type)
                            {
                                var map = DeserializeTypeRef.GetCachedTypeAccessors(derivedType, Serializer);
                                if (map != null)
                                {
                                    typeAccessors = map;
                                }
                            }
                        }
                    }

                    Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
                    continue;
                }

                if (instance == null)
                {
                    instance = ctorFn();
                }

                var typeAccessor = typeAccessors.Get(propertyName, lenient);

                var propType = possibleTypeInfo && propertyValueStr[0] == '_' ? TypeAccessor.ExtractType(Serializer, propertyValueStr) : null;
                if (propType != null)
                {
                    try
                    {
                        if (typeAccessor != null)
                        {
                            //var parseFn = Serializer.GetParseFn(propType);
                            var parseFn = JsonReader.GetParseStringSpanFn(propType);

                            var propertyValue = parseFn(propertyValueStr);
                            if (typeConfig.OnDeserializing != null)
                            {
                                propertyValue = typeConfig.OnDeserializing(instance, propertyName.ToString(), propertyValue);
                            }
                            typeAccessor.SetProperty(instance, propertyValue);
                        }

                        //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
                        for (; index < strTypeLength; index++)
                        {
                            if (!JsonUtils.IsWhiteSpace(buffer[index]))
                            {
                                break;
                            }
                        }                                                                                             //Whitespace inline
                        if (index != strTypeLength)
                        {
                            var success = buffer[index] == JsWriter.ItemSeperator || buffer[index] == JsWriter.MapEndChar;
                            index++;
                            if (success)
                            {
                                for (; index < strTypeLength; index++)
                                {
                                    if (!JsonUtils.IsWhiteSpace(buffer[index]))
                                    {
                                        break;
                                    }
                                }                                                                                             //Whitespace inline
                            }
                        }

                        continue;
                    }
                    catch (Exception e)
                    {
                        config.OnDeserializationError?.Invoke(instance, propType, propertyName.ToString(), propertyValueStr.ToString(), e);
                        if (config.ThrowOnError)
                        {
                            throw DeserializeTypeRef.GetSerializationException(propertyName.ToString(), propertyValueStr.ToString(), propType, e);
                        }
                        else
                        {
                            Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName.ToString(), propertyValueStr.ToString());
                        }
                    }
                }

                if (typeAccessor?.GetProperty != null && typeAccessor.SetProperty != null)
                {
                    try
                    {
                        var propertyValue = typeAccessor.GetProperty(propertyValueStr);
                        if (typeConfig.OnDeserializing != null)
                        {
                            propertyValue = typeConfig.OnDeserializing(instance, propertyName.ToString(), propertyValue);
                        }
                        typeAccessor.SetProperty(instance, propertyValue);
                    }
                    catch (NotSupportedException) { throw; }
                    catch (Exception e)
                    {
                        config.OnDeserializationError?.Invoke(instance, propType ?? typeAccessor.PropertyType, propertyName.ToString(), propertyValueStr.ToString(), e);
                        if (config.ThrowOnError)
                        {
                            throw DeserializeTypeRef.GetSerializationException(propertyName.ToString(), propertyValueStr.ToString(), typeAccessor.PropertyType, e);
                        }
                        else
                        {
                            Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName.ToString(), propertyValueStr.ToString());
                        }
                    }
                }
                else
                {
                    // the property is not known by the DTO
                    typeConfig.OnDeserializing?.Invoke(instance, propertyName.ToString(), propertyValueStr.ToString());
                }

                //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
                for (; index < strTypeLength; index++)
                {
                    if (!JsonUtils.IsWhiteSpace(buffer[index]))
                    {
                        break;
                    }
                }                                                                                             //Whitespace inline
                if (index != strType.Length)
                {
                    var success = buffer[index] == JsWriter.ItemSeperator || buffer[index] == JsWriter.MapEndChar;
                    index++;
                    if (success)
                    {
                        for (; index < strTypeLength; index++)
                        {
                            if (!JsonUtils.IsWhiteSpace(buffer[index]))
                            {
                                break;
                            }
                        }                                                                                             //Whitespace inline
                    }
                }
            }

            return(instance);
        }
        public static void WriteQueryString(TextWriter writer, object instance)
        {
            try
            {
                JsState.QueryStringMode = true;
                var config = JsConfig <T> .GetConfig();

                var i             = 0;
                var typedInstance = (T)instance;
                foreach (var propertyWriter in PropertyWriters)
                {
                    var propertyValue = propertyWriter.GetterFn(typedInstance);
                    if (propertyValue == null)
                    {
                        continue;
                    }

                    if (i++ > 0)
                    {
                        writer.Write('&');
                    }

                    var propertyType = propertyValue.GetType();
                    var strValue     = propertyValue as string;
                    var isEnumerable = strValue == null &&
                                       !propertyType.IsValueType &&
                                       propertyType.HasInterface(typeof(IEnumerable));

                    if (QueryStringSerializer.ComplexTypeStrategy != null)
                    {
                        var nonEnumerableUserType = !isEnumerable && (propertyType.IsUserType() || propertyType.IsInterface);
                        if (nonEnumerableUserType || propertyType.IsOrHasGenericInterfaceTypeOf(typeof(IDictionary <,>)))
                        {
                            if (QueryStringSerializer.ComplexTypeStrategy(writer, propertyWriter.GetPropertyName(config), propertyValue))
                            {
                                continue;
                            }
                        }
                    }

                    Serializer.WritePropertyName(writer, propertyWriter.GetPropertyName(config));
                    writer.Write('=');

                    if (strValue != null)
                    {
                        writer.Write(strValue.UrlEncode());
                    }
                    else if (!isEnumerable)
                    {
                        propertyWriter.WriteFn(writer, propertyValue);
                    }
                    else
                    {
                        //Trim brackets in top-level lists in QueryStrings, e.g: ?a=[1,2,3] => ?a=1,2,3
                        using (var ms = MemoryStreamFactory.GetStream())
                        {
                            var enumerableWriter = new StreamWriter(ms); //ms disposed in using
                            propertyWriter.WriteFn(enumerableWriter, propertyValue);
                            enumerableWriter.Flush();
                            var output = ms.ReadToEnd();
                            output = output.Trim(ArrayBrackets);
                            writer.Write(output);
                        }
                    }
                }
            }
            finally
            {
                JsState.QueryStringMode = false;
            }
        }
        internal static object StringToType(ReadOnlySpan <char> strType,
                                            TypeConfig typeConfig,
                                            EmptyCtorDelegate ctorFn,
                                            KeyValuePair <string, TypeAccessor>[] typeAccessors)
        {
            var index = 0;
            var type  = typeConfig.Type;

            if (strType.IsEmpty)
            {
                return(null);
            }

            //if (!Serializer.EatMapStartChar(strType, ref index))
            if (strType[index++] != JsWriter.MapStartChar)
            {
                throw DeserializeTypeRef.CreateSerializationError(type, strType.ToString());
            }

            if (JsonTypeSerializer.IsEmptyMap(strType))
            {
                return(ctorFn());
            }

            var config = JsConfig.GetConfig();

            object instance = null;
            var    lenient  = config.PropertyConvention == PropertyConvention.Lenient;

            var strTypeLength = strType.Length;

            while (index < strTypeLength)
            {
                var propertyName = Serializer.EatMapKey(strType, ref index).Trim();

                //Serializer.EatMapKeySeperator(strType, ref index);
                index++;

                var propertyValueStr = Serializer.EatValue(strType, ref index);
                var possibleTypeInfo = propertyValueStr != null && propertyValueStr.Length > 1;

                if (possibleTypeInfo && propertyName.Equals(typeAttr.Span, StringComparison.OrdinalIgnoreCase))
                {
                    var explicitTypeName = Serializer.ParseString(propertyValueStr);
                    var explicitType     = config.TypeFinder(explicitTypeName);

                    if (explicitType == null || explicitType.IsInterface || explicitType.IsAbstract)
                    {
                        Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr.ToString());
                    }
                    else if (!type.IsAssignableFrom(explicitType))
                    {
                        Tracer.Instance.WriteWarning("Could not assign type: " + propertyValueStr.ToString());
                    }
                    else
                    {
                        JsWriter.AssertAllowedRuntimeType(explicitType);
                        instance = ActivatorUtils.FastCreateInstance(explicitType);
                    }

                    if (instance != null)
                    {
                        //If __type info doesn't match, ignore it.
                        if (!type.IsInstanceOfType(instance))
                        {
                            instance = null;
                        }
                        else
                        {
                            var derivedType = instance.GetType();
                            if (derivedType != type)
                            {
                                var map = DeserializeTypeRef.GetCachedTypeAccessors(derivedType, Serializer);
                                if (map != null)
                                {
                                    typeAccessors = map;
                                }
                            }
                        }
                    }

                    //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
                    if (index != strType.Length)
                    {
                        index++;
                    }

                    continue;
                }

                if (instance == null)
                {
                    instance = ctorFn();
                }

                var typeAccessor = typeAccessors.Get(propertyName, lenient);

                var propType = possibleTypeInfo && propertyValueStr[0] == '_' ? TypeAccessor.ExtractType(Serializer, propertyValueStr) : null;
                if (propType != null)
                {
                    try
                    {
                        if (typeAccessor != null)
                        {
                            var parseFn       = Serializer.GetParseStringSpanFn(propType);
                            var propertyValue = parseFn(propertyValueStr);
                            if (typeConfig.OnDeserializing != null)
                            {
                                propertyValue = typeConfig.OnDeserializing(instance, propertyName.ToString(), propertyValue);
                            }
                            typeAccessor.SetProperty(instance, propertyValue);
                        }

                        //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
                        if (index != strType.Length)
                        {
                            index++;
                        }

                        continue;
                    }
                    catch (Exception e)
                    {
                        config.OnDeserializationError?.Invoke(instance, propType, propertyName.ToString(), propertyValueStr.ToString(), e);
                        if (config.ThrowOnError)
                        {
                            throw DeserializeTypeRef.GetSerializationException(propertyName.ToString(), propertyValueStr.ToString(), propType, e);
                        }
                        else
                        {
                            Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName.ToString(), propertyValueStr.ToString());
                        }
                    }
                }

                if (typeAccessor?.GetProperty != null && typeAccessor.SetProperty != null)
                {
                    try
                    {
                        var propertyValue = typeAccessor.GetProperty(propertyValueStr);
                        if (typeConfig.OnDeserializing != null)
                        {
                            propertyValue = typeConfig.OnDeserializing(instance, propertyName.ToString(), propertyValue);
                        }
                        typeAccessor.SetProperty(instance, propertyValue);
                    }
                    catch (NotSupportedException) { throw; }
                    catch (Exception e)
                    {
                        config.OnDeserializationError?.Invoke(instance, propType ?? typeAccessor.PropertyType, propertyName.ToString(), propertyValueStr.ToString(), e);
                        if (config.ThrowOnError)
                        {
                            throw DeserializeTypeRef.GetSerializationException(propertyName.ToString(), propertyValueStr.ToString(), propType, e);
                        }
                        else
                        {
                            Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName.ToString(), propertyValueStr.ToString());
                        }
                    }
                }
                else
                {
                    // the property is not known by the DTO
                    typeConfig.OnDeserializing?.Invoke(instance, propertyName.ToString(), propertyValueStr.ToString());
                }

                //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
                if (index != strType.Length)
                {
                    index++;
                }
            }

            return(instance);
        }
        public static object ParseNumber(this ReadOnlySpan <char> value, bool bestFit)
        {
            if (value.Length == 1)
            {
                int singleDigit = value[0];
                if (singleDigit >= 48 || singleDigit <= 57) // 0 - 9
                {
                    var result = singleDigit - 48;
                    if (bestFit)
                    {
                        return((byte)result);
                    }
                    return(result);
                }
            }

            var config = JsConfig.GetConfig();

            // Parse as decimal
            var acceptDecimal = config.ParsePrimitiveFloatingPointTypes.Has(ParseAsType.Decimal);
            var isDecimal     = value.TryParseDecimal(out decimal decimalValue);

            // Check if the number is an Primitive Integer type given that we have a decimal
            if (isDecimal && decimalValue == decimal.Truncate(decimalValue))
            {
                // Value is a whole number
                var parseAs = config.ParsePrimitiveIntegerTypes;
                if (parseAs.Has(ParseAsType.Byte) && decimalValue <= byte.MaxValue && decimalValue >= byte.MinValue)
                {
                    return((byte)decimalValue);
                }
                if (parseAs.Has(ParseAsType.SByte) && decimalValue <= sbyte.MaxValue && decimalValue >= sbyte.MinValue)
                {
                    return((sbyte)decimalValue);
                }
                if (parseAs.Has(ParseAsType.Int16) && decimalValue <= Int16.MaxValue && decimalValue >= Int16.MinValue)
                {
                    return((Int16)decimalValue);
                }
                if (parseAs.Has(ParseAsType.UInt16) && decimalValue <= UInt16.MaxValue && decimalValue >= UInt16.MinValue)
                {
                    return((UInt16)decimalValue);
                }
                if (parseAs.Has(ParseAsType.Int32) && decimalValue <= Int32.MaxValue && decimalValue >= Int32.MinValue)
                {
                    return((Int32)decimalValue);
                }
                if (parseAs.Has(ParseAsType.UInt32) && decimalValue <= UInt32.MaxValue && decimalValue >= UInt32.MinValue)
                {
                    return((UInt32)decimalValue);
                }
                if (parseAs.Has(ParseAsType.Int64) && decimalValue <= Int64.MaxValue && decimalValue >= Int64.MinValue)
                {
                    return((Int64)decimalValue);
                }
                if (parseAs.Has(ParseAsType.UInt64) && decimalValue <= UInt64.MaxValue && decimalValue >= UInt64.MinValue)
                {
                    return((UInt64)decimalValue);
                }
                return(decimalValue);
            }

            // Value is a floating point number

            // Return a decimal if the user accepts a decimal
            if (isDecimal && acceptDecimal)
            {
                return(decimalValue);
            }

            var acceptFloat = config.ParsePrimitiveFloatingPointTypes.HasFlag(ParseAsType.Single);
            var isFloat     = value.TryParseFloat(out float floatValue);

            if (acceptFloat && isFloat)
            {
                return(floatValue);
            }

            var acceptDouble = config.ParsePrimitiveFloatingPointTypes.HasFlag(ParseAsType.Double);
            var isDouble     = value.TryParseDouble(out double doubleValue);

            if (acceptDouble && isDouble)
            {
                return(doubleValue);
            }

            if (isDecimal)
            {
                return(decimalValue);
            }
            if (isFloat)
            {
                return(floatValue);
            }
            if (isDouble)
            {
                return(doubleValue);
            }

            return(null);
        }
        public static void WriteProperties(TextWriter writer, object instance)
        {
            if (instance == null)
            {
                writer.Write(JsWriter.EmptyMap);
                return;
            }

            var valueType = instance.GetType();

            if (PropertyWriters != null && valueType != typeof(T) && !typeof(T).IsAbstract)
            {
                WriteLateboundProperties(writer, instance, valueType);
                return;
            }

            if (typeof(TSerializer) == typeof(JsonTypeSerializer) && JsState.WritingKeyCount > 0)
            {
                writer.Write(JsWriter.QuoteChar);
            }

            writer.Write(JsWriter.MapStartChar);

            var i = 0;

            if (WriteTypeInfo != null || JsState.IsWritingDynamic)
            {
                if (JsConfig.PreferInterfaces && TryWriteSelfType(writer))
                {
                    i++;
                }
                else if (TryWriteTypeInfo(writer, instance))
                {
                    i++;
                }
                JsState.IsWritingDynamic = false;
            }

            if (PropertyWriters != null)
            {
                var config = JsConfig <T> .GetConfig();

                var typedInstance = (T)instance;
                var len           = PropertyWriters.Length;
                for (int index = 0; index < len; index++)
                {
                    var propertyWriter = PropertyWriters[index];

                    if (propertyWriter.shouldSerialize?.Invoke(typedInstance) == false)
                    {
                        continue;
                    }

                    var dontSkipDefault = false;
                    if (propertyWriter.shouldSerializeDynamic != null)
                    {
                        var shouldSerialize = propertyWriter.shouldSerializeDynamic(typedInstance, propertyWriter.GetPropertyName(config));
                        if (shouldSerialize.HasValue)
                        {
                            if (shouldSerialize.Value)
                            {
                                dontSkipDefault = true;
                            }
                            else
                            {
                                continue;
                            }
                        }
                    }

                    var propertyValue = propertyWriter.GetterFn(typedInstance);

                    if (!dontSkipDefault)
                    {
                        if (!propertyWriter.ShouldWriteProperty(propertyValue, config))
                        {
                            continue;
                        }

                        if (config.ExcludePropertyReferences?.Contains(propertyWriter.propertyReferenceName) == true)
                        {
                            continue;
                        }
                    }

                    if (i++ > 0)
                    {
                        writer.Write(JsWriter.ItemSeperator);
                    }

                    Serializer.WritePropertyName(writer, propertyWriter.GetPropertyName(config));
                    writer.Write(JsWriter.MapKeySeperator);

                    if (typeof(TSerializer) == typeof(JsonTypeSerializer))
                    {
                        JsState.IsWritingValue = true;
                    }
                    try
                    {
                        if (propertyValue == null)
                        {
                            writer.Write(JsonUtils.Null);
                        }
                        else
                        {
                            propertyWriter.WriteFn(writer, propertyValue);
                        }
                    }
                    finally
                    {
                        if (typeof(TSerializer) == typeof(JsonTypeSerializer))
                        {
                            JsState.IsWritingValue = false;
                        }
                    }
                }
            }

            writer.Write(JsWriter.MapEndChar);

            if (typeof(TSerializer) == typeof(JsonTypeSerializer) && JsState.WritingKeyCount > 0)
            {
                writer.Write(JsWriter.QuoteChar);
            }
        }