代码之家  ›  专栏  ›  技术社区  ›  blablaalb

有没有办法将嵌套对象序列化为JSON

  •  0
  • blablaalb  · 技术社区  · 5 年前

    假设我有一个名为 ObjectA 包含两个对象: ObjectsB ObjectC .

    [System.Serializable]
    public ClassA
    {
        public ClassB classB;
        public ClassC classC;
    
        public ClassA()
        {
            classB = new ClassB();
            classC = new ClassC();
        }
    }
    
    [System.Serializable]
    public ClassB
    {
        //Some fields.
    }
    
    [System.Serializable]
    public ClassC
    {
        //Some fields.
    }
    

    如果我序列化 反对 ObjectB 对象C 反对 到JSON:
    {"_instanceB":{"instanceID":10480},"_instanceC":{"instanceID":10230}}
    我需要将所有这些对象序列化为一个文件,并将其本地保存在硬盘上,以便以后能够恢复其状态。我该怎么做?
    我应该找回 ClassB ClassC ClassA

    public void Save()
    {
        //Get instances of ClassB and ClassC.
        ClassB classB = classA.GetClassB;
        ClassC classC = classA.GetClassC;
    
        //Generate different JSON for each class.
        string classA_JSON = JsonUtility.ToJson(classA);
        string classB_JSON = JsonUtility.ToJson(classB);
        string classC_JSON = JsonUtility.ToJson(classC);
    
        //Paths for saving locally.
        string pathForClassA = Path.Combine("C:\\", "classA.json");
        string pathForClassB = Path.Combine("C:\\", "classB.json");
        string pathForClassC = Path.Combine("C:\\", "classC.json");
    
        File.WriteAllText(pathForClassA, classA_JSON);
        File.WriteAllText(pathForClassB, classB_JSON);
        File.WriteAllText(pathForClassC, classC_JSON);
    }
    

    看起来很难看,它将为每个嵌套类生成一个新的JSON文件。我能不能序列化 甲级 将其嵌套类包含到一个JSON文件中?

    附笔。 这是一个联合项目 甲级 , B类 ,和 C类 源自 MonoBehaviour . 自从 BinaryFormatter 不支持 单一行为 我不能用它。唯一留给我的是将它序列化为JSON。

    0 回复  |  直到 5 年前
        1
  •  0
  •   derHugo    5 年前

    我能把ClassA(包括它的嵌套类)序列化成一个JSON文件吗?

    是的,你可以,但这需要一些工作:

    你本可以 [Serializable] 表示类 ClassB ClassC 使用 ISerializationCallbackReceiver interface 用于填充和使用 ClassA

    比如说。

    public class ClassB : MonoBehaviour
    {
        [SerializeField] private float example1;
        [SerializeField] private string example2;
        // etc.
    
        public void SetUp(SerializableClassB values)
        {
            // set all values
            this.example1 = values.example1;
            this.example2 = values.example2;
            // etc.
        }
    
        public SerializableClassB GetSerializable()
        {
            var output = new SerializableClassB();
    
            output.example1 = this.example1;
            output.example2 = this.example2;
            // etc.
    
            return output;
        }
    }
    
    [Serializable]
    public class SerializableClassB
    {
        public float example1;
        public string example2;
        // etc
    }
    

    C类

    public class ClassC : MonoBehaviour
    {
        [SerializeField] private float example3;
        [SerializeField] private string example4;
        // etc.
    
        public void SetUp(SerializableClassC values)
        {
            // set all values
            example3 = values.example3;
            example4 = values.example4;
            // etc.
        }
    
        public SerializableClassC GetSerializable()
        {
            var output = new SerializableClassC();
    
            output.example3 = example3;
            output.example4 = example4;
            // etc.
    
            return output;
        }
    }
    
    [Serializable]
    public class SerializableClassC
    {
        public float example3;
        public string example4;
        // etc
    }
    

    甲级 你可以的

    public class ClassA : MonoBehaviour, ISerializationCallbackReceiver
    {
        public ClassB _classB;
        public ClassC _classC;
    
        [SerializeField] private SerializableClassB _serializableClassB;
        [SerializeField] private SerializableClassC _serializeableClassC;
    
    
        public void OnBeforeSerialize()
        {
            // before writing to a Json get the information from the MonoBehaviours into the normal classes
            if(_classB) _serializableClassB = _classB.GetSerializable();
            if(_classC) _serializeableClassC = _classC.GetSerializable();
    
        }
    
        public void OnAfterDeserialize()
        {
            // after deserializing write the infromation from the normal classes into the MonoBehaviours
            if(_classB) _classB.SetUp(_serializableClassB);
            if(_classC) _classC.SetUp(_serializeableClassC);
        }
    }
    

    第二个巨大的优点(副作用)是现在您还可以控制 _classB _classC 直接在 甲级 实例。这样,您就可以在集中式管理器类中修改单行为值。

    enter image description here

    在使用

    private void Start()
    {
        File.WriteAllText(Path.Combine(Application.streamingAssetsPath, "Test.txt"), JsonUtility.ToJson(this));
        AssetDatabase.Refresh();
    }
    

    你现在得到

    {
        "_classB":{"instanceID":-6766},"_classC":{"instanceID":-6826},
        "_serializableClassB": {
                "example1":23.0,
                "example2":"54ththfghg"
        },
        "_serializeableClassC": {
                "example3":67.0,
                "example4":"567gffhgfhgf"
        }
    }
    

    我把它改成了

    {
        "_classB":{"instanceID":-6766},"_classC":{"instanceID":-6826},
        "_serializableClassB": {
                "example1":47,
                "example2":"Hello"
        },
        "_serializeableClassC": {
                "example3":32.123,
                "example4":"World!"
        }
    }
    

    private void Start()
    {
        JsonUtility.FromJsonOverwrite(File.ReadAllText(Path.Combine(Application.streamingAssetsPath, "Test.txt")), this);
    }
    

    enter image description here