【Unity】UnityのネイティブプラグインでJsonを使ってやり取りしたい。【シリアライズ】

# はじめに
今日は昨日の続き、UnityとAndroidネイティブプラグインのやり取りにJsonを使おうと思います。
今回はAndroidですが、特にAndroid特有のものは使っていないので応用は聞くと思います。しらんけど
昨日の記事はこちら

https://qiita.com/AtsuAtsu0120/items/c8898c4888610e1271af?utm_campaign=post_article&utm_medium=twitter&utm_source=twitter_share

# 昨日の復習
ネイティブプラグインのJavaコードからUnityのC#コードに結果を返すときは`UnitySendMessage`関数を使うんでした。
ただ、文字列しか返せないので微妙です。

今回はJsonで渡してオブジェクトごと通信してやろうという会です。
# JavaにおけるJson
JavaではJsonを扱う際に**Jackson**というライブラリを使うのが主流なようです。
導入していきます。
## Jacksonの導入
簡単です。ネイティブプラグインの`build.gradle`に追記するだけです。
```gradle:build.gradle
...//略
dependencies {
    //追記部分
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.15.0-rc1'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.15.0-rc1'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.15.0-rc1'
    //ここまで
    ...//略
```
これでsyncしてもらえればJava側は導入完了です。らくちん。ただ、あとでUnityにもこちらを書かないといけません。

## Jacksonの使い方
Jacksonがメインではないので簡単に…
```java:AndroidNativeDialog.java
   public static TimePickerDialog.OnTimeSetListener TimerDialogCallback() {
        return new TimePickerDialog.OnTimeSetListener() {
            @Override
            public void onTimeSet(TimePicker timePicker, int hour, int min) {
                //オブジェクト化
                SerializedTime time = new SerializedTime(hour, min);
                

                //Json化（ここからJackson）
                ObjectMapper mapper = new ObjectMapper();
                String timeJson = null;

                try {
                    timeJson = mapper.writeValueAsString(time);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                //（ここまで）

                //Unityに送信
                UnityPlayer.UnitySendMessage("listenerObj", "TimeSetCallback", timeJson);
            }
        };
    }
```
今回シリアライズしているのはこのクラス。（これぐらいならJsonじゃなくてもいいやろとか言わない）
ちなみに、`java.io.Serializableインターフェース`をクラスに実装しているとエラーになりました。
```java:SerializedTime.java
public class SerializedTime {
    private int hour;
    private int min;

    public SerializedTime(int hour, int min) {
        this.hour = hour;
        this.min = min;
    }

    public int getHour() {
        return hour;
    }
    public int getMin() {
        return min;
    }

    public void setHour(int hour) {
        this.hour = hour;
    }
    public void setMin(int min) {
        this.min = min;
    }
}
```
`ObjectMapper`というクラスをインスタンス化して、そのインスタンスの`writeValueAsString()`メソッドを使うだけです。
このメソッドの戻り値から結果である文字列が取得できます。

そして、`UnitySendMessage()`メソッドでC#側に送信します。
# UnityにおけるJson
Unityにはみんな大好き**JsonUtility**大先生がいらっしゃいますよね。
結構好きでよく使ってます。
## 値を受け取る。
Jsonから変換するクラスを作ります。
```C#:TestJsonClass.cs
using System;

[Serializable]//これ大事
public class TestJsonClass
{
    public int hour;
    public int min;

    public TestJsonClass(int min, int hour)
    {
        this.min = min;
        this.hour = hour;
    }
}
```
`Serializable`属性だけ忘れないでくださいね。
>ちなみに、知らなかったんですが`setter`と`getter`を付けるとシリアライズされないみたいです。注意

JsonUtilityで受け取ったJson形式の文字列を変換していきます。
```C#:ListenerTest.cs
using UnityEngine;

public class ListenerTest : MonoBehaviour
{
    public void TimeSetCallback(string message)
    {
        var json = JsonUtility.FromJson<TestJsonClass>(message);

        Debug.Log($"{json.hour}:{json.min}");
    }
}
```
よっしゃ！勝ち！！！、、、と言いたいんですけど私はここから4時間ぐらいの戦いに入るとは思ってませんでした。
でも大丈夫。5秒で解決します。そうこの記事ならね。

# UnityのビルドにJacksonを含める。
UnityはAndroidのビルド時に、aarのビルド時にも作った`build.gradle`ではなく全く別のものを使います。
なので、Jacksonねぇじゃねぇか！って怒られます。

ただ、Unityの`build.gradle`はカスタマイズが加えられておりいくつかのファイルに分かれています。
どこに書くか、、、これをネットで探しまくりました。
## 正解発表
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083521/14b25f0b-ee9a-d5f6-fcb9-0e1483e173e2.png)
まず、プロジェクト設定（Project Settings）の下線部、`Custom Lancher Gradle Template`にチェックを入れてください。
そうすると、そのgradleファイルが生成され、パスも下に記載されます。
そのファイルを編集していきます。
```gradle:lancherTemplate.gradle
...//略
dependencies {
    implementation project(':unityLibrary')
    // 追記部分
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.15.0-rc1'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.15.0-rc1'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.15.0-rc1'
    // ここまで
    }
...//略
```
ここに先ほどと全く同じものを記載すれば大丈夫です。
こんなに簡単なのに4時間ぐらい使ったの悔しい。

# ビルドして実機で確認
はい。このようにログを出力できました。
実は、ログの状態は前回の記事と全く変わってません。Jsonで変換してるかしてないかです。
このJson化が必要になるときは来るんですかね。どうなんでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083521/4993548c-898c-d131-d576-b7d2f54194d7.png)

> 古のスマホをデバック用として使っているのかだって？普段使いだよ！！

# おわりに
なんも書くことないっすわ。お付き合いありがとうございました。
また、Tips的なこと書けそうになったら書きますねー。
んじゃ、また！