Преобразование массивов массивов в json

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

string filename = "data.json";
string jsonString;
string path;

[System.Serializable]
public class LevelGrid
{
    public string[] rows;
}

[System.Serializable]
public class Levels
{
    public LevelGrid[] levels;
}

void LoadGrid()
{
    // Load data
    string path = Application.streamingAssetsPath + "/" + filename;
    jsonString = File.ReadAllText(path);
    var levelBricks = JsonUtility.FromJson<Levels>(jsonString);

    // DOESNT WORK
    Debug.Log(levelBricks.levels[0]); 

}

Мой data.json:

 {
     "Levels": [
         {"Level1": ["1,1,1,1,1", "1,1,1,1,1", "1,1,1,1,1"]},
         {"Level2": ["1,1,1,1,1", "1,1,1,1,1", "1,0,1,0,1"]}
     ]
 }

Что-то не так с int levelBricks, и из json ничего не загружается должным образом. Что я делаю неправильно? Debug.Log выдает ошибку, и если я использую только Debug.Log «levelBricks», все, что я получаю, это «Levels». Я хотел бы иметь доступ к массивам на Уровне 1 и Уровне 2.

Что такое JsonUtility.FromJson?

DavidG 05.07.2018 16:13

Попробуйте использовать json.net вместо JsonUtility newtonsoft.com/json

Sean T 05.07.2018 16:14

OP использует Unity, насколько я знаю, JSON.NET недоступен в Unity. Кроме того, ошибка довольно очевидна. Ключи Level1 и Level2 динамические, классы C# этого не отражают ...

maccettura 05.07.2018 16:18

Не уверен в Unity, но вы можете выполнить десериализацию в JSON.Net с помощью этого класса public class Levels { public Dictionary<string, string[]>[] levels; }, чтобы это могло сработать.

DavidG 05.07.2018 16:23

@DavidG, это сработает? Levels - это массив объектов, использование словаря даст объект, а не массив объектов. По крайней мере, насколько мой опыт работы с Json.NET

maccettura 05.07.2018 16:24

Нет, словари не поддерживаются в библиотеке Json по умолчанию Unity docs.unity3d.com/Manual/script-Serialization.html прочтите примечание здесь

LiefLayer 05.07.2018 16:25

@maccettura Да, работает в JSON.Net, поймите! i.stack.imgur.com/BJdJq.png

DavidG 05.07.2018 16:26

@DavidG о, я пропустил обозначение массива в объекте Dictionary. Виноват! Я бы сказал, что это ответ, вы получите мой голос

maccettura 05.07.2018 16:29

@maccettura Да, неприятно, но работает. Не вижу причин, по которым вы не можете добавить JSON.Net в Unity, теперь он нацелен на Net Standard, поэтому должен работать где угодно.

DavidG 05.07.2018 16:31

@DavidG Я думаю, это потому, что Unity построен на Mono. Я попытался исследовать его, и похоже, что все пакеты Json.NET, доступные для него, являются копиями, а не сделаны Newtonsoft. Я никогда не использовал Unity, так что я далеко не разбираюсь в этом предмете.

maccettura 05.07.2018 16:32

@maccettura То же самое и здесь. На веб-сайте JSON.Net говорится, что он работает под Mono, хотя это должен быть случай импорта DLL.

DavidG 05.07.2018 16:34

Сказав это, если бы я использовал JSON.Net, я бы, вероятно, использовал специальный преобразователь для динамического свойства.

DavidG 05.07.2018 16:34

@DavidG Слишком много причин. Дело не только в работе в Windows. Unity является мультиплатформенным, и на таких платформах, как iOS, он не работает из-за AOT. Кроме того, Unity недавно добавила поддержку сети 4.5, что является минимальным требованием для Json.Net. Только те, у кого установлена ​​последняя версия Unity, могут использовать это, но проблемы с AOT все еще остаются. К счастью, есть разветвленная версия Json.Net, созданная для Unity, чтобы решить эти проблемы. здесь

Programmer 05.07.2018 16:39

Вам действительно стоит взглянуть на мой обновленный ответ. Я отредактировал только через две минуты после того, как сказал, что основная проблема была в переменной. С моим ответом вы сможете делать все с помощью базовой библиотеки единства json.

LiefLayer 05.07.2018 16:42

@Programmer Этой библиотеке уже 2 года. JSON.Net теперь нацелен на .NET Standard 1, 1.3 и 2.0 и является полностью переносимым.

DavidG 05.07.2018 16:43

Старость не имеет значения. Он по-прежнему работает и используется многими пользователями Unity. Я также слышал, что JSON.Net был обновлен для поддержки более низких версий .NET, но я не пробовал их протестировать, и простая поддержка этой версии не означает, что проблемы с сбоями, вызванные AOT или неподдерживаемыми функциями, теперь решены.

Programmer 05.07.2018 16:50

@Programmer Да, я хорошо осведомлен об этом, но сейчас я использую JSON.Net на всех платформах (Windows, .NET Core, Linux, Android, iOS и т. д.), И он отлично работает. Я не вижу причин, по которым это не сработает и в Unity

DavidG 05.07.2018 16:59

Я читаю, мне нужно просто обернуть массив [System.Serializable] публичный класс BrickGrid {[System.Serializable] публичный класс LevelGrid {публичная строка [] уровни; } общедоступные уровни LevelGrid []; }

Rach 05.07.2018 17:50

@Ranch Как я уже сказал в своем ответе, вы не сможете сериализовать 2 массива строк, если ваш класс имеет только 1 массив строк. Просто попробуйте, и вы узнаете, что мой ответ правильный, если вы хотите использовать библиотеку Unity по умолчанию (чем вы можете ее принять). Кроме того, да, обертка объекта правильная

LiefLayer 05.07.2018 17:55
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
19
469
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Основная проблема заключается в том, что переменные вашего класса должны использовать то же имя, что и ваш json. пример: публичная строка [] строк;

должно быть публичная строка [] Уровни;

РЕДАКТИРОВАТЬ. вам нужен сериализуемый класс с

    [SerializeField] ClassForLevel12[] levels;

    public ClassName() {
    }

    public ClassName(ClassForLevel12[] levels) {
      this.levels = levels;
    }

и геттер / сеттер

    public static ClassName SaveFromString(string 
jsonString) {
          return JsonUtility.FromJson<ClassName>(jsonString);
         }

    public string SaveToString() {
      return JsonUtility.ToJson(this);
    }

и сериализуемый класс ClassForLevel12 с 2

    public string[] level1;
    public string[] level2;

(и все как у другого класса).

Окончательное РЕДАКТИРОВАНИЕ. Хорошо, это то, что вам нужно, просто скопируйте, вставьте и поймите:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class MyLevels{
  [SerializeField] List<LevelGrid> levels;
  public MyLevels(){}
  public MyLevels(List<LevelGrid> levels){
    this.levels = levels;
  }
  public List<LevelGrid> Levels{
    get { return levels; }
    set { levels = value; }
  }
  //from a jsonstring to an object
  public static MyLevels SaveFromString(string jsonString){
    return JsonUtility.FromJson<MyLevels>(jsonString);
  }
  //object to json
  public string SaveToString(){
    return JsonUtility.ToJson(this);
  }

}

Второй класс

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class LevelGrid{
    [SerializeField] string[] level1;
    [SerializeField] string[] level2;
    public LevelGrid() {
    }
    public LevelGrid(string[] level1, string[] level2) {
      this.level1 = level1;
      this.level2 = level2;
    }
    public string[] Level1{
      get { return level1; }
      set { level1 = value; }
    }
    public string[] Level2{
      get { return level2; }
      set { level2 = value; }
    }
    //from a jsonstring to an object
    public static LevelGrid SaveFromString(string jsonString) {
      return JsonUtility.FromJson<LevelGrid>(jsonString);
    }
    //object to json
    public string SaveToString() {
      return JsonUtility.ToJson(this);
    }
}

Теперь ты можешь просто вызвать

    string jsonString = "{ \"levels\": [ {\"level1\": [\"1,1,1,1,1\", \"1,1,1,1,1\", \"1,1,1,1,1\"]},{\"level2\":[\"1,1,1,1,1\", \"1,1,1,1,1\", \"1,0,1,0,1\"]}]}";
    MyLevels levelBricks = MyLevels.SaveFromString(jsonString);
    Debug.Log(levelBricks.Levels[0].Level1[0]);

Класс Levels имеет свойство levels. Изменение строк на Levels не исправит это

maccettura 05.07.2018 16:25

ему все еще не хватает level1 и level2. Также переменная строк неверна как верхняя сериализуемая

LiefLayer 05.07.2018 16:28

Что происходит, когда json содержит level3, level4? Видишь ли, это неправильно

Programmer 05.07.2018 16:44

json должен отражать данные в классе. Библиотека Unity получает только базовую поддержку примитивных типов и нескольких сложных типов (например, List). Я уверен, что есть много хороших и лучших библиотек, которые лучше, чем по умолчанию Unity, но если вам нужно использовать библиотеку по умолчанию Unity3d, это правильный ответ. docs.unity3d.com/Manual/script-Serialization.html это документы

LiefLayer 05.07.2018 16:48

Я не уверен, что понимаю этот ответ. Не могли бы вы написать его точно так же, как Id-код? @Mah

Rach 05.07.2018 18:22

@Rach, теперь должно быть ясно. Вам просто нужно скопировать и вставить. Если есть что-то, чего вы не поняли, просто спросите. теперь код должен быть действительно легко читаемым.

LiefLayer 05.07.2018 20:46

Также ... вы можете использовать [SerializeField] вместо общедоступных, как в моем первом примере для переменных, если вы не хотите, чтобы они были общедоступными (в конце концов, вам нужен геттер / сеттер)

LiefLayer 05.07.2018 20:51

@Rach Хорошо, я попробовал прямо сейчас. Просто скопировать и вставить не работает, потому что есть проблема с именованием ... Я редактирую ответ прямо сейчас с полным рабочим и проверенным кодом.

LiefLayer 06.07.2018 12:08

Debug.Log (уровень Bricks.Level1] .Level2 [0]); Уровень 2 не работает @Mah

Rach 06.07.2018 12:46

@Rach, ты можешь поблагодарить меня, приняв мой ответ и проголосовав за. чтобы все знали, что это правильный ответ, чтобы посмотреть на

LiefLayer 06.07.2018 12:55

Другие вопросы по теме