JsonUtility is Unity’s built-in JSON serializer. It’s a lightweight API perfect for simple data types, but it has limitations—most notably, it does not support collections like Dictionary. However, it does support List<T> and arrays!
In this comprehensive guide, we’ll cover everything you need to know about JSON serialization in Unity, from basic usage to advanced patterns.
Basic Serialization
Serializing an Object
using UnityEngine;
using System.Serializable;
[Serializable]
public class PlayerData
{
public string playerName;
public int score;
public float health;
}
// Usage:
PlayerData data = new PlayerData { playerName = "Hero", score = 100, health = 75f };
string json = JsonUtility.ToJson(data, true); // true = pretty print
Debug.Log(json);
// Output: {"playerName":"Hero","score":100,"health":75.0}
⚠️ Important: All classes you want to serialize must have the
[Serializable]attribute.
Deserializing JSON
string json = "{\"playerName\":\"Hero\",\"score\":100,\"health\":75.0}";
PlayerData data = JsonUtility.FromJson<PlayerData>(json);
Debug.Log(data.playerName); // Output: Hero
Working with Arrays and Lists
Serializing an Array
[Serializable]
public class StringArrayWrapper
{
public string[] items;
}
string[] myItems = new string[] { "Apple", "Banana", "Cherry" };
var wrapper = new StringArrayWrapper { items = myItems };
string json = JsonUtility.ToJson(wrapper);
// Output: {"items":["Apple","Banana","Cherry"]}
Serializing a List
[Serializable]
public class IntListWrapper
{
public List<int> numbers;
}
var listWrapper = new IntListWrapper
{
numbers = new List<int> { 1, 2, 3, 4, 5 }
};
string json = JsonUtility.ToJson(listWrapper);
// Output: {"numbers":[1,2,3,4,5]}
Handling Complex Data Structures
Nested Objects
[Serializable]
public class Address
{
public string street;
public string city;
public string zipCode;
}
[Serializable]
public class PlayerData
{
public string playerName;
public int score;
public Address homeAddress; // Nested object
}
// Usage:
var data = new PlayerData
{
playerName = "Hero",
score = 100,
homeAddress = new Address { street = "123 Main St", city = "Springfield", zipCode = "12345" }
};
string json = JsonUtility.ToJson(data, true);
Arrays of Objects
[Serializable]
public class InventoryItem
{
public string itemName;
public int quantity;
public float price;
}
[Serializable]
public class InventoryWrapper
{
public InventoryItem[] items;
}
// Usage:
var inventory = new InventoryWrapper
{
items = new InventoryItem[]
{
new InventoryItem { itemName = "Sword", quantity = 1, price = 100f },
new InventoryItem { itemName = "Potion", quantity = 5, price = 20f }
}
};
string json = JsonUtility.ToJson(inventory, true);
Saving and Loading JSON Data
Save to File
using System.IO;
public void SavePlayerData(PlayerData data)
{
string json = JsonUtility.ToJson(data, true);
string filePath = Path.Combine(Application.persistentDataPath, "playerSave.json");
File.WriteAllText(filePath, json);
Debug.Log($"Saved to: {filePath}");
}
Load from File
public PlayerData LoadPlayerData()
{
string filePath = Path.Combine(Application.persistentDataPath, "playerSave.json");
if (File.Exists(filePath))
{
string json = File.ReadAllText(filePath);
return JsonUtility.FromJson<PlayerData>(json);
}
// Return default data if file doesn't exist
return new PlayerData { playerName = "Player", score = 0, health = 100f };
}
Common Pitfalls and Solutions
Issue 1: Dictionary Not Supported
JsonUtility does not support Dictionary<TKey, TValue>. Use these alternatives:
Option A: Parallel Lists
[Serializable]
public class StringIntDictWrapper
{
public string[] keys;
public int[] values;
}
// Usage:
var wrapper = new StringIntDictWrapper
{
keys = new string[] { "Gold", "Silver", "Bronze" },
values = new int[] { 100, 50, 25 }
};
Option B: Use a Third-Party Library
For Dictionary support, consider these popular alternatives:
| Library | Pros | Cons |
|---|---|---|
| Newtonsoft.Json (Json.NET) | Full feature set, widely used | Larger build size |
| System.Text.Json (.NET 5+) | Built into modern .NET, fast | Requires Unity 2021+ |
| LitJSON | Lightweight, simple API | Less maintained |
Issue 2: Missing Fields in JSON
If the JSON is missing a field, JsonUtility will use the default value for that type:
[Serializable]
public class PlayerData
{
public string playerName; // Default: null
public int score; // Default: 0
public float health; // Default: 0.0f
}
// JSON with missing field: {"score": 100}
// Result: playerName = null, score = 100, health = 0.0f
Issue 3: Private Fields Ignored
JsonUtility only serializes public fields and properties with getters/setters:
[Serializable]
public class PlayerData
{
public string name; // ✅ Serialized
private int score; // ❌ Not serialized
public int Score // ✅ Serialized (property)
{
get => score;
set => score = value;
}
}
Issue 4: Enum Serialization
Enums serialize as integers by default. For string representation, use a wrapper:
public enum Rarity { Common, Uncommon, Rare, Epic, Legendary }
[Serializable]
public class ItemWrapper
{
public string itemName;
public int rarityValue; // Store as int
// Helper property for convenience
public Rarity Rarity
{
get => (Rarity)rarityValue;
set => rarityValue = (int)value;
}
}
Best Practices Summary
- Always use
[Serializable]on classes you want to serialize - Use public fields or properties—private members are ignored
- Wrap arrays and lists in a serializable class for consistent JSON structure
- Handle missing files gracefully—provide default data when saves don’t exist
- Pretty-print during development (
ToJson(data, true)) for easier debugging - Consider third-party libraries for complex data structures (Dictionaries, nested generics)
Related Resources
- Unity Coroutines Tutorial – Manage async data loading
- A Useful Countdown Timer Class in C# – Time-based game mechanics
- Best Unity Assets 2025 – Easy Save for persistent data
Need help with JSON serialization in your project? Check our other Unity tutorials or leave a comment below! 💻✨