Сохранеие в Json Листа с сложной структурой.

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

Сохранеие в Json Листа с сложной структурой.

Сообщение T116 14 ноя 2018, 16:45

Привет всем. Мб не самое удачное название, но если честно столкнулся с тем что пока не могу найти ответ на ситуацию в которую попал.
по умолчанию допустим что есть Базовый класс Item
Синтаксис:
Используется csharp
[System.Serializable]
public class Item  {

    [SerializeField] protected int itemCount;
    [SerializeField] protected string id;
}
 


и есть пара наследников у которых еще по 1 параметру у каждого добавляется

Синтаксис:
Используется csharp
[System.Serializable]
public class Item1  {

    [SerializeField] protected int itemCount;
    [SerializeField] protected string id;
    [SerializeField] protected bool state;
}
[System.Serializable]
public class Item2  {

    [SerializeField] protected int itemCount;
    [SerializeField] protected string id;
    [SerializeField] protected float price;
}


 


ну и как водится есть List<Item> в котором некоторое количество как Item1 так и Item2. При сохзранении всего этого беспредела приходится указывать Тип SaveArrayFile<T>(T[] array,string fileName) где уже все это сохраняется) но конечно же сериализуются параметры только Item. Я пока не нашел возможности сериализовать лист с учетом типа наследника который туда засунут. Не хочется для каждого типа делать свою струтуру данных и ее загонять. Геморно както.
T116
UNец
 
Сообщения: 38
Зарегистрирован: 28 янв 2017, 02:35

Re: Сохранеие в Json Листа с сложной структурой.

Сообщение 1max1 14 ноя 2018, 18:08

На ум пришла только костылизация из рефлексии, но мне кажется можно и проще))
Синтаксис:
Используется csharp
using UnityEngine;
using System;
using System.Reflection;
using System.Collections.Generic;

[Serializable]
class Base
{
    [SerializeField] protected int a = 1;
    [SerializeField] protected int b = 2;
}

[Serializable]
class Class1 : Base
{
    [SerializeField] int c = 3;
}

[Serializable]
class Class2 : Class1
{
    [SerializeField] int d = 4;
}

class test : MonoBehaviour
{
    void Start()
    {
        List<Base> l = new List<Base>();

        l.Add(new Class1());
        l.Add(new Class2());

        // В json строку
        string json = l.ToJson();

        print(json);
        // Вывод:
        // {"a":1,"b":2,"c":3}|Class1
        // {"a":1,"b":2,"c":3,"d":4}|Class2

        // Из Json`a в List<T>
        List<Base> l2 = json.FromJson<Base>();
    }
}

static class Extensions
{
    public static string ToJson<T>(this List<T> l)
    {
        Type baseType = typeof(T);

        List<Type> needTypes = new List<Type>();

        foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
        {
            if (type.ValidateBaseType(baseType))
            {
                needTypes.Add(type);
            }
        }

        string result = string.Empty;

        foreach (T element in l)
        {
            foreach (Type type in needTypes)
            {
                if (type.Equals(element.GetType()))
                {
                    object changeType = Convert.ChangeType(element, type);

                    string json = JsonUtility.ToJson(changeType);

                    result += json + '|' + type.FullName + '\n';
                }
            }
        }

        return result;
    }

    public static List<T> FromJson<T>(this string json)
    {
        List<T> result = new List<T>();

        string[] elements = json.Split('\n');

        for (int i = 0; i < elements.Length - 1; ++i)
        {
            int split = elements[i].LastIndexOf('|');

            string type = elements[i].Substring(split + 1);

            result.Add((T)JsonUtility.FromJson(elements[i].Substring(0, split), Type.GetType(type)));
        }

        return result;
    }

    public static bool ValidateBaseType(this Type me, Type baseType)
    {
        if (me != null)
        {
            if (me.BaseType != baseType)
            {
                return me.BaseType.ValidateBaseType(baseType);
            }
            else
                return true;
        }
        else
            return false;
    }
}
Последний раз редактировалось 1max1 14 ноя 2018, 18:31, всего редактировалось 3 раз(а).
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Сохранеие в Json Листа с сложной структурой.

Сообщение Friend123 14 ноя 2018, 18:11

Я для сериализации юзаю сей ассет: https://forum.unity.com/threads/discontinued-unity-save-load-utility-free-save-and-load-your-data.435506/
И листы сериализуются и прочие необходимые компоненты
Аватара пользователя
Friend123
Старожил
 
Сообщения: 701
Зарегистрирован: 26 фев 2012, 22:12
Откуда: Тверь
  • ICQ

Re: Сохранеие в Json Листа с сложной структурой.

Сообщение Anonymyx 14 ноя 2018, 19:57

Newtonsoft json умеет такое, в настройках сериализации чтоли или что-то включить или перегрузка какая-то была у сериализатора... но точно помню что эта библиотека это умеет.
Аватара пользователя
Anonymyx
Адепт
 
Сообщения: 1973
Зарегистрирован: 05 апр 2015, 15:55

Re: Сохранеие в Json Листа с сложной структурой.

Сообщение IDoNotExist 15 ноя 2018, 11:54

T116 писал(а):и есть пара наследников у которых еще по 1 параметру у каждого добавляется

Синтаксис:
Используется csharp
[System.Serializable]
public class Item1  {

    [SerializeField] protected int itemCount;
    [SerializeField] protected string id;
    [SerializeField] protected bool state;
}
[System.Serializable]
public class Item2  {

    [SerializeField] protected int itemCount;
    [SerializeField] protected string id;
    [SerializeField] protected float price;
}
 


Это не наследники, если ты только не имеешь в виду наследование от System.Object.

T116 писал(а):ну и как водится есть List<Item> в котором некоторое количество как Item1 так и Item2.

Круто, ты в List<Item> умудрился засунуть Item1 и Item2, которые не являются наследниками Item. Может там у тебя лежат экземпляры Item всё-таки?

T116 писал(а):При сохзранении всего этого беспредела приходится указывать Тип

На какой черт?

T116 писал(а):SaveArrayFile<T>(T[] array,string fileName) где уже все это сохраняется) но конечно же сериализуются параметры только Item.

Чем сериализуются то? Самописной приблудой или стандартными методами?

T116 писал(а):Геморно както.

Я полагаю это не так геморно, как по человечески сформулировать свой вопрос.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Сохранеие в Json Листа с сложной структурой.

Сообщение T116 15 ноя 2018, 12:14

Это не наследники, если ты только не имеешь в виду наследование от System.Object.


Да ты прав, я допустил ошибку. Item1:Item, и Item2:Item.

Чем сериализуются то? Самописной приблудой или стандартными методами?


в основе UnityEngine.JsonUtility .

Я полагаю это не так геморно, как по человечески сформулировать свой вопрос.

да за исключением того, что провтыкал поставить знаки наследования, по моему вопрос ясен. Каким образом сохранить массив наследников в json.
T116
UNец
 
Сообщения: 38
Зарегистрирован: 28 янв 2017, 02:35

Re: Сохранеие в Json Листа с сложной структурой.

Сообщение T116 15 ноя 2018, 13:45

1max1 писал(а):На ум пришла только костылизация из рефлексии, но мне кажется можно и проще))

Спасибо) да, я прикидывал и такой вариант, пока показался чересчур для задачи.
T116
UNец
 
Сообщения: 38
Зарегистрирован: 28 янв 2017, 02:35

Re: Сохранеие в Json Листа с сложной структурой.

Сообщение IDoNotExist 15 ноя 2018, 13:52

T116 писал(а):в основе UnityEngine.JsonUtility .

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

public class JsonTest : MonoBehaviour
{

        [ContextMenu("Test")]
        void Start ()
        {
                List<Item> list = new List<Item>();
                list.Add(new Item1() { id = "a", itemCount = 0, state = true });
                list.Add(new Item2() { id = "b", itemCount = 1, price = 0.1f });


                SerializedList serList = new SerializedList()
                {
                        types = list.Select(obj => obj.GetType().FullName).ToArray(),
                        objects = list.Select(obj => JsonUtility.ToJson(obj, false)).ToArray(),
                };

                string jsonStr = JsonUtility.ToJson(serList, true);
                Debug.Log(jsonStr);

                SerializedList deserList = JsonUtility.FromJson<SerializedList>(jsonStr);

                for (int i = 0; i < deserList.types.Length; i++)
                {
                        System.Type dataType = System.Type.GetType(deserList.types[i]);
                        Item item = (Item)JsonUtility.FromJson(deserList.objects[i], dataType);

                        Debug.Log(item.GetType());
                }

        }


        [System.Serializable]
        public class Item
        {
                public int itemCount;
                public string id;
        }

        [System.Serializable]
        public class Item1 : Item
        {
                public bool state;
        }

        [System.Serializable]
        public class Item2 : Item
        {
                public float price;
        }

        [System.Serializable]
        public class SerializedList
        {
                public string[] types;
                public string[] objects;
        }
}
 

Собсно лог:
Синтаксис:
Используется csharp
{
    "types": [
        "JsonTest+Item1",
        "JsonTest+Item2"
    ],
    "objects": [
        "{\"itemCount\":0,\"id\":\"a\",\"state\":true}",
        "{\"itemCount\":1,\"id\":\"b\",\"price\":0.10000000149011612}"
    ]
}
JsonTest:Start() (at Assets\JsonTest.cs:24)
 
JsonTest+Item1
JsonTest:Start() (at Assets\JsonTest.cs:33)
 
JsonTest+Item2
JsonTest:Start() (at Assets\JsonTest.cs:33)
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Сохранеие в Json Листа с сложной структурой.

Сообщение T116 16 ноя 2018, 16:11

Спасибо) я чет о таком подходе не подумал)
T116
UNец
 
Сообщения: 38
Зарегистрирован: 28 янв 2017, 02:35


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

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

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