Unity:超高速なJsonパーサ Utf8Json+WebGLの使い方、JsonUtilityの問題点

最終更新日



はじめに

Unity で Json を使いたい場合、標準の JsonUtility を使った事はありますでしょうか?しかしこの JsonUtility は痒い所に手が届かない子ですごく面倒が発生しますので今回は、Utf8Json をご紹介させていただきます。

JsonUtility の問題点

以下に私が感じている、JsonUtilityの問題点を書かせていただきます。

  • 可変長配列(List)が扱えない
  • 辞書型(Dictionary)が扱えない
  • Json で Null が指定できない
    • Null を指定するとデフォルトコンストラクタで作られた空クラスが生成される。
  • root 要素に 配列([])や “文字列”が渡せない、Object型じゃないといけない

どうでしょうか、結構厄介ですよね。

一番致命的なのは、List が使えない、Null が指定できないとかでしょうか、ここら辺が対応していないだけでも仕事で使うことを考えるとぞっとします( ;∀;)

Utf8Json の使い方

Utf8Json を使う前に、まずは使うメリットを説明させていただきます。

メリット

上記で書かせていただいた、JsonUtility の問題点はすべて解消しています。

しかも、高速に動作します。公式で説明されている以下の表を確認していただければわかりますがかなり早いJsonパーサーとなります。

Unity に取り込む

Utf8Json のリリースページ にある .unitypackage をダウンロードしましょう。

Unity を起動して、ダウンロードしてきたパッケージを Assetsフォルダ にドラッグアンドドロップしましょう。

エラーの対応

このままですと、以下のようなエラーが発生するのでこのエラーを解消しましょう。

Assets\Scripts\Utf8Json\Shims\Reflection.cs(203,52): error CS0246: The type or namespace name 'TypeBuilder' could not be found (are you missing a using directive or an assembly reference?)
Assets\Scripts\Utf8Json\Internal\AutomataDictionary.cs(91,28): error CS0227: Unsafe code may only appear if compiling with /unsafe. Enable "Allow 'unsafe' code" in Player Settings to fix this error.
Assets\Scripts\Utf8Json\Internal\AutomataDictionary.cs(189,31): error CS0246: The type or namespace name 'ILGenerator' could not be found (are you missing a using directive or an assembly reference?)

Unity ではメニューの「File > Build Settings > Player Setting」を開いて書きの設定を行いましょう。

「Api Compatibility Level」を「.NET 4.x」に、
「Allow ‘unsafe’ code」のチェックボックスをON(オン)にしましょう。

C#オブジェクトから Json に変換

Jsonへの変換は簡単です、JsonSerializer.ToJsonString を使いましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using Utf8Json;

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

public class NewBehaviourScript : MonoBehaviour {
	void Start () {
        var p = new Person { Age = 99, Name = "foobar" };

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

        // byte[] -> Object
        var p2 = JsonSerializer.Deserialize<Person>(result);

        // Object -> String
        var json = JsonSerializer.ToJsonString(p2);
    }
}

Json からC#オブジェクトに変換

自作クラスへの変換も簡単です、JsonSerializer.Deserialize を使いましょう。

using UnityEngine;
using Utf8Json;

public class Test
{
    public string foo { get; set; }
    public int bar { get; set; }

    public Nest nest { get; set; }
}

public class Nest
{
    public bool foobar { get; set; }
}

public class NewBehaviourScript : MonoBehaviour
{
    void Start()
    {
        var test = JsonSerializer.Deserialize<Test>(@"{""foo"":""json"",""bar"":100,""nest"":{""foobar"":true}}");
    }
}

自作クラスに変換するのがめんどくさい場合、dynamicオブジェクトに変換しましょう、同じくJsonSerializer.Deserialize を使いましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using Utf8Json;

public class NewBehaviourScript : MonoBehaviour {
	void Start () {
        var json2 = JsonSerializer.Deserialize<dynamic>(@"{""foo"":""json"",""bar"":100,""nest"":{""foobar"":true}}");

        var r1 = json2["foo"]; // "json" - dynamic(string)
        var r2 = json2["bar"]; // 100 - dynamic(double), it can cast to int or other number.
        var r3 = json2["nest"]["foobar"]; // true
    }
}

Unity Jsonビューワが便利

Json形式ってデータ量が肥大化すると、目的のデータまで探しに行くのがすごく難しくなりますよね、そこでUnityのエディタ拡張「Json Viewer」を使うとUnityエディタ上でJsonを扱えるのですごく便利です。

Json Viewer

WebGLでの使い方

Utf8Json を Unity のWebGLプラットフォームで使おうとすると、Jsonで使うクラスを扱うための特殊なクラスを生成(ジェネレート)して、Utf8Json にエンジンとして登録しないといけないです。

ツールをダウンロード

Utf8Json のリリースページ にあるツールをダウンロードしましょう。

Utf8JsonGenerated.cs の生成

ツールをダウンロードしたら適当なフォルダに解凍してください。

このツールでは、フォルダを指定するとそこに含まれるC#ソースコードから、このC#ソースコードをJsonとして変換できるようにするための、Utf8JsonGenerated.cs というソースコードを出力します。

以下にサンプルのコマンドを記述しますので、皆さんの環境に合わせて使ってください。

Utf8Json.UniversalCodeGenerator\win-x64\Utf8Json.UniversalCodeGenerator.exe -d ".\Assets\JsonDto" -o ".\Assets\Utf8JsonGenerated.cs"

Utf8JsonGenerated.cs を取り込む

どこかのオブジェクトの Start() メソッドなどで、Utf8Json.Resolvers を使って、Utf8Json.Resolvers.GeneratedResolver.Instance を登録してください。

GeneratedResolver 以外の、~Resolver などは必要に応じてコメントにしたり外したりしてください。
 ※Jsonで使う型により必要な変換クラスが違います。


    Start() {
        Utf8Json.Resolvers.CompositeResolver.RegisterAndSetAsDefault(
            Utf8Json.Resolvers.GeneratedResolver.Instance,
            Utf8Json.Resolvers.DynamicGenericResolver.Instance,
            Utf8Json.Resolvers.BuiltinResolver.Instance
            // Utf8Json.Resolvers.EnumResolver.Default,
            // Utf8Json.Resolvers.DynamicObjectResolver.Default
            // Utf8Json.Resolvers.AttributeFormatterResolver.Instance,
            // Utf8Json.Resolvers.CompositeResolver.Instance,
            // Utf8Json.Unity.UnityResolver.Instance
            // Utf8Json.Resolvers.CompositeResolver.Instance
            // It does not work under IL2CPP and caused crash.
            // Utf8Json.Resolvers.StandardResolver.Default
        );
    }







よければ、SNSにシェアをお願いします!

3件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

コメントする