1
votes

I generate a JSON representation from type Car and then create a System.Object from that json. When I try to explicitly convert that object to type Car it shows an error "InvalidCastException: Specified cast is not valid". Can anyone explain to me the reason?

using System;
using UnityEngine;
[Serializable]
class Car
{
    public string type;
}
public class Test : MonoBehaviour
{   
    void Start()
    {
        Car car = new Car();
        car.type = "BMW";

        string json = JsonUtility.ToJson(car);
        System.Object @object = JsonUtility.FromJson<System.Object>(json);
        car = (Car)@object;
        Debug.Log(car.type);
    }
}
1
You are deserialising to object which cannot be cast to Car. Why not just directly deserialise to Car? Like this: var car = JsonUtility.FromJson<Car>(json); - DavidG
I tried only to understand the deep cause of this error. - Vuqar
The cause is "you're not creating an instance of Car, so you can't cast to Car". - Jon Skeet

1 Answers

0
votes

What you are trying to do there is called Down/UpCasting.

In c# object is the parent class for all other types. So you can simply assign an inherited type (like in this case Car to an object) variable. This is called Upcast.

Then when trying to cast from a more generic to a more specific type (in your case object to Car this is called Downcast.

You only can directly downcast an object (which btw is simply a type keyword and alias for System.Object) to Car if previously this actually was a Car reference e.g.

Car car = new Car();
car.type = "BMW";

//string json = JsonUtility.ToJson(car);
//System.Object @object = JsonUtility.FromJson<System.Object>(json);
object @object = car;
car = (Car)@object;
Debug.Log(car.type);

would work since now @object actually still holds the information for a Car but boxed into an object.


You can not use

System.Object @object = JsonUtility.FromJson<System.Object>(json);

System.Object is not (de)serializable and makes absolutely no sense as target type here since the type object also holds no information about the fields you are wanting to deserialize. What you want is a Car not an object.

So what you could use is

// Here the Car reference returned by FromJson is BOXED into object
System.Object @object = JsonUtility.FromJson<Car>(json);
// Since @object is still a boxed Car value it is now UNBOXED from object to Car
car = (Car)@object;

However, why the whole casting at all? You really rather want to use

car = JsonUtility.FromJson<Car>(json);