I have a piece of JSON that looks like this:
[
{
\"$id\": \"1\",
\"Name\": \"James\",
\"BirthDate\": \"1983-03-08T00:00Z\",
\"LastModified\
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 _objects =
new Dictionary();
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>(
json, jsonSerializerSettings);
Edit: I was bored so I made a generic version:
public class GenericResolver : IReferenceResolver
where TEntity : ICloneable, new()
{
private readonly IDictionary _objects = new Dictionary();
private readonly Func _keyReader;
public GenericResolver(Func 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(p => p.Name)
};
var deserializedPersons = JsonConvert.DeserializeObject>(
json, jsonSerializerSettings);