二次元配列をJSONに書き込む方法【Unity・C#】

# 概要

Unityで二次元配列をJSONに入れたいと思ったことはありませんか？
今回は、マップを例に二次元配列をJSONファイルに保存する方法を紹介します。




# ポイント
classを2つに分けて保存する。

```C#:data.cs

───────
using System;

[Serializable]
public class YValue
{
    public int[] xValue = new int[23];
}

[Serializable]
public class SavingData
{
    public YValue[] yValue = new YValue[10];
}
```

JSONファイルに取り込む。

```C#:jsonWrite.cs
using System.IO

// 書き込み
public void saveData_save(SavingData saver)
{
    StreamWriter writer;
    string jsonstr = JsonUtility.ToJson(saver);
    writer = new StreamWriter(Application.dataPath + "/save/savedataJO.json", false);
    writer.Write(jsonstr);
    writer.Flush();
    writer.Close();
}

// 読み込み
public SavingData loadsaveData()
{
    string datastr = "";
    StreamReader reader;
    reader = new StreamReader(Application.dataPath+"/save/savedataJO.json");
    datastr = reader.ReadToEnd();
    reader.Close();
     
    try
    {
        return JsonUtility.FromJson<SavingData>(datastr);
    }
        
    catch (ArgumentException e)
    {
        Debug.LogError("Failed to deserialize JSON: " + e.Message);

        return null;
    }
```
この2点を押さえればOK。



# 詳しいやり方
  
今回はマップのバリューをJSONに保存します。

今回やることは次の通りになります。
1. 保存するためのSavingDataクラスを作る
2. 保存先のTrapControllerクラスでマップの値を読み込み
3. Jsonの書き込むSaveManagerクラスで入れた値を書き込む



### 保存用classを作る

jsonは二次元配列を記述することができないため、まず、YValueクラスとSavingDataクラスの2つに分けます。
SavingDataクラスで、YValueの配列YValueクラスでintの配列を作ることにより、擬似的な二次元配列を表現します。

```C#:date.cs
using System;
    
[Serializable]
public class YValue
{
    public int[] xValue = new int[23];
}

[Serializable]
public class SavingData
{
    public YValue[] yValue = new YValue[10];
}
```

### 保存先で値を代入する


SavingDataクラスをインスタンスとして関数を

```C#:dataSystem.cs
// save
public SaveMapping saveMapping = new SaveMapping();
public GameObject sM_trap;
    
void Start()
{
    // save setting
    saveMapping.saveX = transform.position.x;
    saveMapping.saveY = transform.position.y;

    int changeX = (int)saveMapping.saveX;
    int changeY = (int)saveMapping.saveY;

    // 連番変換
    if (changeX < 0)
    {
        changeX = 11 + changeX;       
    }
        
    else if (changeX >= 0)
    {
        changeX += 11;
    }
        
    if (changeY < 0)
    {
        changeY = (changeY * -1) + 4;
    }
        
    else if (changeY >= 0)
    {
        changeY = 4 - changeY;
    }

    saveMapping.saveCode = 3;
    sM_trap = GameObject.Find("SaveManager");
    saveMapping.sM = sM_trap.GetComponent<SaveManager>();
    saveMapping.sM.InputTo(changeY, changeX,saveMapping.saveCode);        
    // save End

}
```

### Jsonに書きこむ
StreamWriter 変数[writer]を用意string型の変数に保存用のクラスをJsonUnity.ToJsonでJSON型変換する[writer]にStreamWriter(パス+ファイル名,false)インスタンスを入れる[writer]のStreamWriterインスタンスのWrite、Flushを使用してJSONの中身を書き込む書き終わったらwriterの書き込みを終了させる

```C#
using System.IO
//save activety
public void saveData_save(SavingData saver)
{
    StreamWriter writer;
    string jsonstr = JsonUtility.ToJson(saver);
    writer = new StreamWriter(Application.dataPath + "/save/savedataJO.json", false);
    writer.Write(jsonstr);
    writer.Flush();
    writer.Close();
}
```


### サンプルコード
```C#:StageData.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;


[Serializable] public class StageValueX
{
    public List<int> xValue;
}


[Serializable] public class StageValueY
{
    public List<StageValueX> yValue;
}


[CreateAssetMenu(fileName = "StageDate", menuName = "GameDate/StageDateBase")]  
public class StageDate : ScriptableObject{
    public List<StageValueY> stageList;
}


[Serializable]public class Total
{
    public int EnemyKill;
    public float PlayingTime;
    public int SetTrap;
}

public class GameManeger : MonoBehaviour
{
    //@result-Use result menu.

    //map[y,x]  で管理してる
    /* 0= なんもない
     * 1=　プレイヤー
     * 2=　敵
     * 3=　トラップ
     */
    public List<int> enemyManagerID = new List<int>();

    public Transform player;
    public GameObject enemy;
    public GameObject trap;

    public GameObject menu;

    int[,] map = new  int[9,17] {
        { 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2,2 },
        { 2, 0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 0, 2,2 },
        { 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 2,2 },
        { 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 2,2 },
        { 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 2,2 },
        { 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,2 },
        { 2, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,2 },
        { 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 2,2 },
        { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,2 }
    };
    int mapNumber = 0;
    int y_number = 0;
    int x_number = 0;

    public SpriteRenderer background;
    [SerializeField] GameDate gamestageDateBase;


    public bool EndGame = false;
    public bool Use_menuListNumber = true;

    // Start is called before the first frame update
    void Start()
    {
        if (Use_menuListNumber)
        {
            stageNumber = MenuManager.menuStageNumber;
        }

        background.sprite = gamestageDateBase.stagelist[stageNumber].background;
        //SetStage 
        for(int y = 4; y >=  -5; y--)
        {
            for(int x = -11; x <= 11; x++)
            {
                if (x_number > 22)
                {
                    x_number = 0;
                }
                
                mapNumber = stagedate.stageList[stageNumber].yValue[y_number].xValue[x_number];

                switch (mapNumber)
                {
                    case 1:
                        player.position = new Vector3(x, y, 0);
                        break;

                    case 2:
                        Instantiate(enemy, new Vector3(x, y, 0), Quaternion.identity);
                        break;

                    case 3:
                        Instantiate(trap, new Vector3(x, y, 0), Quaternion.identity);
                        break;
                }
                mapnumberMix = mapNumber % 100;
                int mapcheack = mapNumber - mapnumberMix;
                
                x_number++;
            }
            y_number++;
        }
    }
}
```


以上です、ご覧いただきありがとうございました。