web-dev-qa-db-fra.com

Sérialiser et désérialiser Json et Json Array dans Unity

J'ai une liste d'éléments envoyés d'un fichier PHP à l'unité à l'aide de WWW.

Le WWW.text ressemble à:

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

Où je coupe le [] supplémentaire de la string. Lorsque j'essaie de l'analyser avec Boomlagoon.JSON, seul le premier objet est récupéré. J'ai découvert qu'il me fallait deserialize() la liste et que j'ai importé MiniJSON.

Mais je ne comprends pas comment deserialize() cette liste. Je souhaite parcourir tous les objets JSON et récupérer des données. Comment puis-je faire cela dans Unity en utilisant C #?

La classe que j'utilise est

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

Après avoir coupé le [], je peux analyser le json avec MiniJSON. Mais il ne retourne que le premier 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));
}

Merci!

75
dil33pm

Unity a ajouté JsonUtility à leur API après 5.3.3 Update. Oubliez toutes les bibliothèques tierces, à moins que vous ne fassiez quelque chose de plus compliqué. JsonUtility est plus rapide que les autres bibliothèques Json. Mettez à jour vers Unity 5.3.3 ou une version ultérieure, puis essayez la solution ci-dessous.

JsonUtility est une API légère. Seuls les types simples sont pris en charge. Il ( ne supporte pas des collections telles que Dictionary. Une exception est List. Il supporte List et List tableau!

Si vous devez sérialiser un Dictionary ou faire autre chose que de simplement sérialiser et désérialiser des types de données simples, utilisez une API tierce. Sinon, continuez à lire.

Exemple de classe à sérialiser:

_[Serializable]
public class Player
{

    public string playerId;
    public string playerLoc;
    public string playerNick;
}
_

1. UN OBJET DE DONNEES (JSON NON-ARRAY)

Sérialisation de la partie A :

Sérialiser sur Json avec la méthode public static string ToJson(object obj); .

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

//Convert to Jason
string playerToJason = JsonUtility.ToJson(playerInstance);
Debug.Log(playerToJason);
_

Sortie :

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

Sérialisation de la partie B :

Sérialiser sur Json avec la surcharge de la méthode public static string ToJson(object obj, bool prettyPrint); . Passer simplement true à la fonction _JsonUtility.ToJson_ formatera les données. Comparez la sortie ci-dessous à la sortie ci-dessus.

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

//Convert to Jason
string playerToJason = JsonUtility.ToJson(playerInstance, true);
Debug.Log(playerToJason);
_

Sortie :

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

Désérialisation de la partie A :

Désérialisez json avec la surcharge de la méthode 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);
_

Désérialisation de la partie B :

Désérialisez json avec la surcharge de la méthode 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);
_

Désérialisation de la partie C :

Deserialize json avec la méthode public static void FromJsonOverwrite(string json, object objectToOverwrite); . Lorsque _JsonUtility.FromJsonOverwrite_ est utilisé, aucune nouvelle instance de cet objet que vous désérialisez ne sera créée. Il va simplement réutiliser l'instance que vous avez transmise et écraser ses valeurs.

Ceci est efficace et devrait être utilisé si possible.

_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. MULTIPLE DATA (ARRAY JSON)

Votre Json contient plusieurs objets de données. Par exemple, playerId est apparu plus de une fois . JsonUtility de Unity ne prend pas en charge le tableau car il est encore nouveau, mais vous pouvez utiliser une classe aide de cette personne pour obtenir un tableau travailler avec JsonUtility.

Créez une classe appelée JsonHelper. Copiez le JsonHelper directement d'en bas.

_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;
    }
}
_

Sérialisation du tableau 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 Jason
string playerToJason = JsonHelper.ToJson(playerInstance, true);
Debug.Log(playerToJason);
_

Sortie :

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

Deserializing Json Array :

_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);
_

Sortie :

Powai

Utilisateur2


S'il s'agit d'un tableau Json du serveur et que vous ne l'avez pas créé manuellement :

Vous devrez peut-être ajouter _{"Items":_ devant la chaîne reçue, puis ajouter _}_ à la fin de celle-ci.

J'ai créé une fonction simple pour cela:

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

alors vous pouvez l'utiliser:

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

3.Deserialize json string sans la classe && Déssérialisation de Json avec des propriétés numériques

C'est un Json qui commence par un nombre ou des propriétés numériques.

Par exemple:

_{ 
"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" : "$"}
}
_

JsonUtility de Unity ne prend pas cela en charge car la propriété "15m" commence par un nombre. Une variable de classe ne peut pas commencer par un entier.

Télécharger SimpleJSON.cs à partir de wiki .

Pour obtenir la propriété "15m" de USD:

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

Pour obtenir la propriété "15m" d'ISK:

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

Pour obtenir la propriété "15m" de NZD:

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

Le reste des propriétés Json qui ne commencent pas par un chiffre peut être géré par JsonUtility de Unity.


4. RÉSOLUTION DES PROBLÈMES Jsonutilité:

Problèmes de sérialisation avec _JsonUtility.ToJson_?

Obtenir une chaîne vide ou "_{}_" avec _JsonUtility.ToJson_?

A. Assurez-vous que la classe n'est pas un tableau. Si c'est le cas, utilisez la classe d'assistance ci-dessus avec _JsonHelper.ToJson_ au lieu de _JsonUtility.ToJson_.

B. Ajoutez _[Serializable]_ en haut de la classe que vous sérialisez.

C. Supprimer la propriété de la classe. Par exemple, dans la variable, _public string playerId { get; set; }_ , supprimez _{ get; set; }_. Unity ne peut pas sérialiser cela.

Problèmes lors de la désérialisation avec _JsonUtility.FromJson_?

A. Si vous obtenez Null, assurez-vous que le Json n'est pas un tableau Json. Si c'est le cas, utilisez la classe d'assistance ci-dessus avec _JsonHelper.FromJson_ au lieu de _JsonUtility.FromJson_.

B. Si vous obtenez NullReferenceException lors de la désérialisation, ajoutez _[Serializable]_ en haut de la classe.

C. Si vous rencontrez un autre problème, vérifiez que votre JSON est valide. Allez sur ce site ici et collez le json. Il devrait vous montrer si le json est valide. Il devrait également générer la classe appropriée avec le Json. Assurez-vous simplement de supprimer remove _{ get; set; }_ de chaque variable et d'ajouter également _[Serializable]_ en haut de chaque classe générée.


Newtonsoft.Json:

Si pour une raison quelconque Newtonsoft.Json doit être utilisé, consultez la version forkée de Unity ici . Notez que vous pouvez rencontrer un crash si certaines fonctionnalités sont utilisées. Faites attention.


Pour répondre à votre question :

Vos données d'origine sont

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

Ajoutez _{"Items":_ à avant de celui-ci puis ajoutez _}_ à la fin de celle-ci.

Code pour faire ceci:

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

Maintenant vous avez:

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

Pour sérialiser les multiples données de php en tant que tableaux , vous pouvez maintenant faire

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

_playerInstance[0]_ est votre première donnée

_playerInstance[1]_ est votre deuxième donnée

_playerInstance[2]_ est votre troisième donnée

ou des données à l'intérieur de la classe avec _playerInstance[0].playerLoc_, _playerInstance[1].playerLoc_, _playerInstance[2].playerLoc_ ......

Vous pouvez utiliser _playerInstance.Length_ pour vérifier la longueur avant d'y accéder.

REMARQUE: Supprimez _{ get; set; }_ de la classe player. Si vous avez _{ get; set; }_, cela ne fonctionnera pas. La JsonUtility de Unity ne fonctionne PAS avec les membres de la classe définis comme propriétés .

184
Programmer

Supposons que vous ayez un JSON comme celui-ci

[
    {
        "type": "qrcode",
        "symbol": [
            {
                "seq": 0,
                "data": "HelloWorld9887725216",
                "error": null
            }
        ]
    }
]

Pour analyser le JSON ci-dessus dans l'unité, vous pouvez créer un modèle JSON comme ceci.

[System.Serializable]
public class QrCodeResult
{
    public QRCodeData[] result;
}

[System.Serializable]
public class Symbol
{
    public int seq;
    public string data;
    public string error;
}

[System.Serializable]
public class QRCodeData
{
    public string type;
    public Symbol[] symbol;
}

Et puis simplement analyser de la manière suivante ...

var myObject = JsonUtility.FromJson<QrCodeResult>("{\"result\":" + jsonString.ToString() + "}");

Vous pouvez maintenant modifier le code JSON/CODE en fonction de vos besoins. https://docs.unity3d.com/Manual/JSONSerialization.html

13
Narottam Goyal

vous devez ajouter [System.Serializable] à PlayerItem class, comme ceci:

using System;
[System.Serializable]
public class PlayerItem   {
    public string playerId;
    public string playerLoc;
    public string playerNick;
}
2
Myan

Pour lire un fichier JSON, reportez-vous à cet exemple simple

Votre fichier JSON (StreamingAssets/Player.json)

{
    "Name": "MyName",
    "Level": 4
}

Script C #

public class Demo
{
    public void ReadJSON()
    {
        string path = Application.streamingAssetsPath + "/Player.json";
        string JSONString = File.ReadAllText(path);
        Player player = JsonUtility.FromJson<Player>(JSONString);
        Debug.Log(player.Name);
    }
}

[System.Serializable]
public class Player
{
    public string Name;
    public int Level;
}
1
Juned Khan Momin

Comme @Maximiliangerhardt l'a dit, MiniJson n'a pas la capacité de se désérialiser correctement. J'ai utilisé JsonFx et fonctionne comme un charme. Fonctionne avec le []

player[] p = JsonReader.Deserialize<player[]>(serviceData);
Debug.Log(p[0].playerId +" "+ p[0].playerLoc+"--"+ p[1].playerId + " " + p[1].playerLoc+"--"+ p[2].playerId + " " + p[2].playerLoc);
0
dil33pm

Ne coupez pas le [] et ça devrait aller. [] identifie un tableau JSON qui correspond exactement à ce dont vous avez besoin pour pouvoir itérer ses éléments.

0
Thomas Hilbert