Esempio n. 1
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (contractResolver != serializer.ContractResolver)
            {
                throw new InvalidOperationException("Inconsistent contract resolvers");
            }
            Type         elementType;
            JsonProperty keyProperty;

            if (!CanConvert(contractResolver, objectType, out elementType, out keyProperty))
            {
                throw new JsonSerializationException(string.Format("Invalid input type {0}", objectType));
            }

            if (reader.TokenType == JsonToken.Null)
            {
                return(existingValue);
            }

            var list = existingValue as IList;

            if (list == null || list.Count == 0)
            {
                list = list ?? (IList)contractResolver.ResolveContract(objectType).DefaultCreator();
                serializer.Populate(reader, list);
            }
            else
            {
                var jArray   = JArray.Load(reader);
                var comparer = new KeyedListMergeComparer();
                var lookup   = jArray.ToLookup(i => i[keyProperty.PropertyName].ToObject(keyProperty.PropertyType, serializer), comparer);
                var done     = new HashSet <JToken>();
                foreach (var item in list)
                {
                    var key         = keyProperty.ValueProvider.GetValue(item);
                    var replacement = lookup[key].Where(v => !done.Contains(v)).FirstOrDefault();
                    if (replacement != null)
                    {
                        using (var subReader = replacement.CreateReader())
                            serializer.Populate(subReader, item);
                        done.Add(replacement);
                    }
                }
                // Populate the NEW items into the list.
                if (done.Count < jArray.Count)
                {
                    foreach (var item in jArray.Where(i => !done.Contains(i)))
                    {
                        list.Add(item.ToObject(elementType, serializer));
                    }
                }
            }
            return(list);
        }
    object ReadJsonGeneric <T>(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer, JsonProperty keyProperty)
    {
        var list = existingValue as IList <T>;

        if (list == null || list.Count == 0)
        {
            list = list ?? (IList <T>)contractResolver.ResolveContract(objectType).DefaultCreator();
            serializer.Populate(reader, list);
        }
        else
        {
            var jArray   = JArray.Load(reader);
            var comparer = new KeyedListMergeComparer();
            var lookup   = jArray.ToLookup(i => i[keyProperty.PropertyName].ToObject(keyProperty.PropertyType, serializer), comparer);
            var done     = new HashSet <JToken>();
            foreach (var item in list)
            {
                var key         = keyProperty.ValueProvider.GetValue(item);
                var replacement = lookup[key].Where(v => !done.Contains(v)).FirstOrDefault();
                if (replacement != null)
                {
                    using (var subReader = replacement.CreateReader())
                        serializer.Populate(subReader, item);
                    done.Add(replacement);
                }
            }
            // Populate the NEW items into the list.
            if (done.Count < jArray.Count)
            {
                foreach (var item in jArray.Where(i => !done.Contains(i)))
                {
                    list.Add(item.ToObject <T>(serializer));
                }
            }
        }
        return(list);
    }