json.net - net - newtonsoft jsonproperty example
La deserialización de las propiedades de autorreferencia no funciona (2)
El uso de referencias no funciona con objetos que solo tienen constructores con parámetros.
Json.NET tiene que deserializar todos los valores secundarios antes de que cree el elemento primario, necesita que esos valores pasen al constructor, por lo que no hay una referencia principal válida para asignar al elemento secundario.
Tengo este objeto con una propiedad principal que hace referencia a otro objeto del mismo tipo:
[JsonObject(IsReference = true)]
class Group
{
public string Name { get; set; }
public Group(string name)
{
Name = name;
Children = new List<Group>();
}
public IList<Group> Children { get; set; }
public Group Parent { get; set; }
public void AddChild(Group child)
{
child.Parent = this;
Children.Add(child);
}
}
La serialización funciona bien y hace que json se vea así:
{
"$id": "1",
"Name": "Parent",
"Children": [
{
"$id": "2",
"Name": "Child",
"Children": [],
"Parent": {
"$ref": "1"
}
}
],
"Parent": null
}
Pero la deserialización no funciona. La propiedad Parent vuelve nula.
Una prueba se ve así:
[Test]
public void Test()
{
var child = new Group("Child");
var parent = new Group("Parent");
parent.AddChild(child);
var json = JsonConvert.SerializeObject(parent, Formatting.Indented);
Debug.WriteLine(json);
var deserializedParent = (Group) JsonConvert.DeserializeObject(json, typeof(Group));
Assert.IsNotNull(deserializedParent.Children.First().Parent);
}
¿Qué estoy haciendo mal? Cualquier ayuda apreciada!
Para ampliar la respuesta de James, puede solucionar este problema proporcionando un constructor sin parámetros (predeterminado) para que Json.Net lo use. Puede ser privado si lo desea, siempre que también lo marque con un atributo [JsonConstructor]
.
[JsonObject(IsReference = true)]
class Group
{
...
[JsonConstructor]
private Group()
{
}
public Group(string name)
{
Name = name;
Children = new List<Group>();
}
...
}
Esta disposición permite a Json.Net crear el objeto sin necesidad de toda la información por adelantado; luego puede usar las propiedades públicas para completar las cosas después.
Fiddle: https://dotnetfiddle.net/QfqV43