コード例 #1
0
        /// <summary>
        /// Read the specified element
        /// </summary>
        public object ReadElementUtil(JsonReader r, Type t, JsonSerializationContext context)
        {
            var nonGenericT = t.StripGeneric();
            var classifier  = this.GetClassifier(nonGenericT);

            switch (r.TokenType)
            {
            case JsonToken.StartObject:
            {
                var  formatter = this.GetFormatter(nonGenericT);
                bool isList    = typeof(IList).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo());
                // Classifier???
                if (classifier == null || !isList)
                {
                    if (isList)
                    {
                        var retVal = Activator.CreateInstance(t) as IList;
                        retVal.Add(formatter.Deserialize(r, t, context));
                        return(retVal);
                    }
                    else
                    {
                        return(formatter.Deserialize(r, t, context));
                    }
                }
                else
                {
                    // Classifier each of these properties aren't real properties, rather they are classified things
                    int depth = r.Depth;
                    Dictionary <String, Object> values = new Dictionary <string, object>();
                    while (r.Read() && !(r.TokenType == JsonToken.EndObject && r.Depth == depth))
                    {
                        // Classifier
                        if (r.TokenType != JsonToken.PropertyName)
                        {
                            throw new JsonException($"Expected PropertyName token got {r.TokenType}");
                        }
                        string propertyName = (String)r.Value;
                        r.Read();         // Read proeprty name
                        values.Add(propertyName, this.ReadElementUtil(r, r.TokenType == JsonToken.StartObject ? nonGenericT : t, new JsonSerializationContext(propertyName, this, values, context)));
                    }
                    return(classifier.Compose(values, t));
                }
            }

            // Array read, we want to re-call the specified parse
            case JsonToken.StartArray:
            {
                if (!typeof(IList).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo()))
                {
                    throw new JsonSerializationException($"{t} does not implement IList at {r.Path}");
                }
                int depth        = r.Depth;
                var listInstance = Activator.CreateInstance(t) as IList;
                while (r.Read() && !(r.TokenType == JsonToken.EndArray && r.Depth == depth))
                {
                    listInstance.Add(this.ReadElementUtil(r, nonGenericT, context));
                }
                return(listInstance);
            }

            case JsonToken.Null:
            case JsonToken.Boolean:
            case JsonToken.Bytes:
            case JsonToken.Float:
            case JsonToken.Date:
            case JsonToken.Integer:
            case JsonToken.String:
                if (typeof(IdentifiedData).GetTypeInfo().IsAssignableFrom(nonGenericT.GetTypeInfo()))     // Complex object
                {
                    var formatter = this.GetFormatter(nonGenericT);
                    return(formatter.FromSimpleValue(r.Value));
                }
                else
                {
                    // Not a simple value attribute so let's just handle it as normal
                    switch (r.TokenType)
                    {
                    case JsonToken.Null:
                        return(null);

                    case JsonToken.Boolean:
                    case JsonToken.Bytes:
                        return(r.Value);

                    case JsonToken.Float:
                        if (t.StripNullable() == typeof(Decimal))
                        {
                            return(Convert.ToDecimal(r.Value));
                        }
                        else if (t.StripNullable() == typeof(Int32))
                        {
                            return(Convert.ToInt32(r.Value));
                        }
                        else
                        {
                            return((Double)r.Value);
                        }

                    case JsonToken.Date:
                        t = t.StripNullable();
                        if (t == typeof(DateTime))
                        {
                            return((DateTime)r.Value);
                        }
                        else if (t == typeof(String))
                        {
                            return(((DateTime)r.Value).ToString("o"));
                        }
                        else
                        {
                            return(new DateTimeOffset((DateTime)r.Value));
                        }

                    case JsonToken.Integer:
                        t = t.StripNullable();
                        if (t.GetTypeInfo().IsEnum)
                        {
                            return(Enum.ToObject(t, r.Value));
                        }
                        return(Convert.ChangeType(r.Value, t));

                    case JsonToken.String:
                        if (String.IsNullOrEmpty((string)r.Value))
                        {
                            return(null);
                        }
                        else if (t.StripNullable() == typeof(Guid))
                        {
                            return(Guid.Parse((string)r.Value));
                        }
                        else if (t.StripNullable() == typeof(Int32))
                        {
                            return("NaN".Equals(r.Value) ? 0 : Int32.Parse((String)r.Value));
                        }
                        else if (t.StripNullable() == typeof(Decimal))
                        {
                            return(Decimal.Parse((String)r.Value));
                        }
                        else if (t.StripNullable() == typeof(byte[]))
                        {
                            return(Convert.FromBase64String((String)r.Value));
                        }
                        else
                        {
                            return(r.Value);
                        }

                    default:
                        return(r.Value);
                    }
                }

            default:
                throw new JsonSerializationException("Invalid serialization");
            }
        }
コード例 #2
0
        /// <summary>
        /// De-serialize the specified object from the class
        /// </summary>
        public Object Deserialize(JsonReader r, Type asType, JsonSerializationContext context)
        {
            var retVal = new Object();

            if (!asType.GetTypeInfo().IsAbstract)
            {
                retVal = Activator.CreateInstance(asType);
            }

            int depth      = r.TokenType == JsonToken.StartObject ? r.Depth : r.Depth - 1; // current depth
            var properties = GetPropertyInfo(asType);

            // We will parse this until we can no longer parse
            while (r.Read())
            {
                switch (r.TokenType)
                {
                // The current reader is at an end of object
                case JsonToken.EndObject:
                    if (depth == r.Depth)
                    {
                        return(retVal);
                    }
                    else
                    {
                        throw new JsonSerializationException("JSON in invalid state");
                    }

                // Current reader is at a property name
                case JsonToken.PropertyName:
                    switch ((String)r.Value)
                    {
                    case "$type":
                        var xsiType = s_binder.BindToType(asType.GetTypeInfo().Assembly.FullName, r.ReadAsString());
                        if (xsiType != asType)
                        {
                            var fmtr    = context.JsonContext.GetFormatter(xsiType);
                            var nRetVal = fmtr.Deserialize(r, xsiType, context);
                            nRetVal.CopyObjectData(retVal);
                            return(nRetVal);
                        }
                        break;

                    case "$ref":         // TODO: lookup reference
                        break;

                    default:
                        string       propertyName = r.Value as String;
                        PropertyInfo propertyInfo = null;
                        if (properties.TryGetValue(propertyName, out propertyInfo))
                        {
                            // Read next token
                            r.Read();
                            var instance = context.JsonContext.ReadElementUtil(r, propertyInfo.PropertyType, new JsonSerializationContext(propertyName, context.JsonContext, retVal, context));
                            if (!(instance == null || (instance as IList)?.Count == 0))
                            {
                                propertyInfo.SetValue(retVal, instance);
                            }
                        }
                        else
                        {
                            r.Skip();
                        }
                        break;
                    }
                    break;
                }
            }
            return(retVal);
        }
コード例 #3
0
 /// <summary>
 /// Creates a new JSON serialization context
 /// </summary>
 public JsonSerializationContext(String propertyName, JsonViewModelSerializer context, Object instance, JsonSerializationContext parent) : base(propertyName, context, instance, parent)
 {
 }
コード例 #4
0
        /// <summary>
        /// Serialize the specified object to the wire
        /// </summary>
        public void Serialize(JsonWriter w, IdentifiedData o, JsonSerializationContext context)
        {
            if (o == null)
            {
                throw new ArgumentNullException(nameof(o));
            }

            // For each item in the property ...
            bool loadedProperties = false;

            // Iterate properties
            foreach (var propertyInfo in o.GetType().GetRuntimeProperties())
            {
                // Get the property name
                var propertyName = GetPropertyName(propertyInfo);
                if (propertyName == null || propertyName.StartsWith("$")) // Skip internal property names
                {
                    continue;
                }

                // Serialization decision
                if (!context.ShouldSerialize(propertyName))
                {
                    continue;
                }

                // Get the property
                var value = propertyInfo.GetValue(o);

                // Null ,do we want to force load?
                if (value == null || (value as IList)?.Count == 0)
                {
                    var tkey = o.Key.HasValue ? o.Key.Value : Guid.NewGuid();
                    if (context.ShouldForceLoad(propertyName, tkey))
                    {
                        if (value is IList && !propertyInfo.PropertyType.IsArray)
                        {
                            if (o.Key.HasValue)
                            {
                                value = context.JsonContext.LoadCollection(propertyInfo.PropertyType, (Guid)o.Key);
                            }
                            propertyInfo.SetValue(o, value);
                            loadedProperties = (value as IList).Count > 0;
                        }
                        else
                        {
                            var keyPropertyRef = propertyInfo.GetCustomAttribute <SerializationReferenceAttribute>();
                            if (keyPropertyRef != null)
                            {
                                var keyProperty = o.GetType().GetRuntimeProperty(keyPropertyRef.RedirectProperty);
                                var key         = keyProperty.GetValue(o);
                                if (key != null)
                                {
                                    value = context.JsonContext.LoadRelated(propertyInfo.PropertyType, (Guid)key);
                                    propertyInfo.SetValue(o, value);
                                    loadedProperties = value != null;
                                }
                            }
                        }
                    }
                    else
                    {
                        continue;
                    }
                }

                // TODO: Classifier
                context.JsonContext.WritePropertyUtil(w, propertyName, value, context);
            }

            // Loaded something, let's cache it
            if (loadedProperties && o.Key.HasValue && ((o as IVersionedEntity) == null || (o as IVersionedEntity)?.VersionKey.HasValue == true) &&
                o.LoadState != LoadState.New)
            {
                (ApplicationServiceContext.Current.GetService(typeof(IDataCachingService)) as IDataCachingService).Add(o);
            }
        }