Skip to content

Deserialize anonymous typesΒ #53

@NathanBaulch

Description

@NathanBaulch

I've written a serializer strategy that supports deserializing anonymous types and thought I'd share the code here for anyone who's interested. Anonymous types are immutable, with all property values passed in via constructor parameters. The strategy detects the absence of a default (parameterless) public constructor and builds the necessary cached ConstructorDelegate to create and populate the output object.

public static class SimpleJsonExt
{
    public static T DeserializeAnonymousObject<T>(string json, T prototype)
    {
        return SimpleJson.SimpleJson.DeserializeObject<T>(json, new Strategy());
    }

    private class Strategy : PocoJsonSerializerStrategy
    {
        private readonly IDictionary<Type, KeyValuePair<ParameterInfo[], ReflectionUtils.ConstructorDelegate>> _ctorCache = new ReflectionUtils.ThreadSafeDictionary<Type, KeyValuePair<ParameterInfo[], ReflectionUtils.ConstructorDelegate>>(CreateConstructorDelegate);

        private static KeyValuePair<ParameterInfo[], ReflectionUtils.ConstructorDelegate> CreateConstructorDelegate(Type key)
        {
            var ctors = key.GetConstructors();
            if (ctors.Length == 1)
            {
                var ctor = ctors[0];
                var parms = ctor.GetParameters();
                if (parms.Length > 0)
                {
                    return new KeyValuePair<ParameterInfo[], ReflectionUtils.ConstructorDelegate>(parms, ReflectionUtils.GetConstructor(ctor));
                }
            }
            return default(KeyValuePair<ParameterInfo[], ReflectionUtils.ConstructorDelegate>);
        }

        public override object DeserializeObject(object value, Type type)
        {
            var dict = value as IDictionary<string, object>;
            if (dict != null)
            {
                var ctor = _ctorCache[type];
                if (ctor.Key != null)
                {
                    object arg;
                    return ctor.Value(ctor.Key.Select(param => DeserializeObject(dict.TryGetValue(param.Name, out arg) ? arg : null, param.ParameterType)).ToArray());
                }
            }
            return base.DeserializeObject(value, type);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions