You could use a custom reference resolver. For example, assuming Name
is the "primary key" for your objects, this should work. Of course, you may want to make it more generic.
public class PersonReferenceResolver : IReferenceResolver
{
private readonly IDictionary<string, Person> _objects =
new Dictionary<string, Person>();
public object ResolveReference(object context, string reference)
{
Person p;
if (_objects.TryGetValue(reference, out p))
{
//This is the "clever" bit. Instead of returning the found object
//we just return a copy of it.
//May be better to clone your class here...
return new Person
{
Name = p.Name,
BirthDate = p.BirthDate,
LastModified = p.LastModified
};
}
return null;
}
public string GetReference(object context, object value)
{
Person p = (Person)value;
_objects[p.Name] = p;
return p.Name;
}
public bool IsReferenced(object context, object value)
{
Person p = (Person)value;
return _objects.ContainsKey(p.Name);
}
public void AddReference(object context, string reference, object value)
{
_objects[reference] = (Person)value;
}
}
Now you deserialise like this:
var jsonSerializerSettings = new JsonSerializerSettings()
{
ReferenceResolver = new PersonReferenceResolver()
};
var deserializedPersons = JsonConvert.DeserializeObject<List<Person>>(
json, jsonSerializerSettings);
Edit: I was bored so I made a generic version:
public class GenericResolver<TEntity> : IReferenceResolver
where TEntity : ICloneable, new()
{
private readonly IDictionary<string, TEntity> _objects = new Dictionary<string, TEntity>();
private readonly Func<TEntity, string> _keyReader;
public GenericResolver(Func<TEntity, string> keyReader)
{
_keyReader = keyReader;
}
public object ResolveReference(object context, string reference)
{
TEntity o;
if (_objects.TryGetValue(reference, out o))
{
return o.Clone();
}
return null;
}
public string GetReference(object context, object value)
{
var o = (TEntity)value;
var key = _keyReader(o);
_objects[key] = o;
return key;
}
public bool IsReferenced(object context, object value)
{
var o = (TEntity)value;
return _objects.ContainsKey(_keyReader(o));
}
public void AddReference(object context, string reference, object value)
{
if(value is TEntity)
_objects[reference] = (TEntity)value;
}
}
With slightly new usage:
var jsonSerializerSettings = new JsonSerializerSettings()
{
//Now we need to specify the type and how to get the object's key
ReferenceResolver = new GenericResolver<Person>(p => p.Name)
};
var deserializedPersons = JsonConvert.DeserializeObject<List<Person>>(
json, jsonSerializerSettings);
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…