tk3118’s blog

技術ブログっぽいただのブログです。

【Unity】JsonUtilityでルート配列のデシリアライズ

概要

APIのレスポンスが↓こんな感じで返ってくることないでしょうか?

[
    {
        "id": 123,
        "project_id": 234,
    },
    {
        "id": 456,
        "project_id": 567,
    },
    {
        "id": 789,
        "project_id": 890,
    },
    ...
]

しかしUnityのJson周りで JsonUtility を使用している場合
ルートが配列になってしまっている↑のようなJsonはデシリアライズ出来ないです。

これの解決法として自分は以下の2通りで対応しました。

  • 配列にも対応できるようにそれ用の機能を作る。
  • 使う側で工夫する

実装

今回はより簡単な「使う側で工夫する」方法で話していきたいと思います。

まず以下のようなクラスを追加します。

/// <summary>
///  レスポンスで返ってきている配列の1要素
/// </summary>
[Serializable]
public class Hoge
{
    ...
}

/// <summary>
///  レスポンスで返ってきている配列の1要素
/// </summary>
[Serializable]
public class ResponceData
{
    public Hoge[] root;
}

あとは、レスポンス受け取り部分で以下のような感じに 'json' を編集してあげれば大丈夫です。
※ ここでは例として 'UnityWebRequest' を使用しています。(responce変数)

var data = new ResponceData();
json = "{" + $"\"root\": {responce.downloadHandler.text}" + "}";
JsonUtility.FromJsonOverwrite(json, data);

※ 文字列補完が使えないC#のバージョンでは, string.Formatなどを代わりに使ってください。

もうちょっとだけ使いやすくする為に
以下のようなものを作っておくと同じ対応を行う時
少し便利に使えるようになると思います。

[Serializable]
public abstract class ResponceData<T>
{
    public T[] root;
}

public static void DeserializeArray<T>(T target, string json)
    where T :  ResponceData<T>
{
    string _json = "{" + $"\"root\": {json}" + "}";
    JsonUtility.FromJsonOverwrite(_json, data);
}

実際に使う際は

// 宣言しておく (Unity2019から要らない予定).
[Serializable]public class HogeData : ResponceData<Hoge>{}

[SerializeField] HogeData 


DeserializeArray(data, responce.downloadHandler.text);