ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

Unity - Json.NET:List, Dictionary などをJSONで扱う -

初めに

 データのセーブに用いられる JsonUtility ではList や Dictionary などは対象外なため、制約が強いです。そこでより汎用性の高い Json.NET についてまとめます。

Json.NETのドキュメント

www.newtonsoft.com

Json.NET の導入の仕方

 PackageManager の Add package from git URL... に次の URL を入力すれば導入できます。

com.unity.nuget.newtonsoft-json@3.0

 Newtonsoft Json が追加されれば ok です。

※AssetStoreなどほかの導入方法もあります。

Json.NET の使い方

使い方の基本

JsonConvert.SerializeObject:Unity オブジェクトをJSON形式にシリアライズ

JsonConvert.DeserializeObject:JSON形式を Unity オブジェクトにデシリアライズ

(例1)最も基本的なスクリプト
 オブジェクトをシリアライズ、デシリアライズするだけのスクリプト

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;  //追加

public class JsonSample : MonoBehaviour
{
  private void Start()
  {
     int num = 1;

    //シリアライズ
     var jsonint = JsonConvert.SerializeObject(num);

     Debug.Log(jsonint);

     //デシリアライズ
     var outputnum = JsonConvert.DeserializeObject(jsonint);
     Debug.Log(outputnum);
  }
}

(実行結果)


(例2)List や配列がまざっている、保存するデータのクラスを作っている

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;  //追加

public class JsonSample : MonoBehaviour
{
  //JSONに変換するオブジェクトのクラスを取得
  private JsonType jsonType = new JsonType();

  private void Start()
  {
    jsonType.Key1 = "test01";
    jsonType.Key2 = 2;
    jsonType.Key3 = new List<string>();
    jsonType.Key3.Add("aaa");
    jsonType.Key3.Add("bbb");
    float[] numbers = new float[]{0.1f, 0.2f};
    jsonType.Key4 = new List<float[]>();
    jsonType.Key4.Add(numbers);

    //シリアライズ
    var jsonBody = JsonConvert.SerializeObject(jsonType);

    Debug.Log(jsonBody);
     
     //デシリアライズ
     JsonType outPut = JsonConvert.DeserializeObject<JsonType>(jsonBody);
     Debug.Log(outPut.Key1);
     Debug.Log(outPut.Key2);
     Debug.Log(outPut.Key3);
     Debug.Log(outPut.Key4);
  }
}

//JSONに変換するオブジェクトのクラス
[JsonObject]
public class JsonType
{
    [JsonProperty("Key1")]
    public string Key1 { get; set; }

    [JsonProperty("Key2")]
    public int Key2 { get; set; }

    [JsonProperty("Key3")]
    public List<string> Key3 { get; set; }

    [JsonProperty("Key4")]
    public List<float[]> Key4 { get; set; }
}

(実行結果)

ファイルに書き込み、セーブ・ロードできるようにする

 JsonUtility の際に作ったスクリプトを改造し、ファイルに書き込みができるようにします。FromJson や ToJson などの JsonUtility の機能を使っていた部分を変えています。ファイルの書き込み、読み込みについての説明は JsonUtility の記事をご覧ください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using UnityEditor;  //AssetDatabaseを使うために追加
using System.IO;  //StreamWriterなどを使うために追加
using System.Linq;  //Selectを使うために追加

public class JsonSample : MonoBehaviour
{
  private JsonType jsonType = new JsonType();

  //保存先
  string datapath;

  void Awake()
  {
    //保存先の計算をする
    //これはAssets直下を指定. /以降にファイル名
    datapath = Application.dataPath + "/TestJson02.json";
  }

  private void Start()
  {
    JsonType jsonData = new JsonType();

    //JSONファイルがあればロード, なければ初期化関数へ
    if(FindJsonfile())
    {
      jsonData = loadJsonData();
      Debug.Log(jsonData.Key1);
    }
    else
    {
      Initialize();
    }
  }

  //セーブするための関数
  public void saveJsonData(string text)
  {
    StreamWriter writer;

    //JSONファイルに書き込み
    writer = new StreamWriter(datapath, false);
    writer.Write (text);
    writer.Flush ();
    writer.Close ();
  }

  //JSONファイルを読み込み, ロードするための関数
  public JsonType loadJsonData()
  {
    string datastr = "";
    StreamReader reader;
    reader = new StreamReader (datapath);
    datastr = reader.ReadToEnd ();
    reader.Close ();

    return JsonConvert.DeserializeObject<JsonType>(datastr);
  }

  //JSONファイルがない場合に呼び出す初期化関数
  //初期値をセーブし, JSONファイルを生成する
  public void Initialize()
  {
    jsonType.Key1 = "test01";
    jsonType.Key2 = 2;
    jsonType.Key3 = new List<string>();
    jsonType.Key3.Add("aaa");
    jsonType.Key3.Add("bbb");
    float[] numbers = new float[]{0.1f, 0.2f};
    jsonType.Key4 = new List<float[]>();
    jsonType.Key4.Add(numbers);

    var jsonBody = JsonConvert.SerializeObject(jsonType);

    saveJsonData(jsonBody);
  }

  //JSONファイルの有無を判定するための関数
  public bool FindJsonfile()
  {
    //TestJson02はファイル名
    string[] assets = AssetDatabase.FindAssets("TestJson02");
    Debug.Log(assets.Length);
    if(assets.Length != 0)
    {
      string[] paths = assets.Select(guid => AssetDatabase.GUIDToAssetPath(guid)).ToArray();
      Debug.Log($"検索結果:\n{string.Join("\n", paths)}");
      return true;
    }
    else
    {
      Debug.Log("Jsonファイルがなかった");
      return false;
    }
  }
}

[JsonObject]
public class JsonType
{
    [JsonProperty("Key1")]
    public string Key1 { get; set; }

    [JsonProperty("Key2")]
    public int Key2 { get; set; }

    [JsonProperty("Key3")]
    public List<string> Key3 { get; set; }

    [JsonProperty("Key4")]
    public List<float[]> Key4 { get; set; }
}

LINQ to JSONについて

 JSON オブジェクトを LINQ を用いて操作するため機能として、LINQ to JSON があります。

 名前空間に次のテキストを入れることで使用できます。

using Newtonsoft.Json.Linq;

ドキュメント

www.newtonsoft.com

使い方

 通常の LINQ と違い、JSONのままデータを扱います。JObject や JToken、JArray、JValue などの概念が必要になります。
次のサイトでとてもわかりやすく解説してくださっています。

tech.packetroom.net

最後に

 JsonUtility は制約が強く、不便さを感じる場面もあります。Json.NETは使えるに越したことはないように感じます。