Как сохранять/читать List<Class> через JsonUtility ОТВЕТ!

Программирование на Юнити.

Как сохранять/читать List<Class> через JsonUtility ОТВЕТ!

Сообщение prayde.niste 07 окт 2018, 15:38

Нужно сохранить List<Program3> list в xml. Мучаюсь уже неделю. Жопа горит и всё равно ничего не работает! Вроде всё правильно написано а мне постоянно одну и ту же ошибку суёт:
Скрытый текст:
InvalidOperationException: To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object) at all levels of their inheritance hierarchy. UnityEngine.Transform does not implement Add(System.Object).
System.Xml.Serialization.TypeData.get_ListItemType ()
System.Xml.Serialization.TypeData.get_ListItemTypeData ()
System.Xml.Serialization.TypeData..ctor (System.Type type, System.String elementName, Boolean isPrimitive, System.Xml.Serialization.TypeData mappedType, System.Xml.Schema.XmlSchemaPatternFacet facet)
System.Xml.Serialization.TypeData..ctor (System.Type type, System.String elementName, Boolean isPrimitive)
System.Xml.Serialization.TypeTranslator.GetTypeData (System.Type runtimeType, System.String xmlDataType)
System.Xml.Serialization.TypeTranslator.GetTypeData (System.Type type)
System.Xml.Serialization.XmlReflectionImporter.GetReflectionMembers (System.Type type)
System.Xml.Serialization.XmlReflectionImporter.ImportClassMapping (System.Xml.Serialization.TypeData typeData, System.Xml.Serialization.XmlRootAttribute root, System.String defaultNamespace)
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (System.Xml.Serialization.TypeData typeData, System.Xml.Serialization.XmlRootAttribute root, System.String defaultNamespace)
Rethrow as InvalidOperationException: There was an error reflecting type 'Program2'.
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (System.Xml.Serialization.TypeData typeData, System.Xml.Serialization.XmlRootAttribute root, System.String defaultNamespace)
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (System.Type type, System.Xml.Serialization.XmlRootAttribute root, System.String defaultNamespace)
System.Xml.Serialization.XmlSerializer..ctor (System.Type type, System.Xml.Serialization.XmlAttributeOverrides overrides, System.Type[] extraTypes, System.Xml.Serialization.XmlRootAttribute root, System.String defaultNamespace)
System.Xml.Serialization.XmlSerializer..ctor (System.Type type, System.Type[] extraTypes)
Serializator.SaveXml (.Program2 program2, System.String datapath) (at Assets/Scripts/Serializator.cs:17)
Program2.Save (System.String datapath) (at Assets/Scripts/Program2.cs:29)
SaveLogic.Casket (Boolean isSave) (at Assets/Scripts/SaveLogic.cs:397)
SaveLogic.Save () (at Assets/Scripts/SaveLogic.cs:59)
SaveLogic.FixedUpdate () (at Assets/Scripts/SaveLogic.cs:51)


Значит у меня есть класс Program2. Это основной класс в котором объявлен лист:
Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Program2 : MonoBehaviour
{
    private History history;
    private Program3 program3 = new Program3();
    private Serializator ser = new Serializator();
    public List<Program3> list = new List<Program3>(); //Это лист

    public Program2() { } //Пустой конструктор

    public Program2(List<Program3> list) //Не пустой конструктор
    {
        this.list = list;
    }

    public void Save(string datapath)
    {
       
        for (int i = 0; i < history.list.Count; i++)
        {
            list.Add(new Program3(history.list[i].nameProgram, history.list[i].descriptionProgram, history.list[i].sellProgram, history.list[i].idProgram)); //Заполняю лист объектами
        }

        ser.SaveXml(this, datapath);
    }

    public void Add(object o) { } //Хз зачем это

    private void Start()
    {
        history = GameObject.FindGameObjectWithTag("HistoryGameObject").GetComponent<History>();
    }
}
 


Скрипт в таком ужасном виде потому что я перепробовал уже всё что можно.
Собстна класс Program3
Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Program3
{
    public string nameProgram;
    public string descriptionProgram;
    public string sellProgram;
    public int idProgram;

    public Program3()
    {

    }

    public Program3(string nameProgram, string descriptionProgram, string sellProgram, int idProgram)
    {
        this.nameProgram = nameProgram;
        this.descriptionProgram = descriptionProgram;
        this.sellProgram = sellProgram;
        this.idProgram = idProgram;
    }
}
 


И сериализатор
Синтаксис:
Используется csharp
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using UnityEngine;

public class Serializator
{

    private Program2 program2;

    public void SaveXml(Program2 program2, string datapath)
    {
        this.program2 = program2;
        Type[] extraTypes = { typeof(Program3) };
        XmlSerializer serializer = new XmlSerializer(typeof(Program2), extraTypes); //СТРОЧКА НА КОТОРУЮ ЖАЛУЕТСЯ ЮНИТИ

        FileStream fs = new FileStream(datapath, FileMode.Create);
        for (int i = 0; i < program2.list.Count; i++)
        {
            serializer.Serialize(fs, program2.list[i].nameProgram);   //Я ЗНАЮ ЧТО ЭТО НЕ ПРАВИЛЬНО, просто пробовал, а вдруг сработает вместо serializer.Serialize(fs, program2.list);
            serializer.Serialize(fs, program2.list[i].descriptionProgram);
            serializer.Serialize(fs, program2.list[i].sellProgram);
            serializer.Serialize(fs, program2.list[i].idProgram);
        }
           
        fs.Close();
    }

    public Program2 DeXml(string datapath) //Это пока не делал, просто так написано (на будущее)
    {
        Type[] extraTypes = { typeof(Program3) };
        XmlSerializer serializer = new XmlSerializer(typeof(Program2), extraTypes);

        FileStream fs = new FileStream(datapath, FileMode.Open);
        Program2 program2 = (Program2)serializer.Deserialize(fs);
        fs.Close();

        return program2;
    }

}
 


Вообщем надоело мучится. Прошу вашей помощи. А пока пойду жопу бинтовать :)
Последний раз редактировалось prayde.niste 07 окт 2018, 19:29, всего редактировалось 1 раз.
Безработному на пропитание: 5168 7559 0207 5270
Аватара пользователя
prayde.niste
UNец
 
Сообщения: 18
Зарегистрирован: 14 авг 2018, 23:04

Re: Нужна помощь с XmlSerializer. Ну уж очень не понятно

Сообщение 1max1 07 окт 2018, 15:59

Xml принципиально? Есть еще https://docs.unity3d.com/ScriptReferenc ... ility.html и не нужно парится со всякими сериализаторами.
Кстати List сам по себе не сериализуется, нужно его оборачивать в класс или структуру и сериализовать их.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Нужна помощь с XmlSerializer. Ну уж очень не понятно

Сообщение prayde.niste 07 окт 2018, 16:16

Хммм.. Вообще нет) И да кст, я думал про JsonUtility, но что-то никак не хотел браться. Ладно, спасибо. Буду пробовать. Если не выйдет отпишусь)
Безработному на пропитание: 5168 7559 0207 5270
Аватара пользователя
prayde.niste
UNец
 
Сообщения: 18
Зарегистрирован: 14 авг 2018, 23:04

Re: Нужна помощь с XmlSerializer. Ну уж очень не понятно

Сообщение seaman 07 окт 2018, 17:18

1. Не надо в классы, унаследованные от monobehaviour добавлять конструкторы. Хотя бы потому, что нельзя производить экземпляры таких классов с помощью new
2. Не сериализуйте такие классы. Хотя бы потому, что они имеют некий парный нативный код, и потому Вы можете сериализовать не то что нужно. Во всяком случае пока не разберетесь досконально в этом.

Вывод - сериализуйте необходимые данные в таком классе, в не сам класс.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Нужна помощь с XmlSerializer. Ну уж очень не понятно

Сообщение prayde.niste 07 окт 2018, 19:12

seaman писал(а):1. Не надо в классы, унаследованные от monobehaviour добавлять конструкторы. Хотя бы потому, что нельзя производить экземпляры таких классов с помощью new
2. Не сериализуйте такие классы. Хотя бы потому, что они имеют некий парный нативный код, и потому Вы можете сериализовать не то что нужно. Во всяком случае пока не разберетесь досконально в этом.

Вывод - сериализуйте необходимые данные в таком классе, в не сам класс.


Спасибо. Но, я всё же знаю что делаю) А оставшийся мусор буду убирать на этапе оптимизации.
Безработному на пропитание: 5168 7559 0207 5270
Аватара пользователя
prayde.niste
UNец
 
Сообщения: 18
Зарегистрирован: 14 авг 2018, 23:04

Re: Нужна помощь с XmlSerializer. Ну уж очень не понятно

Сообщение prayde.niste 07 окт 2018, 19:28

Вообщем, всё сделано. Для тех, у кого возникает вопрос, как же сохранить List<object> через JsonUtility. Отвечаю. Довольно просто. У меня приняло такой вид:
Синтаксис:
Используется csharp
    private History history;
    private Program3 program3 = new Program3();
[SerializeField]
    public List<Program3> list = new List<Program3>(); //List класса Program3. Содержит 4 параметра(string, string, string, int). Аналог листа который мне нужно сохранить. Тоесть, this.list играет только посредническую роль! Наверное можно сделать используя всего 1 основной лист, но пока мне это не нужно(буду смотреть при оптимизации проэкта). У меня он history.list
   
    public void Save(string datapath) //метод сохранения. Принимает путь к файлу.
    {
        list.Clear(); //Очищаем лист "посредник"
        string[] data = new string[history.list.Count]; //Создаём массив длинной в основной лист
        for (int i = 0; i < history.list.Count; i++)
        {
            list.Add(new Program3(history.list[i].nameProgram, history.list[i].descriptionProgram, history.list[i].sellProgram, history.list[i].idProgram)); //присваивание посреднику параметры основного
            data[i] = JsonUtility.ToJson(list[i]); //записываем Json в массив строк
        }
       
        File.WriteAllLines(datapath, data); //Запись в файл

    }

    public void Load(string datapath) //метод загрузки
    {
        list.Clear();
        history.list.Clear();
        string[] data = File.ReadAllLines(datapath); //Сдеся может ошибка, но вроде работает( Не знаю, задастся ли длинна новому массиву). Крч, Считываем файл в массив строк
        for (int i = 0; i < data.Length; i++)
        {
            program3 = JsonUtility.FromJson<Program3>(data[i]); //Десериализуем из JSON в объект

            history.list.Add(new Program(program3.nameProgram, program3.descriptionProgram, program3.sellProgram, program3.idProgram)); //И записываем в основной лист все параметры. АЛИЛУЯ. Часы моих мучений окончены!
        }
    }
 
Безработному на пропитание: 5168 7559 0207 5270
Аватара пользователя
prayde.niste
UNец
 
Сообщения: 18
Зарегистрирован: 14 авг 2018, 23:04

Re: Как сохранять/читать List<Class> через JsonUtility ОТВЕТ!

Сообщение Cr0c 09 окт 2018, 15:26

Если в классе нет специфического конструктора, то почему бы JsonUtility сразу на список не натравить? Выставить у нужных приватных полей тег сериализации - и всё.
Синтаксис:
Используется csharp
[Serializable]
public class MyData {
public string name;
public string info;
public int data;
[SerializeField]
private string internalData;
}
///
public List<MyData> list;
public string Save(MyData data) {
 return JsonUtility.ToJson(list);
}
public void Load(string json){
 list = JsonUtility.FromJson<List<MyData>>(json);
}
 
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: Как сохранять/читать List<Class> через JsonUtility ОТВЕТ!

Сообщение prayde.niste 09 окт 2018, 21:11

Cr0c писал(а):Если в классе нет специфического конструктора, то почему бы JsonUtility сразу на список не натравить? Выставить у нужных приватных полей тег сериализации - и всё.
Синтаксис:
Используется csharp
[Serializable]
public class MyData {
public string name;
public string info;
public int data;
[SerializeField]
private string internalData;
}
///
public List<MyData> list;
public string Save(MyData data) {
 return JsonUtility.ToJson(list);
}
public void Load(string json){
 list = JsonUtility.FromJson<List<MyData>>(json);
}
 


Хех) Не ищу легких путей :D
Безработному на пропитание: 5168 7559 0207 5270
Аватара пользователя
prayde.niste
UNец
 
Сообщения: 18
Зарегистрирован: 14 авг 2018, 23:04


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7