Exemple #1
0
        public static SerializerMap GetSerializerMap(Type type)
        {
            SerializerMap result;

            if ((result = GlobalMaps.FirstOrDefault(m => m.ObjectType == type)) == null)
            {
                lock (_GlobalMaps)
                {
                    if ((result = _GlobalMaps.FirstOrDefault(m => m.ObjectType == type)) == null)
                    {
                        var l = _GlobalMaps.Length;
                        Array.Resize(ref _GlobalMaps, l + 1);

                        _GlobalMaps[l] = result = new SerializerMap(type);

                        foreach (var t in result.Members
                                 .Select(v => v.ValueType)
                                 .Where(t => t != typeof(string) &&
                                        (t.IsClass || (t.IsValueType && !t.IsPrimitive)))
                                 .Except(GlobalMaps.Select(m => m.ObjectType))
                                 .Distinct())
                        {
                            GetSerializerMap(t);
                        }
                    }
                }
            }

            return(result);
        }
Exemple #2
0
        public void Serialize(object obj, SerializationOptions options)
        {
            if (obj == null)
            {
                Write("null");
                return;
            }

            var objectType = obj.GetType();

            var converter = options?.Converters?.FirstOrDefault(c => c.GetConvertingType() == objectType);

            if (converter != null)
            {
                Serialize(converter.Serializer(obj), options);
                return;
            }

            Func <object, string> cnv;
            Type genericType;

            if (!SerializerCache.TryGetValue(objectType, out cnv))
            {
                var strConverter = new Func <object, string>(
                    s =>
                {
                    var t = (string)s;
                    var r = "\"";

                    for (var i = 0; i < t.Length; i++)
                    {
                        var c = t[i];

                        r += c == '\r' ? "\\r" :
                             c == '\n' ? "\\n" :
                             c == '\t' ? "\\t" :
                             c == '"' ? "\\\"" :
                             c == '\\' ? "\\\\" :
                             c == '/' ? "\\/" :
                             c == '\b' ? "\\b" :
                             c == '\f' ? "\\f" :
                             c.ToString();
                    }

                    r += "\"";

                    return(r);
                });

                if (obj is string)
                {
                    cnv = strConverter;
                }
                else if (obj is IEnumerable)
                {
                    Write(obj is IDictionary ? "{" : "[");

                    var first = true;

                    foreach (var o in (IEnumerable)obj)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            Write(",");
                        }

                        Serialize(o, options);
                    }

                    Write(obj is IDictionary ? "}" : "]");
                    return;
                }
                else if (obj is bool || obj is bool?)
                {
                    cnv = b => (bool)b ? "true" : "false";
                }
                else if (obj is int || obj is int? ||
                         obj is short || obj is short? ||
                         obj is long || obj is long? ||
                         obj is uint || obj is uint? ||
                         obj is ushort || obj is ushort? ||
                         obj is ulong || obj is ulong? ||
                         obj is float || obj is float? ||
                         obj is double || obj is double? ||
                         obj is decimal || obj is decimal?||
                         obj is float || obj is uint? ||
                         obj is ushort || obj is ushort? ||
                         obj is ulong || obj is ulong?)
                {
                    cnv = n => string.Format(CultureInfo.InvariantCulture, "{0}", n);
                }
                else if (obj is DateTime || obj is DateTime?)
                {
                    cnv = d => strConverter(((DateTime)d).ToString(CultureInfo.InvariantCulture));
                }
                else if (obj is DateTimeOffset || obj is DateTimeOffset?)
                {
                    cnv = d => strConverter(((DateTimeOffset)d).ToString(CultureInfo.InvariantCulture));
                }
                else if (obj is TimeSpan || obj is TimeSpan?)
                {
                    cnv = d => strConverter(((TimeSpan)d).ToString("c"));
                }
                else if (obj is Enum)
                {
                    cnv = e => ((int)e).ToString(CultureInfo.InvariantCulture);
                }
                else if (objectType.IsGenericType &&
                         objectType.GenericTypeArguments.Length == 2 &&
                         objectType == (genericType = typeof(KeyValuePair <,>).MakeGenericType(objectType.GenericTypeArguments)))
                {
                    var k = genericType.GetProperty("Key").GetValue(obj).ToString();
                    var v = genericType.GetProperty("Value").GetValue(obj);

                    Write(strConverter(k));
                    Write(":");
                    Serialize(v, options);
                    return;
                }
                else if (!objectType.IsPrimitive)
                {
                    Write("{");

                    var first = true;

                    foreach (var m in SerializerMap.GetSerializerMap(objectType)
                             .Members)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            Write(",");
                        }

                        if (objectType == typeof(DictionaryEntry))
                        {
                            var d = (DictionaryEntry)obj;
                            Write(strConverter(d.Key.ToString()));
                            Write(":");
                            Serialize(d.Value, options);
                        }
                        else
                        {
                            string memberName = m.Name;
                            if (options?.PropertyNameTransform != null)
                            {
                                memberName = options?.PropertyNameTransform.Transform(m.Name);
                            }
                            Write(strConverter(memberName));
                            Write(":");

                            try
                            {
                                Serialize(m.GetValue(obj), options);
                            }
                            catch (TargetInvocationException)
                            {
                                Serialize(null, options);
                            }
                        }
                    }

                    Write("}");
                    return;
                }

                SerializerCache[objectType] =
                    cnv ??
                    throw new InvalidOperationException(
                              "Unknown object type! " + objectType.FullName);;
            }

            Write(cnv(obj));
        }
Exemple #3
0
        public object FromJson(Type type)
        {
            object result;

            SkipWhite();

            if (NextChar == '{')
            {
                ReadNext();
                SkipWhite();

                if (type.IsValueType)
                {
                    throw new FormatException("Unexpected type!");
                }

                result = Activator.CreateInstance(type);

                var nameType = result is IDictionary ?
                               type.GenericTypeArguments[0] :
                               typeof(string);

                var valueType = result is IDictionary ?
                                type.GenericTypeArguments[1] :
                                null;

                var mIndex = 0;

                while (NextChar != '}')
                {
                    var name = (string)FromJson(nameType);

                    SkipWhite();
                    Match(":");

                    var map = SerializerMap.GetSerializerMap(type);

                    MemberAccessor field = null;

                    if (valueType == null)
                    {
                        for (var i = mIndex; i < map.Members.Length; i++)
                        {
                            string memberName = map.Members[i].Name;
                            if (PropertyNameTransform != null)
                            {
                                memberName = PropertyNameTransform.Transform(memberName);
                            }
                            if (memberName == name)
                            {
                                field = map.Members[i];
                                break;
                            }
                        }
                    }

                    var fieldType = field == null ? valueType : field.ValueType;

                    var value = FromJson(fieldType);

                    if (field != null)
                    {
                        field.SetValue(result, value);
                    }
                    else
                    {
                        ((IDictionary)result).Add(name, value);
                    }

                    SkipWhite();

                    if (NextChar == ',')
                    {
                        ReadNext();
                        SkipWhite();
                        continue;
                    }

                    break;
                }

                Match("}");

                return(result);
            }

            if (NextChar == '[')
            {
                ReadNext();
                SkipWhite();

                var elementType =
                    type.IsArray ?
                    type.GetElementType() :
                    type.IsGenericType ?
                    type.GenericTypeArguments[0] :
                    typeof(object);

                var list =
                    type.IsArray ?
                    new ArrayList() :
                    (IList)Activator.CreateInstance(type);

                while (NextChar != ']')
                {
                    var item = FromJson(elementType);

                    list.Add(item);

                    SkipWhite();

                    if (NextChar == ',')
                    {
                        ReadNext();
                        SkipWhite();
                        continue;
                    }

                    break;
                }

                Match("]");

                if (list is ArrayList)
                {
                    return(((ArrayList)list).ToArray(elementType));
                }
                else
                {
                    return(list);
                }
            }

            if (NextChar == '"')
            {
                ReadNext();

                while (!EndOfStream && NextChar != '"')
                {
                    if (NextChar == '\\')
                    {
                        ReadNext();

                        switch (NextChar)
                        {
                        case 'b':
                        case 't':
                        case 'n':
                        case 'f':
                        case 'r':
                            text.Append(EscapeMap[NextChar]);
                            break;

                        case 'u':
                            ReadNext();

                            var unicode = "";

                            while (unicode.Length < 4 && IsHexDigit)
                            {
                                unicode += NextChar;
                                ReadNext();
                            }

                            text.Append(char.ConvertFromUtf32(int.Parse("0x" + unicode)));
                            continue;

                        default:
                            text.Append(NextChar);
                            break;
                        }
                    }
                    else
                    {
                        text.Append(NextChar);
                    }

                    ReadNext();
                }

                SkipWhite();
                Match("\"");

                result = text.ToString();

                text.Clear();

                var converter = Converters?.FirstOrDefault(c => c.GetConvertingType() == type);

                if (converter != null)
                {
                    return(converter.Deserializer((string)result));
                }

                if (type == typeof(DateTime) ||
                    type == typeof(DateTime?))
                {
                    return(DateTime.Parse((string)result, CultureInfo.InvariantCulture));
                }

                if (type == typeof(DateTimeOffset) ||
                    type == typeof(DateTimeOffset?))
                {
                    return(DateTimeOffset.Parse((string)result, CultureInfo.InvariantCulture));
                }

                if (type == typeof(TimeSpan) ||
                    type == typeof(TimeSpan?))
                {
                    return(TimeSpan.Parse((string)result, CultureInfo.InvariantCulture));
                }

                return(result);
            }
            else if (NextChar == 't')
            {
                Match("true");
                return(true);
            }
            else if (NextChar == 'f')
            {
                Match("false");
                return(false);
            }
            else if (NextChar == 'n')
            {
                Match("null");

                if (!(type.IsClass ||
                      Nullable.GetUnderlyingType(type) != null))
                {
                    throw new InvalidDataException("Type " + type.Name + "'s value cannot be null!");
                }

                return(null);
            }
            else if (NextChar == '-' || IsDigit)
            {
                if (NextChar == '-')
                {
                    text.Append('-');
                    ReadNext();
                }

                if (NextChar == '0')
                {
                    text.Append('0');
                    ReadNext();
                }
                else if (IsDigit)
                {
                    do
                    {
                        text.Append(NextChar);
                        ReadNext();
                    }while (IsDigit);
                }
                else
                {
                    throw new FormatException("Digit expected!");
                }

                if (NextChar == '.')
                {
                    text.Append('.');
                    ReadNext();

                    while (IsDigit)
                    {
                        text.Append(NextChar);
                        ReadNext();
                    }
                }

                if (NextChar == 'e' || NextChar == 'E')
                {
                    text.Append('e');
                    ReadNext();

                    if (NextChar == '+' || NextChar == '-')
                    {
                        text.Append(NextChar);
                        ReadNext();
                    }

                    while (IsDigit)
                    {
                        text.Append(NextChar);
                        ReadNext();
                    }
                }

                var t = text.ToString();
                text.Clear();

                var inv = CultureInfo.InvariantCulture;

                if (type.IsEnum ||
                    type == typeof(int) ||
                    type == typeof(int?))
                {
                    return(int.Parse(t, inv));
                }

                if (type == typeof(long) ||
                    type == typeof(long?))
                {
                    return(long.Parse(t, inv));
                }

                return(double.Parse(t, inv));
            }

            throw new FormatException("Unexpected character! " + NextChar);
        }