0

I have a class GameObject with a public List<Component> Components. I am using Json.NET to store a list of GameObjects that are kept as a list inside a Scene class, so that I can load them in later.

Component is an abstract class. I want to be able to load all of my Components. The loading/saving system I have right now is simple.

Loading the scene:

string Text = File.ReadAllText(Path);
Scene CurrentScene = JsonConvert.DeserializeObject<Scene>(Text);

Saving it:

string JSON = JsonConvert.SerializeObject(Scene, Formatting.Indented, SerializerSettings);
File.WriteAllText(Path, JSON);

Whenever I try to load the scene and I try to access a component, I get a 'NullReferenceException` error.

Edit:

        public static Scene LoadScene(string Path)
        {
            if (!File.Exists(Path))
            {
                Debug.LogError("There is no scene file with the specified path!");
                return new Scene();
            }

            string Text = File.ReadAllText(Path);
            Scene CurrentScene = JsonConvert.DeserializeObject<Scene>(Text);

            foreach (GameObject GObject in CurrentScene.gameObjects)
                for(int i = 0; i <= GObject.Components.Count - 1; ++i)
                    GObject.Components[i] = JsonConvert.DeserializeObject<Component>(Text, new ComponentConverter());

            return CurrentScene;
        }

        public static void CreateSceneFile(string Path, Scene Scene, bool Overwrite)
        {
            if(File.Exists(Path) && !Overwrite)
            {
                Debug.LogError("There already exists a scene file with the specified path!");
                return;
            }

            JsonSerializerSettings SerializerSettings = new JsonSerializerSettings();
            SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

            string JSON = JsonConvert.SerializeObject(Scene, Formatting.Indented, SerializerSettings);
            File.WriteAllText(Path, JSON);
        }
[Serializable]
public class Scene
{
    public List<GameObject> gameObjects = new List<GameObject>();
}
[Serializable]
public class GameObject
{
   public List<Component> Components = new List<Component>();
   public Transform transform = new Transform(); // Separate so that it can't be removed

   public Scene scene // Scene it belongs to
   public string name = "GameObject";
   public string tag = "Untagged";
}
[Serializable]
public class Component
{
   public virtual void FixedUpdate() { }
   public virtual void LateUpdate() { }
   public virtual void Update() { }
   public virtual void Start() { }
   public virtual void Close() { }

   public GameObject gameObject;
   public string name; // added just to see the name in the json
}

Still haven't found a suitable solution

imtouchk
  • 41
  • 1
  • 6
  • Have you tried to load your json in a text editor and look if all the info has been saved? Can you provide an example of this json file? – Steve Jan 12 '20 at 14:02
  • Does this answer your question? [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Pavel Anikhouski Jan 12 '20 at 14:02
  • 1
    It would be helpful if could share minimum reproducible code, including your json and Scene/Component classes – Anu Viswan Jan 12 '20 at 14:02
  • The `Scene` class has a `public List gameObjects = new List();`. – imtouchk Jan 12 '20 at 14:07
  • Output: https://pastebin.com/WMWV8HMi – imtouchk Jan 12 '20 at 14:07
  • try to generate an object here http://json2csharp.com/ and compare with your object – Serhii Matvienko Jan 12 '20 at 14:11
  • Only got the abstract Component class – imtouchk Jan 12 '20 at 14:14
  • Can you please provide us more code and include your serializer settings, etc? – misticos Jan 12 '20 at 15:18
  • There are already several questions about this including [How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?](https://stackoverflow.com/q/8030538/3744182), [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/q/19307752/3744182), [Json.net serialize/deserialize derived types?](https://stackoverflow.com/q/8513042/3744182) and [how to deserialize JSON into IEnumerable with Newtonsoft JSON.NET](https://stackoverflow.com/q/6348215/3744182). Do any of those meet you needs? – dbc Jan 12 '20 at 16:32
  • None of them weree useful – imtouchk Jan 12 '20 at 17:51

1 Answers1

0

The problem is most likely that the serializer does not know what type a component is of.

To support the de-/serialization of objects containing properties with an abstract-classes-/interfaces-type you have to specify the TypeNameHandling property of the JsonSerializerSettings

public static void CreateSceneFile(string Path, Scene Scene, bool Overwrite)
{
    JsonSerializerSettings SerializerSettings = new JsonSerializerSettings();
    SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;

    string JSON = JsonConvert.SerializeObject(Scene, Formatting.Indented, SerializerSettings);
    File.WriteAllText(Path, JSON);
}

See TypeNameHandling for further information

Robert
  • 1,235
  • 7
  • 17