PR

[Unity]JsonUtilityについてまとめてみた

Unity

はじめに

みなさんはUnityでJSON(JavaScript Object Notation)を利用しているでしょうか?

通常ゲーム制作では使うことはあまりないかも知れませんが、通信系の処理を入れている場合は利用していることが多いでしょう。

今回はUnityが用意してくれているJsonUtilityに関して今更ながら、まとめてみました。

環境

  • Unity 2021.1.13f1

JSONとは?

JavaScript Object Notation(JSON、ジェイソン)はデータ記述言語の1つである。軽量なテキストベースのデータ交換用フォーマットでありプログラミング言語を問わず利用できる[1]。名称と構文はJavaScriptにおけるオブジェクトの表記法に由来する。

https://ja.wikipedia.org/wiki/JavaScript_Object_Notation

つまり、XMLとかのようにデータやり取りの際に決められたフォーマットみたいなものです。

そして、こんな感じのフォーマットのことです。

{
    "name": "hogehoge",
    "age": 20,
    "engineer": true
}

JsonUtilityの基本的な使い方

JSONを特定のクラスにパースしたい場合

使い方は非常に簡単です。下記のようなJSONを想定します。

{
    "name": "hogehoge"
    "age": 20,
    "engineer": true
}

まずはJSONのパラメーターのキーと型を揃えた構造のクラスを用意します。

[System.Serializable]
public class User
{
    public string name;
    public int age;
    public bool engineer;

    public User(string name, int age, bool engineer)
    {
        this.name = name;
        this.age = age;
        this.engineer = engineer;
    }

    public override string ToString()
    {
        return string.Format("{0}, {1}, {2}", name, age, engineer);
    }
}

あとはJsonUtility.FromJsonを利用してパースするだけです。

    // 「\"」は「"」をエスケープしてるだけです.
    string json = "{\"name\":\"hogehoge\",\"age\":20,\"engineer\":true}";

    var user = JsonUtility.FromJson<User>(json);
    Debug.Log(user.ToString());
    // hogehoge, 20, True

簡単ですよね?

上記のUserクラスに[System.Serializable]という属性とつけていますが、つけていなくてもパースは出来ます。しかし、Unityのリファレンス資料を見るとつけろとなっているので忘れずにつけましょう

クラスからJSON文字列へ変換

次に逆パターンのクラスからJSON文字列に変換する場合です。

上記のUserクラスをそのまま利用して説明します。

やり方、クラスをインスタンスしてそのままJsonUtility.ToJsonを利用するだけです。

    var user = new User(name: "fugafuga", age: 30, engineer: false);
    Debug.Log(JsonUtility.ToJson(user));
       // {"name":"fugafuga","age":30,"engineer":false}

簡単でしょ?

応用編

上記では簡単なJSONの処理の紹介だったので、次は複雑なJSON構造だった場合の時の処理です。

配列の場合

以下のような配列の場合です。

{
    "names": [
        "1人目だよ",
        "2人目だよ"
    ],    
    "ages": [
        10,
        20
    ],
    "engineers": [
        false,
        true
    ]
}

やり方は2通りあります。配列リストを使います

[System.Serializable]
public class Users1
{
    public string[] names;
    public int[] ages;
    public bool[] engineers;
}

[System.Serializable]
public class Users2
{
    public List<string> names;
    public List<int> ages;
    public List<bool> engineers;
}
    string json = "{\"names\": [\"1人目だよ\",\"2人目だよ\"],\"ages\": [10,20],\"engineers\": [false,true]}";

    var users1 = JsonUtility.FromJson<Users1>(json);
    Debug.LogFormat("{0}, {1}, {2}", users1.names[0], users1.ages[0], users1.engineers[0]);
    // 1人目だよ, 10, False
    Debug.LogFormat("{0}, {1}, {2}", users1.names[1], users1.ages[1], users1.engineers[1]);
    // 2人目だよ, 20, True

    var users2 = JsonUtility.FromJson<Users2>(json);
    Debug.LogFormat("{0}, {1}, {2}", users2.names[0], users2.ages[0], users2.engineers[0]);
    // 1人目だよ, 10, False
    Debug.LogFormat("{0}, {1}, {2}", users2.names[1], users2.ages[1], users2.engineers[1]);
    // 2人目だよ, 20, True

JSONの配下にオブジェクト構造がある場合

下記のようにオブジェクトの配下にオブジェクト構造がある場合です。

{
    "user": {
        "name": "いれこだよ",
        "age": 40,
        "engineer": true
    }
}

このような場合はパースしたいクラスを同じような構造にすれば大丈夫です。

[System.Serializable]
public class Parents
{
    // Userクラスは上記と同じ構造です.
    public User user;
}
    string json = "{\"user\": {\"name\": \"いれこだよ\",\"age\": 40,\"engineer\": true}}";

    var parents = JsonUtility.FromJson<Parents>(json);
    Debug.Log(parents.user.ToString());
    // いれこだよ, 40, True

オブジェクトが配列だった場合

下記のようなJSONでusersが配列の場合です。

{
    "users": [
        {
            "name": "1人目だよ",
            "age": 10,
            "engineer": false
        },
        {
            "name": "2人目だよ",
            "age": 20,
            "engineer": true
        }
    ]
}

やり方は2通りあります。配列リストを使います

[System.Serializable]
public class Parents1
{
    // 配列パターン.
    public User[] users;
}

[System.Serializable]
public class Parents2
{
    // リストパターン.
    public List<User> users;
}
    string json = "{\"users\": [{\"name\": \"1人目だよ\",\"age\": 10,\"engineer\": false},{\"name\": \"2人目だよ\",\"age\": 20,\"engineer\": true}]}";

    // 配列パターン.
    var parents1 = JsonUtility.FromJson<Parents1>(json);
    Debug.Log(parents1.users[0].ToString());
    // 1人目だよ, 10, False
    Debug.Log(parents1.users[1].ToString());
    // 2人目だよ, 20, True

    // リストパターン.
    var parents2 = JsonUtility.FromJson<Parents2>(json);
    Debug.Log(parents2.users[0].ToString());
    // 1人目だよ, 10, False
    Debug.Log(parents2.users[1].ToString());
    // 2人目だよ, 20, True

JSONの始まりが配列だった場合

こういういきなり配列から始まるパターンです。

[
    {
        "name": "1人目だよ",
        "age": 10,
        "engineer": false
    },
    {
        "name": "2人目だよ",
        "age": 20,
        "engineer": true
    }
]

JSONの始まりが配列やオブジェクト配列の場合はJsonUtilityではパースすることはできません。

JSONの形式を変えてもらうか、JsonUtility以外のものを利用しましょう。

私はJsonUtility以外の方法をあまり知らないので、方法がわかりませんでした。

さいごに

JSONはいろいろなところで使うので覚えておいて損はないと思います。

おすすめ参考書

コメント

タイトルとURLをコピーしました