-1
Hello!
I’m trying to customize the serialization of a class using the Newtonsoft.Json. My intention is to add a property in JSON during the serialization of the object.
Following the official documentation, managed to implement a JsonConverter
custom to add the property. However, when I have nested objects, I cannot apply the JsonConverter
in the child objects.
I created a simplified example to demonstrate what happens:
Goal
Add property "Temfilhos" (true
or false
) on JSON during silkscreen screening.
Target
The class Person will be the target of serialization. If you have any children in the collection, the JSON "Temfilhos" property should be true
, but false
.
public class Pessoa
{
public Pessoa() { }
public Pessoa(string nome, params Pessoa[] filhos)
{
Nome = nome;
if (filhos?.Length > 0)
Filhos = new List<Pessoa>(filhos);
}
public string Nome { get; set; }
public List<Pessoa> Filhos { get; set; }
}
Jsonconverter
That’s the JsonConverter
custom that will add the "Temfilhos" property during serialization.
public class PessoaJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Pessoa);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var pessoa = (Pessoa)value;
JObject o = JObject.FromObject(pessoa);
// Adiciona a propriedade "TemFilhos" (true / false)
o.AddFirst(new JProperty("TemFilhos", new JValue(pessoa?.Filhos?.Count > 0)));
o.WriteTo(writer, this);
}
}
Execution
The code below serializes the class Person using the JsonConverter
customized.
public class Program
{
public static void Main(string[] args)
{
var ancestral =
new Pessoa("Goku",
new Pessoa("Gohan", new Pessoa("Pan")),
new Pessoa("Goten")
);
string json = JsonConvert.SerializeObject(ancestral, new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new PessoaJsonConverter() }
});
Console.WriteLine(json);
Console.Read();
}
}
Expected Result
The goal is to create the "Temfilho" property for all instances of the class Person.
{
"TemFilhos": true,
"Nome": "Goku",
"Filhos": [
{
"TemFilhos": true,
"Nome": "Gohan",
"Filhos": [
{
"TemFilhos": false,
"Nome": "Pan",
"Filhos": null
}
]
},
{
"TemFilhos": false,
"Nome": "Goten",
"Filhos": null
}
]
}
Result Obtained
The "Temfilhos" property was created only in the first instance of the hierarchy (Goku).
{
"TemFilhos": true,
"Nome": "Goku",
"Filhos": [
{
"Nome": "Gohan",
"Filhos": [
{
"Nome": "Pan",
"Filhos": null
}
]
},
{
"Nome": "Goten",
"Filhos": null
}
]
}
If anyone can help me, I’ll be very hurt!
Issue 1
I guess I didn’t express myself well in the initial post. I know there are other (much simpler) ways to add this property to JSON, as well as solutions alternatives presented in the comments and responses of this post so far.
However, the code I’m working on is much more complex than this example I built. I am developing a type of plugin for my program, and I have no control over the types that will be serialized/deserialized. The first step would be to have a map of Chave => Tipo
, and make the Chave
be generated in a JSON property, then use it in Deserialization.
I’ve run tests using the option TypeNameHandling = TypeNameHandling.Objects
of JsonSerializerSettings
, where it generates a property called $type
in JSON, with the full name of the class type. That’s more or less what I need, but I want to have control over the name and value of the property that will be generated.
In short, my question is not how to add the "Temfilhos" property to JSON, but how to master the class implementation JsonConverter
to the point where I can add the property I need with it.
Unless the intention is otherwise, it would not be more practical less susceptible to errors declare a getter
TemFilhos
in your class? Something likepublic bool TemFilhos { get { return this.Filhos.Count > 0; } }
– Andre
Thanks for the help @user140828! But that’s not quite what I was looking for. I edited the post explaining the situation better.
– Daniel Giacomelli