Reflection and Lazy Evaluation FTW

For when you have a gigabyte of JSON data to process:

    public static class LazyJson
    {
        public static IEnumerable<T> DeserializeEnumerable<T>(Stream inputStream)
            where T: class, new()
        {
            var type = typeof(T);
            var properties = type.GetMembers(BindingFlags.Instance | BindingFlags.Public)
                .OfType<PropertyInfo>()
                .Where(pi => !pi.GetCustomAttributes(typeof(JsonIgnoreAttribute), true)
                                .OfType<JsonIgnoreAttribute>().Any())
                .ToDictionary(pi =>
                    {
                        var jsonProperty = 
                            pi.GetCustomAttributes(typeof(JsonPropertyAttribute), true)
                            .OfType<JsonPropertyAttribute>().FirstOrDefault();
                        return jsonProperty != null ? jsonProperty.PropertyName : pi.Name;
                    });
 
            using (var sr = new StreamReader(inputStream))
            using (var jr = new JsonTextReader(sr))
            {
                jr.DateParseHandling = DateParseHandling.DateTime;
 
                T currentObject = null;
                PropertyInfo currentProperty = null;
 
                while (jr.Read())
                {
                    switch (jr.TokenType)
                    {
                        case JsonToken.StartObject:
                            currentObject = new T();
                            break;
                        case JsonToken.PropertyName:
                            currentProperty = properties[Convert.ToString(jr.Value)];
                            break;
                        case JsonToken.String:
                            currentProperty.SetValue(currentObject, 
                                Convert.ChangeType(jr.Value, currentProperty.PropertyType), null);
                            break;
                        case JsonToken.Integer:
                            currentProperty.SetValue(currentObject, 
                                Convert.ChangeType(jr.Value, currentProperty.PropertyType), null);
                            break;
                        case JsonToken.Date:
                            currentProperty.SetValue(currentObject, jr.Value, null);
                            break;
                        case JsonToken.EndObject:
                            yield return currentObject;
                            break;
                    }
                }
            }
        }
    }

One thought on “Reflection and Lazy Evaluation FTW”

  1. Amazing how much neat stuff they’ve added to that language in 1 decade.

Comments are closed.