ぼっちブログ

個人ゲーム開発者やっています。主に購入したUniyアセットの使用感を書いていきます。

【Unity】Utf8JsonでJSONシリアライズをする

ゲームデータのJSON化にUtf8Jsonを使おうとしたけど、使うまでに苦戦したので、そのメモ書きです。

バージョン情報

  • Unity 2018.3.0b12
  • Utf8Json Ver 1.3.7

Utf8Jsonとは

UniRxで有名なneueccさんが開発しているJSONリアライザです。

neue cc - Utf8Json - C#最速のJSONシリアライザ(for .NET Standard 2.0, Unity)

どういうものかは上記のサイトを見てもらうとして、個人的にはプロパティからシリアライズ・デシリアライズする点が、JsonUtilityのフィールドを直接シリアライズ・デシリアライズする点より融通が利きそうでグッドです。

Utf8Jsonのインポート

以下から.unitypackageを落として、Unityにインポートします。

github.com

インポートしただけではエラーが出たので、Edit→Project Settings...→Playerで以下の設定を行います。

  • Api Compatiblity Levelを.Net 4.xに変更
  • Allow 'unsafe' Codeのチェックを入れる

Api Compatibility Levelを.Net 4.xに変更

Allow 'unsafe' Codeにチェックを入れる

これでビルドは通る、はず。

Utf8Jsonでシリアライズ

シリアライズはJsonSerializer.SerializeかJsonSerializer.ToJsonStringで、デシリアライズはJsonSerializer.Deserializeを使います。

JsonUtilityと違って、シリアライズ対象はプロパティなので注意。

public class Person
{
    public string Name { get; set; }

    public int Age { get; set; }
}
using UnityEngine;
using Utf8Json;

public class NewBehaviourScript : MonoBehaviour
{
    void Start()
    {
        var p = new Person { Age = 18, Name = "オーエー" };

        // Object -> byte[] (UTF8)
        var bytes = JsonSerializer.Serialize(p);

        // Object -> string
        var json = JsonSerializer.ToJsonString(p);
        Debug.Log(json);

        // string -> Object
        var p2 = JsonSerializer.Deserialize<Person>(json);
        Debug.Log($"Age={p2.Age},Name={p2.Name}");
    }
}

Utf8Jsonでシリアライズ・デシリアライズ結果

シリアライズするプロパティを指定する

Utf8Jsonはデフォルトですべてのプロパティをシリアライズしますが、シリアライズしたくないプロパティは[IgnoreDataMember]を使います。

また、シリアライズするときの名前を変えたい場合は、[DataMember(Name = string)]を使います。

using System.Runtime.Serialization;

public class Person
{
    [IgnoreDataMember]
    public string Name { get; set; }

    [DataMember(Name = "age")]
    public int Age { get; set; }
}

シリアライズしたいプロパティを指定してシリアライズした結果

IL2CPPビルドでJSONシリアライズする

IL2CPPビルドだとUtf8Jsonは動かず、シリアライズしようとするとエラーが出ます。

IL2CPPビルドでJSONシリアライズしてエラー

IL2CPPで使えるようにするには、以下からコードジェネレーターUtf8Json.UniversalCodeGenerator.zipをダウンロードして使う必要があります。

github.com

ダウンロードしたファイルを解凍して、コマンドプロンプトで以下を実行します。

Utf8Json.UniversalCodeGenerator.exe -d [対象スクリプトのディレクトリパス] -o Utf8JsonGenerated.cs

生成したUtf8JsonGenerated.csを使うには、アプリ起動時にリゾルバに登録する必要があります。

Utf8JsonGenerated.csをUnityプロジェクトにインポートして、以下のようにアプリ起動時にリゾルバに登録するようにします。

using UnityEngine;

public static class RuntimeInitializeOnLoad
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    private static void BeforeSceneLoad()
    {
        Utf8Json.Resolvers.CompositeResolver.RegisterAndSetAsDefault(
            // use generated resolver first, and combine many other generated/custom resolvers
            Utf8Json.Resolvers.GeneratedResolver.Instance,

            // Systemのライブラリを使う場合は追記
            Utf8Json.Resolvers.BuiltinResolver.Instance,

            // Unityのライブラリを使う場合は追記
            Utf8Json.Unity.UnityResolver.Instance

            // set StandardResolver or your use resolver chain
            // IL2CPPでは使えないので、コメントアウト
            // Utf8Json.Resolvers.StandardResolver.Default
        );
    }
}

IL2CPPでJSONシリアライズ結果

後は、コードジェネレートする部分を自動化したいけど記事が長くなってきたので、また今度で。