Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialize anonymous types #53

Open
NathanBaulch opened this issue Apr 8, 2014 · 0 comments
Open

Deserialize anonymous types #53

NathanBaulch opened this issue Apr 8, 2014 · 0 comments

Comments

@NathanBaulch
Copy link

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);
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant