LoginSignup
3
0

More than 1 year has passed since last update.

Unityから複雑なJSONファイルを読み込む方法

Posted at

前書き

友達に頼まれ、Unityでの作業を手伝う機会があったのですが、C#ではJson読み込みでひと工夫必要らしく、結構苦労して調べたので共有という感じの記事になります。

結論

Newtonsoftというライブラリを使用します。

というのも、JsonUtilityなどでも読み込めることは読み込めますが、事前にjsonの構造に対応付けたクラスを作成する必要があったり、また例えば辞書の配列など複雑なデータ型は読み込めないようです。(NULLになる)

他の言語のように、json文字列から一発で辞書型に対応付けてほしいなぁと思っていたところ、Newtonsoftというライブラリを使用すると一発でできるそうだったので、以下このライブラリの説明になります。

使用する名前空間

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

ソースコード上部に上記を追加します。

※ Unity2020からはデフォルトでインストールされているそうです

文字列からJObjectへの変換

string jsonText = "{ ... }"; // 何かしらのJSON文字列
JObject obj = JObject.Parse(jsonText); // これでJSONがまとめてパースされる

JObjectの読み込み

これでobj変数にJSONのパース結果のJObjectというオブジェクトが格納されました。
またJObjectの中にはJTokenというオブジェクトなどが入れ子になって入っているイメージになるそうです。

参考ページ

真下のオブジェクトを取得

obj["key_name"]; // JTokenオブジェクトが帰ってくる

真下の値を取得

obj["key_name"].Value<int>(); // intの所には要素の型名を入れる

入れ子のオブジェクトを取得

obj["key1"]["key2"]; // JTokenオブジェクトが帰ってくる

配列を取得

foreach文で回し、用意していたListにAddしていく感じになります。

string jsonText = "{ 'key1': [1, 2, 3] }";

var obj = JObject.Parse(jsonText);
var arr = new List<int>(); // 取得結果がこのリストに格納される

foreach (var jtoken in obj["key1"].Children())
{
    arr.Add(token.Value<int>());
}

Debug.Log(arr);

ネストした辞書を取得

SelectToken()というメソッドを使うと、ネストした辞書の要素にアクセス可能になります。
取得結果はJTokenなどのオブジェクトになるので、Values<型名>()で変換します。

string jsonText = @"
{ 
    'key1': {
        'key2': {
            'key3': 10
        }
    }
}
";
var obj = JObject.Parse(jsonText);

var num = obj.SelectToken("key1.key2.key3").Value<int>();

// 10が出力される
Debug.Log(num);

辞書の配列を取得

調べたところSelectToken("key1[0].value1")などの書き方が可能とのこと。
SelectTokenの第一引数にはJSONPathというものを指定できるため。

SelectTokenにJSONPathを指定してValue<型名>()を使い、要素を取得。

string jsonText = @"
{ 
    'key1': [
        {
            'key2': 'value2',
            'key3': 'value3'
        },
        {
            'key4': 'value4',
            'key5': 'value5'
        }
    ]
}
";
var obj = JObject.Parse(jsonText);

// key1[1]のようにSelectTokenでは添え字も指定可能
// JSONPathというXMLPathのような規格に準拠しているとのこと
var value5 = obj.SelectToken("key1[1].key5").Value<string>();

// "value5"が出力される
Debug.Log(value5);

(参考) ソースコード例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;


public class NewBehaviourScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // JSON文字列をファイルから読み込み
        string json = Resources.Load<TextAsset>("test").ToString();

        // JSON文字列をJTokenオブジェクトにパース
        JObject obj = JObject.Parse(json);

        // 辞書の配列を回す
        foreach (var dic in obj["part_candidates"])
        {
            Debug.Log(dic);
            
            // 辞書の中身を読み込む
            // {"1": [0.0, 0.1, 0.2], "2": [0.0, 0.1, 0.2]} のようなデータ
            foreach (var key in dic.Children())
            {
                // double配列の中身を保持するリスト
                List<double> arr = new List<double>();

                foreach (var value in key.Children())
                {
                    // 配列の中の小数を配列に追加する
                    foreach (var n in value.Children())
                    {
                        arr.Add(n.Value<double>());
                    }
                }
                double x = arr[0];
                double y = arr[1];
                double z = arr[2];

                Debug.Log(x + ", " + y + ", " + z);
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

以上

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0