Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
We use cookies to ensure that we provide you with the best possible experience on our site.
Votre source incontournable sur Unity et le développement web
Votre source incontournable sur Unity et le développement web
JsonUtility est une classe fournie avec Unity, facilitant la sérialisation et la désérialisation du contenu basé sur le format JSON.
Table des matières
JSON, ou JavaScript Object Notation, est un format texte standard pour représenter des données structurées basé sur la syntaxe d’objet JavaScript. Dans Unity, il permet de transformer du texte en une instance de classe C#.
{"id":1,"username":"VectorFocus"}
Cela équivaut à l’instance de classe C# suivante :
public class User
{
public int id;
public string username;
}
var user = new User()
{
id = 1,
username = "VectorFocus"
};
Pour sérialiser un objet en une chaîne JSON, vous pouvez utiliser la méthode JsonUtility.ToJson.
public class User
{
public int id;
public string username;
}
var user = new User()
{
id = 1,
username = "VectorFocus"
};
// {"id":1,"username":"VectorFocus"}
string json = JsonUtility.ToJson(user);
Pour désérialiser une chaîne au format JSON en un objet, vous pouvez utiliser JsonUtility.FromJson.
string json = "{\"id\":1,\"username\":\"VectorFocus\"}";
User user = JsonUtility.FromJson<User>(json);
JsonUtility.FromJsonOverwrite permet la désérialisation du JSON dans des classes héritant de UnityEngine.Object (Monobehaviour et ScriptableObject). Il peut également être utilisé pour des classes plus simples en passant un objet en tant que deuxième paramètre à mettre à jour, au lieu de créer un nouvel objet.
using UnityEngine;
public class JsonMonobehaviour : MonoBehaviour
{
public int number;
public string informations;
private void Start()
{
string json = "{\"number\":6,\"informations\":\"my data\"}";
JsonUtility.FromJsonOverwrite(json, this);
}
}
Les champs peuvent être masqués de la sérialisation en utilisant l’attribut [NonSerialized]. Les champs privés et les getters/setters sont également ignorés.
using UnityEngine;
using System;
public class JsonMonobehaviour : MonoBehaviour
{
public int number;
public string informations;
// masquer de JsonUtility
[NonSerialized]
public int field;
// masquer de JsonUtility
private int _field2;
// masquer de JsonUtility
public int Field3 { get; set; }
}
Les getters et setters peuvent être directement sérialisés en utilisant l’attribut [field: SerializeField]
. Cependant, le champ se verra attribuer une clé non conviviale (par exemple, k__BackingField
).
[field: SerializeField]
public int Field3 { get; set; }
Les tableaux ou listes peuvent être directement définis dans la structure pour les types simples (int, string, etc.).
public class User
{
public int id;
public string username;
public List<int> points = new List<int>();
public int[] pointsArray;
}
Les types personnalisés peuvent être utilisés dans votre structure ; attribuez simplement l’attribut [System.Serializable] à votre classe ou struct personnalisée.
public class User
{
public int id;
public string username;
// un seul groupe
public Group group;
// fonctionne avec les listes et les tableaux aussi
public List<Group> groups = new List<Group>();
}
[System.Serializable]
public class Group
{
public string name;
}
Si vos données JSON deviennent énormes et que JsonUtility devient lent : Il peut être intéressant d’exécuter la sérialisation dans un autre thread pour éviter que le thread principal ne soit bloqué et que le jeu ne se fige. Depuis Unity 2019.1.6, nous pouvons utiliser JsonUtility dans un thread d’arrière-plan. Vous ne devez pas altérer un objet qui est utilisé dans la fonction pendant son exécution.
using System.Collections;
using System.Threading;
using UnityEngine;
using UnityEngine.Events;
public class JsonBackground : MonoBehaviour
{
public class User
{
public int id;
public string username;
}
private void Start()
{
string json = "{\"id\":1,\"username\":\"VectorFocus\"}";
FromJsonBackground<User>(json, (user) =>
{
// actions avec l'utilisateur
});
}
public void FromJsonBackground<T>(string data, UnityAction<T> unityAction)
{
StartCoroutine(FromJsonBackgroundCoroutine<T>(data, unityAction));
}
private IEnumerator FromJsonBackgroundCoroutine<T>(string data, UnityAction<T> unityAction)
{
T convertData = default(T);
var thread = new Thread(() =>
{
convertData = JsonUtility.FromJson<T>(data);
});
thread.Start();
while (thread.IsAlive)
{
yield return null;
}
unityAction.Invoke(convertData);
}
}
Je ne suis pas un grand fan de ce code, je ne suis pas satisfait du mélange de thread et de coroutine. Un autre problème est ajouté : si la coroutine est arrêtée, le thread continuera à s’exécuter. Je n’ai pas encore trouvé de solution à ce problème, car Thread.Abort est obsolète et CancellationToken ne semble pas pouvoir répondre à ce besoin.
Vous pouvez utiliser les fonctionnalités Task
et async/await
de C# dans Unity pour effectuer ces opérations en arrière-plan. N’oubliez pas d’appeler les opérations liées à Unity sur le thread principal lorsque c’est nécessaire.
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
public class JsonBackgroundTask : MonoBehaviour
{
public class User
{
public int id;
public string username;
}
private void Start()
{
string json = "{\"id\":1,\"username\":\"VectorFocus\"}";
FromJsonTask<User>(json, (user) =>
{
// actions avec l'utilisateur
});
AwaitSyntax();
}
public async void AwaitSyntax()
{
// si vous préférez sans rappel avec await
string json = "{\"id\":1,\"username\":\"VectorFocus\"}";
var user = await FromJsonGetTask<User>(json);
}
public async void FromJsonTask<T>(string json, UnityAction unityAction)
{
var data = await Task.Run(() => JsonUtility.FromJson<T>(json));
unityAction?.Invoke(data);
}
public Task FromJsonGetTask<T>(string json)
{
return Task.Run(() => JsonUtility.FromJson<T>(json));
}
}
J’ai le même problème ici qu’avec le code utilisant le thread, la tâche continuera même si l’objet est détruit. Vous pouvez modifier le code pour ajouter un CancellationToken, mais il ne semble pas possible d’arrêter l’exécution de JsonUtility une fois qu’elle a commencé.
EditorJsonUtility est un utilitaire similaire à JsonUtility mais conçu spécifiquement pour l’éditeur Unity. Il offre plus de contrôle sur la sérialisation et la désérialisation dans les scripts de l’éditeur.
using UnityEditor;
using UnityEngine;
public class EditorJsonExample
{
[MenuItem("Tools/Deserialize JSON")]
private static void DeserializeJson()
{
User user = new User() { id = 1 };
string json = EditorJsonUtility.ToJson(user);
}
}
Illustration originale par J S de Pixabay