1. ホーム
  2. c#

[解決済み] UnityでJsonとJson Arrayをシリアライズ/デシリアライズする

2022-07-21 04:23:53

質問

PHPファイルからunityに送信されるアイテムのリストを WWW .

WWW.text のように見える。

[
    {
        "playerId": "1",
        "playerLoc": "Powai"
    },
    {
        "playerId": "2",
        "playerLoc": "Andheri"
    },
    {
        "playerId": "3",
        "playerLoc": "Churchgate"
    }
]

余分な [] から string . を使ってパースしようとすると Boomlagoon.JSON を使ってパースしようとすると、最初のオブジェクトだけが取得されます。私は、私が deserialize() を作成し、MiniJSONをインポートしています。

しかし、私は混乱していますどのように deserialize() を作成する方法がわかりません。私はすべてのJSONオブジェクトをループしてデータを取得したいです。どのように私はC#を使用してUnityでこれを行うことができますか?

私が使用しているクラスは

public class player
{
    public string playerId { get; set; }
    public string playerLoc { get; set; }
    public string playerNick { get; set; }
}

を切り詰めた後 [] MiniJSONを使用してjsonをパースすることができます。しかし、それは最初の KeyValuePair .

IDictionary<string, object> players = Json.Deserialize(serviceData) as IDictionary<string, object>;

foreach (KeyValuePair<string, object> kvp in players)
{
    Debug.Log(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
}

ありがとうございます。

どのように解決するのですか?

Unityを追加しました。 JsonUtility を API に追加しました。 5.3.3 更新しました。もっと複雑なことをしない限り、すべてのサードパーティライブラリのことは忘れてください。JsonUtilityは他のJsonライブラリより高速です。Unityへのアップデート 5.3.3 バージョン以上にしてから、以下の解決策を試してみてください。

JsonUtility は軽量なAPIです。単純な型のみをサポートしています。これは ではなく はDictionaryのようなコレクションをサポートしません。一つの例外は List . これは ListList の配列になります!

をシリアライズする必要がある場合 Dictionary をシリアライズする必要がある場合、または単純なデータ型のシリアライズとデシリアライズ以外のことを行う場合は、サードパーティのAPIを使用してください。それ以外の場合は、読み進めてください。

シリアライズするクラスの例です。

[Serializable]
public class Player
{
    public string playerId;
    public string playerLoc;
    public string playerNick;
}

1. 1つのデータオブジェクト(非配列のjson)

シリアライズ そのA :

シリアライズ をJsonに変換するために public static string ToJson(object obj); メソッドでJsonに変換します。

Player playerInstance = new Player();
playerInstance.playerId = "8484239823";
playerInstance.playerLoc = "Powai";
playerInstance.playerNick = "Random Nick";

//Convert to JSON
string playerToJson = JsonUtility.ToJson(playerInstance);
Debug.Log(playerToJson);

出力 :

{"playerId":"8484239823","playerLoc":"Powai","playerNick":"Random Nick"}


連載パートB :

シリアライズ をJsonに変換するために public static string ToJson(object obj, bool prettyPrint); メソッドのオーバーロードです。単に渡すだけで trueJsonUtility.ToJson 関数がデータをフォーマットします。下の出力と上の出力を比べてみてください。

Player playerInstance = new Player();
playerInstance.playerId = "8484239823";
playerInstance.playerLoc = "Powai";
playerInstance.playerNick = "Random Nick";

//Convert to JSON
string playerToJson = JsonUtility.ToJson(playerInstance, true);
Debug.Log(playerToJson);

出力 :

{
    "playerId": "8484239823",
    "playerLoc": "Powai",
    "playerNick": "Random Nick"
}


デシリアライズ そのA :

デシリアライズ というjsonを public static T FromJson(string json); メソッドをオーバーロードします。

string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
Player player = JsonUtility.FromJson<Player>(jsonString);
Debug.Log(player.playerLoc);

デシリアライズ そのB :

デシリアライズ というjsonを public static object FromJson(string json, Type type); メソッドをオーバーロードします。

string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
Player player = (Player)JsonUtility.FromJson(jsonString, typeof(Player));
Debug.Log(player.playerLoc);


デシリアライズ そのC :

デシリアライズ というjsonを public static void FromJsonOverwrite(string json, object objectToOverwrite); メソッドを使用します。いつ JsonUtility.FromJsonOverwrite を使用した場合、デシリアライズ先のオブジェクトの新しいインスタンスは作成されません。単に渡されたインスタンスを再利用し、その値を上書きするだけです。

これは効率的であり、可能であれば使用されるべきです。

Player playerInstance;
void Start()
{
    //Must create instance once
    playerInstance = new Player();
    deserialize();
}

void deserialize()
{
    string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";

    //Overwrite the values in the existing class instance "playerInstance". Less memory Allocation
    JsonUtility.FromJsonOverwrite(jsonString, playerInstance);
    Debug.Log(playerInstance.playerLoc);
}


2. 複数データ(配列json)

あなたのJsonは複数のデータオブジェクトを含んでいます。例えば playerId よりも多く出現し が一度だけ . ユニティの JsonUtility はまだ新しいので配列はサポートしていませんが、このような場合は ヘルパー クラスを使って 配列 と連携して JsonUtility .

というクラスを作成します。 JsonHelper . JsonHelperを下から直接コピーします。

public static class JsonHelper
{
    public static T[] FromJson<T>(string json)
    {
        Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
        return wrapper.Items;
    }

    public static string ToJson<T>(T[] array)
    {
        Wrapper<T> wrapper = new Wrapper<T>();
        wrapper.Items = array;
        return JsonUtility.ToJson(wrapper);
    }

    public static string ToJson<T>(T[] array, bool prettyPrint)
    {
        Wrapper<T> wrapper = new Wrapper<T>();
        wrapper.Items = array;
        return JsonUtility.ToJson(wrapper, prettyPrint);
    }

    [Serializable]
    private class Wrapper<T>
    {
        public T[] Items;
    }
}

Json配列のシリアライズ :

Player[] playerInstance = new Player[2];

playerInstance[0] = new Player();
playerInstance[0].playerId = "8484239823";
playerInstance[0].playerLoc = "Powai";
playerInstance[0].playerNick = "Random Nick";

playerInstance[1] = new Player();
playerInstance[1].playerId = "512343283";
playerInstance[1].playerLoc = "User2";
playerInstance[1].playerNick = "Rand Nick 2";

//Convert to JSON
string playerToJson = JsonHelper.ToJson(playerInstance, true);
Debug.Log(playerToJson);

出力 :

{
    "Items": [
        {
            "playerId": "8484239823",
            "playerLoc": "Powai",
            "playerNick": "Random Nick"
        },
        {
            "playerId": "512343283",
            "playerLoc": "User2",
            "playerNick": "Rand Nick 2"
        }
    ]
}


Json配列のデシリアライズ :

string jsonString = "{\r\n    \"Items\": [\r\n        {\r\n            \"playerId\": \"8484239823\",\r\n            \"playerLoc\": \"Powai\",\r\n            \"playerNick\": \"Random Nick\"\r\n        },\r\n        {\r\n            \"playerId\": \"512343283\",\r\n            \"playerLoc\": \"User2\",\r\n            \"playerNick\": \"Rand Nick 2\"\r\n        }\r\n    ]\r\n}";

Player[] player = JsonHelper.FromJson<Player>(jsonString);
Debug.Log(player[0].playerLoc);
Debug.Log(player[1].playerLoc);

出力 :

ポワイ

ユーザー2


もしこれがサーバからのJson配列で、手動で作成したのでないなら :

を追加する必要があるかもしれません。 {"Items": を受信した文字列の前に追加し } を末尾につける。

そのための簡単な関数を作ってみました。

string fixJson(string value)
{
    value = "{\"Items\":" + value + "}";
    return value;
}

とすれば、使えるようになります。

string jsonString = fixJson(yourJsonFromServer);
Player[] player = JsonHelper.FromJson<Player>(jsonString);


3.クラスなしのjson文字列をデシリアライズする && 数値プロパティを持つJsonをデシリアライズする

これは、数字や数値プロパティで始まるJsonです。

例えば

{ 
"USD" : {"15m" : 1740.01, "last" : 1740.01, "buy" : 1740.01, "sell" : 1744.74, "symbol" : "$"}, 

"ISK" : {"15m" : 179479.11, "last" : 179479.11, "buy" : 179479.11, "sell" : 179967, "symbol" : "kr"},

"NZD" : {"15m" : 2522.84, "last" : 2522.84, "buy" : 2522.84, "sell" : 2529.69, "symbol" : "$"}
}

Unityの JsonUtility は、"15m" プロパティが数字で始まるため、これをサポートしません。クラス変数が整数で始まることはありません。

ダウンロード SimpleJSON.cs をUnityの ウィキ .

USDの"15m"プロパティを取得する。

var N = JSON.Parse(yourJsonString);
string price = N["USD"]["15m"].Value;
Debug.Log(price);

ISKの"15m"プロパティを取得する。

var N = JSON.Parse(yourJsonString);
string price = N["ISK"]["15m"].Value;
Debug.Log(price);

NZDの"15m"プロパティを取得する。

var N = JSON.Parse(yourJsonString);
string price = N["NZD"]["15m"].Value;
Debug.Log(price);

数字で始まらない残りのJsonプロパティは、UnityのJsonUtilityで処理することができます。


4.TROUBLESHOOTING JsonUtility:

でシリアライズする際の問題 JsonUtility.ToJson ?

空文字列または " を取得します。 {} というように JsonUtility.ToJson ?

A . クラスが配列でないことを確認してください。もしそうなら、上記のヘルパークラスで JsonHelper.ToJson の代わりに JsonUtility.ToJson .

B . 追加 [Serializable] をシリアライズするクラスの先頭に追加してください。

C . クラスからプロパティを削除します。例えば、変数に public string playerId { get; set; } を削除します。 { get; set; } . Unityはこれをシリアライズすることができません。

でデシリアライズした場合の問題 JsonUtility.FromJson ?

A . もし、あなたが Null が表示された場合、JsonがJson配列でないことを確認してください。もしそうなら、上記のヘルパークラスで JsonHelper.FromJson の代わりに JsonUtility.FromJson .

B . もし、あなたが NullReferenceException が表示された場合、デシリアライズ中に [Serializable] をクラスの先頭に追加します。

C .その他の問題がある場合は、jsonが有効であることを確認してください。このサイトへ こちら にアクセスし、jsonを貼り付けてください。jsonが有効かどうかが表示されるはずです。また、Jsonと一緒に適切なクラスが生成されるはずです。ただ、必ず を削除してください。 { get; set; } を各変数から削除し、さらに [Serializable] を生成された各クラスの先頭に追加してください。


Newtonsoft.Json。

もし何らかの理由で Newtonsoft.Json を使用しなければならない場合は、Unity用にフォークされたバージョンをチェックアウトしてください。 ここで . なお、特定の機能を使用するとクラッシュすることがあります。ご注意ください。


ご質問にお答えします。 :

あなたの元データは

 [{"playerId":"1","playerLoc":"Powai"},{"playerId":"2","playerLoc":"Andheri"},{"playerId":"3","playerLoc":"Churchgate"}]

追加 {"Items": フロント であれば、それの 加える } 末尾 を追加してください。

これを行うためのコードです。

serviceData = "{\"Items\":" + serviceData + "}";

これで

 {"Items":[{"playerId":"1","playerLoc":"Powai"},{"playerId":"2","playerLoc":"Andheri"},{"playerId":"3","playerLoc":"Churchgate"}]}

への シリアライズ 複数の のデータを php から 配列 であれば、これで

public player[] playerInstance;
playerInstance = JsonHelper.FromJson<player>(serviceData);

playerInstance[0] が最初のデータです。

playerInstance[1] は2番目のデータです。

playerInstance[2] は3番目のデータです。

またはクラス内のデータで playerInstance[0].playerLoc , playerInstance[1].playerLoc , playerInstance[2].playerLoc ......

を使うことができます。 playerInstance.Length を使って、アクセスする前に長さをチェックすることができます。

注意 を削除する { get; set; } を削除します。 player クラスと同じです。もし { get; set; } を指定した場合、動作しません。Unityの JsonUtility ではない として定義されているクラスのメンバで動作します。 プロパティ .