- Home /
Handling inheritance with JSONUtility.ToJSON
I'm trying to use the new JSONUtility to serialize an object that contains an object that is the descendant of a base class. Here's an example:
[Serializable]
public class Class1
{
public int class1Field = 1;
public Class2 attributes = new Class3();
}
[Serializable]
public class Class3 : Class2
{
public int class3Field = 3;
}
[Serializable]
public class Class2
{
public int class2Field = 2;
}
If I then do:
Class1 myClass = new Class1();
Debug.Log(JsonUtility.ToJson(myClass));
The output is:
{"class1Field":1,"attributes":{"class2Field":2}}.
As you can see, nothing from Class3 is being serialized. Interestingly if I do:
Debug.Log(JsonUtility.ToJson(myClass.attributes));
The output is :
{"class2Field":2,"class3Field":3}
which is what I expect. I know that I can do a pretty simple workaround using string.Format, but is there a more elegant solution to this issue? Am I perhaps not using the JSONUtility correctly? Or is this simply not supported by the JSONUtility at this time (Unity 5.3.2)?
To be clear, my desired output is:
{"class1Field":1,"attributes":{"class2Field":2,"class3Field":3}}
Answer by Bunny83 · Feb 18, 2016 at 12:35 PM
I still use Unity 5.2.1f1 and i don't have the JSONUtility class ^^.
However i guess that they did the same as they did with the serialization system in Unity. They serialize the fields based on the field type, not on the actual runtime type. If you want to support serialization and deserialization you have two choices:
either you have to serialize the actual runtime type as well so when deserializing the data the deserializer can recreate the correct type
or don't support inheritance and only serialize the pure data. When deserializing the data you usually have to specify the type of the top object. From there on the deserializer can simply use the field types of the given class to determine the object types it needs to create. This of course doesn't support inheritance since if the field type has a baseclass type there's no way how the deserializer can determine which derived type it has to instantiate. This information is simply missing in the serialized data.
Your "desired output" also misses the information which class type the attributes sub object has. Of course you could create a "smart" deserializer which looks at the field type, enumerates it's fields and matches the found fields with the given serialized data. If there are missing fields it could search for a subclass of the given field type and try to find one that matches the serialized fields. However that's quite complicated and isn't a reliable approach. If a subclass doesn't add new fields, it would still create a baseclass instance. It's also possible that two child classes have the same fields so again it can't reliable decide which class to use.
Thanks for the detailed reply. I know this will seem odd, but I don't actually care about deserializing the object for the use case I have in $$anonymous$$d. The idea is that I serialize the object, launch it at a web server where it gets processed and another object, which may or may not be type-compatible with the original, gets sent back.
I cannot know what the definitions of either of these types will be until run-time (the functionality I'm seeking will be in a plugin that will use classes deter$$anonymous$$ed by another programmer). Therefore, based on your answer, the solution seems to be to write my own JSON serializer, or else find an existing one that can support what I'm looking for.
Just to clarify, I'm looking to:
Serialize a type defined at run time
Deserialize a type defined at run time that may or may not be the same as the above type
Thanks again for the reply. I'll be looking into creating my own JSON serializer.
Your answer
Follow this Question
Related Questions
An OS design issue: File types associated with their appropriate programs 1 Answer
C# serialization with polymorphism/inheritance. 1 Answer
JsonUtility doesn't serialize nested mixed var 1 Answer
Distribute terrain in zones 3 Answers
Copy reference from one component to another derived component., 2 Answers