- Home /
Loading class instances from Json file gives ArgumentNullException
In my game, I have a Computer class with following variables:
[System.Serializable]
public class Computer : MonoBehaviour, ShopItem{
public string model;
public int price;
public int speed;
public int watt;
public Sprite image;
}
And I have a script that contains a list of Computer:
List<Computer> computerList;
Then when I save the game, I pass all data to the DataClass and convert it to Json:
public string SaveToJson(){
//Create data class
DataClass dataClass = new DataClass(...other parameters..., computerList);
//Convert to json
string jsonString = JsonUtility.ToJson(dataClass, false);
//Save to PlayerPref
PlayerPrefs.SetString("GameData", jsonString);
}
I also stored it into a json file just to see the format. The computerList contains some instanceID like below.
"computerList": [
{
"instanceID": 655388
},
{
"instanceID": 654696
},
{
"instanceID": 655502
},
{
"instanceID": 654696
}
],
When load game,I load the playerPref and convert it back to dataClass:
public void LoadGame(){
string result = PlayerPrefs.GetString("GameData");
DataClass dataClass = JsonUtility.FromJson<DataClass>(result);
this.computerList = dataClass.computerList;
}
But when I try to access the computerList, it gives me this error: ArgumentNullException: Argument cannot be null.
I am not sure what went wrong, does anyone have any idea? Is it related to the non-persistent instance id? Any help would be appreciated.
-----------------------------------------------------------Updates--------------------------------------------------------------- I also saved it in the localhost database, and when I load it back it gives the same error, so I guess it's nothing wrong about PlayerPrefs. Other variables like int, float, list does well, so the problem should be about custom classes.
The full error code is:
ArgumentNullException: Argument cannot be null. Parameter name: key System.Collections.Generic.Dictionary`2[ShopItem,System.Int32].ContainsKey (ShopItem key) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:280) InventoryManager.ProcessItemList () (at Assets/Script/CoreGame/Local Manager/InventoryManager.cs:54) InventoryManager.ShowInvnetory () (at Assets/Script/CoreGame/Local Manager/InventoryManager.cs:89) UnityEngine.Events.InvokableCall.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:166) UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:58) UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:66) UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:108) UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:50) UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:261) UnityEngine.EventSystems.EventSystem:Update()
Answer by Bunny83 · Apr 15, 2019 at 02:55 AM
It's not entirely clear what you want to do here. However the JsonUtility and json in general is for pure data objects only. Json does not support references. You also can not directly deserialize classes derived from MonoBehaviour. For this you can partially use JsonUtility.FromJsonOverwrite to just deserialize and overwrite the pure datafields of an existing instance.
The code snippets you've posted are missing a lot important details. However it seems you try to serialize a list of Monobehaviour components which is pretty pointless as this doesn't work.
In the computerList, I am trying to store the list of computer that the player has bought. and the computerList will be saved to json. I am thinking to give each computer instance an ID, and just store the id of the computer into json, and next time when I load it back, it will find the computer id and get back the computer instance. I hope it will work. Thanks for the response.
Yes, that's what you have to do ^^. It's a pity that Unity doesn't provide access to the internally used AssetGUIDs at runtime. It would simplify many serialization problems.
@Bunny83 Thank you, just realized I can do it in a simple way... Stupid me.