C
C#7mo ago
Elio

✅ JSON Deserialize Derived Class

Hi, i'm struggling to deserialize my object with the Newtonsoft.Json Librairy. I've a collection of Step named Steps which can be a Stepspecial or Stepnormal. I'm trying to write my JsonConverter to deserialize the collection of Step but when i try to deserialize i keep getting the stack overflow error because jObject.ToObject call back ReadJson :
public class StepConverterJSON : JsonConverter<Step>
{
#region Properties
public override bool CanWrite => false;
#endregion

#region Override Methods
public override void WriteJson(JsonWriter writer, Step? value, JsonSerializer serializer) { throw new NotImplementedException(); }

public override Step? ReadJson(JsonReader reader, Type objectType, Step? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
// Load a JObject from the JsonReader
JObject jObject = JObject.Load(reader);

if(jObject["Message"] != null)
{
// Use the new serializer to deserialize the object
StepSpecial? stepSpecial = serializer.Deserialize<StepSpecial>(reader);
return stepSpecial;
}
else
{
StepNormal? stepNormal = jObject.ToObject<StepNormal>(serializer);
//StepNormal? stepNormal = serializer.Deserialize<StepNormal>(reader);
return stepNormal;
}
}
#endregion
}
public class StepConverterJSON : JsonConverter<Step>
{
#region Properties
public override bool CanWrite => false;
#endregion

#region Override Methods
public override void WriteJson(JsonWriter writer, Step? value, JsonSerializer serializer) { throw new NotImplementedException(); }

public override Step? ReadJson(JsonReader reader, Type objectType, Step? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
// Load a JObject from the JsonReader
JObject jObject = JObject.Load(reader);

if(jObject["Message"] != null)
{
// Use the new serializer to deserialize the object
StepSpecial? stepSpecial = serializer.Deserialize<StepSpecial>(reader);
return stepSpecial;
}
else
{
StepNormal? stepNormal = jObject.ToObject<StepNormal>(serializer);
//StepNormal? stepNormal = serializer.Deserialize<StepNormal>(reader);
return stepNormal;
}
}
#endregion
}
Any idea how to solve this and write a good ReadJson method ? i've thought about the populate method but not sure this is the good way of doing it.
45 Replies
Elio
ElioOP7mo ago
Jimmacle
Jimmacle7mo ago
can you $paste the json?
MODiX
MODiX7mo ago
If your code is too long, you can post to https://paste.mod.gg/ and copy the link into chat for others to see your shared code!
Elio
ElioOP7mo ago
BlazeBin - cgqvpondvcnu
A tool for sharing your source code with the world!
Elio
ElioOP7mo ago
well it seem that i solved my problem just by adding this setting .... JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; but i do not really uderstand why and if it's the good solution
leowest
leowest7mo ago
you should avoid Newtonsoft unless you have an edge case that forces u to use it.
leowest
leowest7mo ago
System.Text.Json is the way to go these days.... with your data your modesl would look like this for STJ https://paste.mod.gg/wifpvbzpkwvj/0
BlazeBin - wifpvbzpkwvj
A tool for sharing your source code with the world!
leowest
leowest7mo ago
var result = JsonSerializer.Deserialize<Width>(json);
var result = JsonSerializer.Deserialize<Width>(json);
no need to write any corverters either unless I missed out something from your json
Elio
ElioOP7mo ago
why do we avoid Newtonsoft ? thanks for the solution i'll try to do it this way
Jimmacle
Jimmacle7mo ago
it's pretty much obsolete with STJ and doesn't perform as well
leowest
leowest7mo ago
because its inefficient, slow, the same people that created newtonsoft made STJ
Elio
ElioOP7mo ago
Given the number of its popularity, I thought it was a good librairy
leowest
leowest7mo ago
newtonsoft was made in the acient era where there was no json reason reader and there was a wide range of dirty json in the market that needed handling
Elio
ElioOP7mo ago
ok good to know
leowest
leowest7mo ago
its popular because it existed when nothing existed so that is years until .net core came out
Elio
ElioOP7mo ago
do i really need to specify the name of each property for the json ?
leowest
leowest7mo ago
but the performances alone should speak for it self. u dont if they are the same except casing I do because if I need to change it later for whaterver reason I dont need to change the underlying variable name or vice-verse if the naming in the json
Elio
ElioOP7mo ago
i understand thanks i will quiclky try this and let u know if everything work well 🙂
leowest
leowest7mo ago
I was trying to find the benchmark they did comparing both but I couldn't find lol
JC
JC7mo ago
If you're already deep into Newtonsoft with things like custom converters switching to STJ might not be trivial
Elio
ElioOP7mo ago
i've got the same problem as before, when i deserialize the array of step, it only use the class step and ignore the subclass stepspecial and stepnormal that's good i've started yesterday so i can still change from newton to STJ
JC
JC7mo ago
STJ can have some behavior thats unexpected, but generally reasonable. If you're serializing to an interface, only the members of that interface will be serialized.
Elio
ElioOP7mo ago
here is the good class : https://paste.mod.gg/pymisjadpkel/0
BlazeBin - pymisjadpkel
A tool for sharing your source code with the world!
The Fog from Human Resources
You should totally use the built in JSON class. Pretty sure someone else already said that tho
JC
JC7mo ago
I think the problem, as I understand it, is that you have Step[] as your target, but want to include derived classes as a part of the result
Elio
ElioOP7mo ago
yep that's it
JC
JC7mo ago
I don't know if that's something trivially done by System.Text.Json. If you try to deserialize to Step[], you're going to get an array of Step only.
Elio
ElioOP7mo ago
i want to have stepnormal and stepspecial instead of only step
No description
JC
JC7mo ago
Now, I'll assume you are not planning to allow typenamehandling
Elio
ElioOP7mo ago
yup and i can't really figure it out how to say to STJ to select the good class when i want to deserialize my object which contains this list
JC
JC7mo ago
JsonDerivedTypeAttribute would probably be what you're looking for, if .NET 7+ is your target
Jimmacle
Jimmacle7mo ago
it seems like the issue with this is the data itself, it does not include a type discriminator field
JC
JC7mo ago
You could take a look at https://github.com/dmitry-bym/JsonKnownTypes if you're going to stick with netwonsoft
GitHub
GitHub - dmitry-bym/JsonKnownTypes: Simple way to serialize and des...
Simple way to serialize and deserialize polymorphic types for Json.NET - dmitry-bym/JsonKnownTypes
Jimmacle
Jimmacle7mo ago
so you have to infer what C# type it is by the presence/absence of properties or simply make a single model with all the potential properties but marked optional
JC
JC7mo ago
but you probably want to add a descriminator field As far as your current converter is concerned take a look at changing StepSpecial? stepSpecial = serializer.Deserialize<StepSpecial>(reader); to StepSpecial? stepSpecial = jObject.ToObject<StepSpecial>(serializer);
Elio
ElioOP7mo ago
i'm open to switch to STJ, i just need to figure it out how to handle the desesrialization of my polymorphic object
Jimmacle
Jimmacle7mo ago
do you have control over the json schema?
JC
JC7mo ago
I think you're recursively entering the same serializer by trying to deserialize the derived type.
Elio
ElioOP7mo ago
what do you mean ? yup and with newtonsoft i've found the solution how to do it, rn i'm looking to find how to do it with STJ
Jimmacle
Jimmacle7mo ago
are you creating this json or is it coming from a program you can't change?
Elio
ElioOP7mo ago
y i'm creating the json
Elio
ElioOP7mo ago
to resume i want to save programbending as a json in order to export/import it from a usb
Jimmacle
Jimmacle7mo ago
do this
Elio
ElioOP7mo ago
perfect that was what i was looking for ! 😍 Well i should be careful about my vocabulary it would have save some time i think 😅 polymorphic object/derived classes Thank you all for helping me !
Want results from more Discord servers?
Add your server