Skip to content

RS-Unity3D/RS.SimpleJson-Unity

Repository files navigation

SimpleJson-Unity.cs 使用文档

目录


简介

SimpleJson-Unity.cs 是一个专为Unity优化的轻量级JSON序列化/反序列化库,基于SimpleJson项目改进而来,特别针对Unity的AOT(Ahead-Of-Time)编译环境进行了优化。

主要优势

  • 轻量级:无外部依赖,代码量小
  • AOT友好:完全支持Unity IL2CPP编译
  • 高性能:优化的反射缓存和字符串处理
  • 跨平台:支持所有Unity平台(包括WebGL)
  • 灵活:支持自定义序列化策略

特性

核心特性

  • ✅ 完整的JSON序列化/反序列化支持
  • ✅ 支持复杂对象、集合、字典
  • ✅ 支持泛型类型
  • ✅ 支持日期时间格式(ISO8601)
  • ✅ 支持GUID、Uri等特殊类型
  • ✅ 支持枚举序列化
  • ✅ 支持只读集合(IReadOnlyCollection, IReadOnlyList, IReadOnlyDictionary)
  • ✅ 支持属性/字段过滤(JsonIgnore, JsonInclude特性)
  • 支持 JsonAlias 多别名(兼容 Newtonsoft.Json)
  • 支持循环引用检测(防止栈溢出)
  • 支持序列化别名控制(useJsonAliasForSerialization 参数)

Unity优化特性

  • ✅ WebGL单线程优化(无锁机制)
  • ✅ AOT类型注册机制
  • ✅ 值类型构造函数优化
  • ✅ 反射缓存管理(复合键缓存)
  • ✅ 延迟StringBuilder创建(减少内存分配)
  • 完善的 AOT 异常捕获(支持更多 AOT 场景)
  • 线程安全的序列化栈(循环引用检测)
  • AOT 安全的枚举转换(SafeEnumConversion)
  • WebGL 无锁模式(SIMPLE_JSON_WEBGL)

安装

1. 复制文件

SimpleJson-Unity.cs 复制到你的Unity项目中,建议放在 Scripts/Utils/ 目录下。

2. 命名空间

using RS.SimpleJsonUnity;

3. 可选:初始化AOT支持

对于IL2CPP构建,建议在游戏启动时初始化常用AOT类型:

void Awake() {
    SimpleJson.InitializeCommonAotTypes();
}

基本使用

序列化对象

public class PlayerData {
    public string Name { get; set; }
    public int Level { get; set; }
    public float Health { get; set; }
    public List<string> Items { get; set; }
}

// 序列化
PlayerData player = new PlayerData {
    Name = "Hero",
    Level = 10,
    Health = 100.5f,
    Items = new List<string> { "Sword", "Shield", "Potion" }
};

string json = SimpleJson.SerializeObject(player);
// 输出: {"Name":"Hero","Level":10,"Health":100.5,"Items":["Sword","Shield","Potion"]}

反序列化对象

string json = @"{
    ""Name"": ""Hero"",
    ""Level"": 10,
    ""Health"": 100.5,
    ""Items"": [""Sword"", ""Shield"", ""Potion""]
}";

PlayerData player = SimpleJson.DeserializeObject<PlayerData>(json);

Debug.Log($"Player: {player.Name}, Level: {player.Level}");

处理动态JSON

// 解析为动态对象
JsonObject jsonObj = SimpleJson.DeserializeObject<JsonObject>(json);

// 访问属性
string name = (string)jsonObj["Name"];
int level = (int)jsonObj["Level"];
JsonArray items = (JsonArray)jsonObj["Items"];

// 遍历数组
foreach (var item in items) {
    Debug.Log($"Item: {item}");
}

处理列表和字典

// 序列化列表
List<int> scores = new List<int> { 100, 200, 300, 400 };
string json = SimpleJson.SerializeObject(scores);

// 反序列化列表
List<int> deserializedScores = SimpleJson.DeserializeObject<List<int>>(json);

// 序列化字典
Dictionary<string, int> inventory = new Dictionary<string, int> {
    { "Gold", 1000 },
    { "Silver", 500 }
};
string json = SimpleJson.SerializeObject(inventory);

// 反序列化字典
Dictionary<string, int> deserializedInventory = 
    SimpleJson.DeserializeObject<Dictionary<string, int>>(json);

高级使用

自定义序列化策略

public class CustomJsonStrategy : PocoJsonSerializerStrategy {
    protected override string MapClrMemberNameToJsonFieldName(string clrPropertyName) {
        // 将属性名转换为小写
        return char.ToLower(clrPropertyName[0]) + clrPropertyName.Substring(1);
    }
}

// 使用自定义策略
string json = SimpleJson.SerializeObject(obj, new CustomJsonStrategy());

使用特性控制序列化

public class UserData {
    public string Username { get; set; }
    
    [JsonIgnore]
    public string Password { get; set; }  // 不序列化
    
    [JsonInclude]
    private string InternalToken { get; set; }  // 强制序列化私有字段
}

使用 JsonAlias 多别名支持(v2.1.0+)

SimpleJson-Unity v2.1.0 新增了 JsonAliasAttribute,完全兼容 Newtonsoft.Json 的别名规则:

基本用法

public class UserProfile {
    // 支持多个别名,反序列化时按顺序尝试
    [JsonAlias("user_name", "userName", "username")]
    public string UserName { get; set; }
    
    [JsonAlias("user_id", "userId", "uid")]
    public int UserId { get; set; }
    
    // 没有别名的属性使用原始名称
    public string Email { get; set; }
}

// 反序列化时支持所有别名
string json1 = @"{""user_name"": ""张三"", ""user_id"": 123, ""Email"": ""test@example.com""}";
string json2 = @"{""userName"": ""李四"", ""userId"": 456, ""Email"": ""test2@example.com""}";
string json3 = @"{""username"": ""王五"", ""uid"": 789, ""Email"": ""test3@example.com""}";

// 以上三种格式都能正确反序列化
var profile1 = SimpleJson.DeserializeObject<UserProfile>(json1);
var profile2 = SimpleJson.DeserializeObject<UserProfile>(json2);
var profile3 = SimpleJson.DeserializeObject<UserProfile>(json3);

控制序列化别名

默认情况下,序列化时使用原始属性名。可以通过参数控制是否使用别名:

public class UserProfile {
    [JsonAlias("user_name", "userName")]
    public string UserName { get; set; }
}

var profile = new UserProfile { UserName = "张三" };

// 默认:使用原始属性名
string json1 = SimpleJson.SerializeObject(profile);
// 输出: {"UserName":"张三"}

// 启用别名序列化
var strategy = new DefaultJsonSerializationStrategy(
    toLowerCase: false, 
    useJsonAliasForSerialization: true
);
string json2 = SimpleJson.SerializeObject(profile, strategy);
// 输出: {"user_name":"张三"}  // 使用第一个别名

AcceptOriginalName 属性

控制反序列化时是否接受原始属性名:

public class StrictAliasProfile {
    // AcceptOriginalName = false:只接受别名,不接受原始属性名
    [JsonAlias("user_name", AcceptOriginalName = false)]
    public string UserName { get; set; }
}

// 这个 JSON 将无法反序列化 UserName(因为没有使用别名)
string json = @"{""UserName"": ""张三""}";
var profile = SimpleJson.DeserializeObject<StrictAliasProfile>(json);
// profile.UserName 为 null

// 必须使用别名
string json2 = @"{""user_name"": ""李四""}";
var profile2 = SimpleJson.DeserializeObject<StrictAliasProfile>(json2);
// profile2.UserName = "李四"

与 Newtonsoft.Json 的兼容性

SimpleJson-Unity 的 JsonAlias 完全兼容 Newtonsoft.Json 的 [JsonProperty] 别名行为:

// Newtonsoft.Json 写法
public class NewtonsoftStyle {
    [JsonProperty("user_name")]
    public string UserName { get; set; }
}

// SimpleJson-Unity 等价写法
public class SimpleJsonStyle {
    [JsonAlias("user_name")]
    public string UserName { get; set; }
}

// 两者行为一致

处理日期时间

public class EventData {
    public DateTime CreatedAt { get; set; }
    public DateTimeOffset UpdatedAt { get; set; }
}

EventData eventData = new EventData {
    CreatedAt = DateTime.UtcNow,
    UpdatedAt = DateTimeOffset.UtcNow
};

string json = SimpleJson.SerializeObject(eventData);
// 输出: {"CreatedAt":"2025-03-10T12:00:00.000Z","UpdatedAt":"2025-03-10T12:00:00.000Z"}

处理枚举

public enum PlayerClass {
    Warrior = 1,
    Mage = 2,
    Archer = 3
}

public class Character {
    public PlayerClass ClassType { get; set; }
}

Character character = new Character { ClassType = PlayerClass.Mage };
string json = SimpleJson.SerializeObject(character);
// 输出: {"ClassType":2.0}  // 枚举值作为数字

处理GUID和Uri

public class ResourceData {
    public Guid Id { get; set; }
    public Uri ResourceUrl { get; set; }
}

ResourceData resource = new ResourceData {
    Id = Guid.NewGuid(),
    ResourceUrl = new Uri("https://example.com/resource")
};

string json = SimpleJson.SerializeObject(resource);
// 输出: {"Id":"d4a3b2c5-1e4d-4b8a-9c2d-3e5f6a7b8c9d","ResourceUrl":"https://example.com/resource"}

处理嵌套对象

public class Address {
    public string Street { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

public class Person {
    public string Name { get; set; }
    public int Age { get; set; }
    public Address HomeAddress { get; set; }
}

Person person = new Person {
    Name = "John",
    Age = 30,
    HomeAddress = new Address {
        Street = "123 Main St",
        City = "New York",
        Country = "USA"
    }
};

string json = SimpleJson.SerializeObject(person);
// 输出: {"Name":"John","Age":30,"HomeAddress":{"Street":"123 Main St","City":"New York","Country":"USA"}}

AOT支持

什么是AOT编译?

AOT(Ahead-Of-Time)编译是Unity IL2CPP使用的技术,它在构建时将C#代码转换为C++代码,然后编译为原生代码。这导致运行时无法动态创建泛型类型。

SimpleJson-Unity的AOT解决方案

1. 自动AOT支持

SimpleJson-Unity内置了对常用类型的AOT支持,调用 InitializeCommonAotTypes() 后自动注册以下类型:

// Dictionary<string, T> - string键的字典(支持20+种值类型)
Dictionary<string, object>
Dictionary<string, string>

// 有符号整数
Dictionary<string, int>
Dictionary<string, long>
Dictionary<string, short>
Dictionary<string, sbyte>

// 无符号整数
Dictionary<string, uint>
Dictionary<string, ulong>
Dictionary<string, ushort>
Dictionary<string, byte>

// 浮点类型
Dictionary<string, float>
Dictionary<string, double>
Dictionary<string, decimal>

// 其他基础类型
Dictionary<string, bool>
Dictionary<string, char>

// 日期时间类型
Dictionary<string, DateTime>
Dictionary<string, DateTimeOffset>
Dictionary<string, TimeSpan>

// 特殊类型
Dictionary<string, Guid>
Dictionary<string, Uri>
Dictionary<string, Version>

// List<T> - 列表(支持与Dictionary相同的值类型)
List<object>
List<string>
List<int>, List<long>, List<short>, List<sbyte>
List<uint>, List<ulong>, List<ushort>, List<byte>
List<float>, List<double>, List<decimal>
List<bool>, List<char>
List<DateTime>, List<DateTimeOffset>, List<TimeSpan>
List<Guid>, List<Uri>, List<Version>

// 非string键的字典
Dictionary<int, string>
Dictionary<int, int>
Dictionary<int, object>
Dictionary<long, string>
Dictionary<Guid, string>
Dictionary<Guid, object>

// 嵌套泛型集合
List<List<string>>, List<List<int>>, List<List<object>>
Dictionary<string, List<string>>, Dictionary<string, List<int>>, Dictionary<string, List<object>>
Dictionary<string, Dictionary<string, string>>, Dictionary<string, Dictionary<string, int>>
Dictionary<string, Dictionary<string, object>>
List<Dictionary<string, string>>, List<Dictionary<string, int>>, List<Dictionary<string, object>>

2. 初始化常用AOT类型

void Awake() {
    // 初始化内置的常用AOT类型
    SimpleJson.InitializeCommonAotTypes();
}

3. 注册自定义AOT类型

如果你的项目使用了其他泛型类型,需要手动注册:

void Awake() {
    SimpleJson.InitializeCommonAotTypes();
    
    // 方式1:使用工厂委托注册(推荐)
    SimpleJson.RegisterAotType(typeof(MyCustomData), () => new MyCustomData());
    SimpleJson.RegisterAotType(typeof(Dictionary<string, MyCustomData>), 
        () => new Dictionary<string, MyCustomData>());
    SimpleJson.RegisterAotType(typeof(List<MyItem>), () => new List<MyItem>());
    
    // 方式2:使用类型名称注册
    SimpleJson.RegisterAotType("Dictionary<String,MyCustomData>", 
        typeof(Dictionary<string, MyCustomData>));
}

4. AOT安全的类型创建

SimpleJson-Unity提供了AOT安全的类型创建方法:

// 创建POCO实例
object instance = SimpleJson.SafeCreateInstance(typeof(MyCustomData));

// 创建List(AOT安全)
IList list = SimpleJson.SafeCreateList(typeof(string));

// 创建Dictionary(AOT安全)
IDictionary dict = SimpleJson.SafeCreateDictionary(typeof(string), typeof(int));

5. AOT安全的枚举转换

在AOT环境下,枚举转换需要特殊处理:

// 数值到枚举的AOT安全转换
object enumValue = SimpleJson.SafeEnumConversion(1, typeof(PlayerClass));
// 返回 PlayerClass.Warrior(假设 Warrior = 1)

// 字符串到枚举的转换(支持名称和数字字符串)
// 在反序列化时自动处理,无需手动调用

6. Type键查找

使用 Type 对象直接查找已注册的工厂:

// 通过 Type 键查找工厂
Func<object> factory = SimpleJson.GetRegisteredAotFactory(typeof(Dictionary<string, int>));
if (factory != null) {
    var dict = (Dictionary<string, int>)factory();
}

7. 检测AOT环境

if (SimpleJson.IsAotEnvironment) {
    Debug.Log("Running in AOT mode");
    // AOT环境下的特殊处理
} else {
    Debug.Log("Running in JIT mode");
}

8. 清理反射缓存

在场景切换或内存紧张时清理缓存:

void OnDestroy() {
    SimpleJson.ClearReflectionCache();
}

WebGL优化

WebGL平台的特殊挑战

WebGL 平台有几个特殊的限制:

  1. 单线程环境:WebGL 不支持真实的后台线程
  2. AOT编译:必须经过 IL2CPP 编译
  3. 内存限制:浏览器内存有限,需要注意 GC
  4. 锁开销:在单线程环境下,锁是不必要的开销

WebGL无锁模式

SimpleJson-Unity 提供了 WebGL 专用的无锁模式:

// 在 Unity 中,通过 PlayerSettings 添加编译符号
// SIMPLE_JSON_WEBGL

// 无锁模式的效果:
// - 移除所有锁操作
// - 使用简单的字典代替线程安全字典
// - 提高单线程环境下的性能

WebGL平台最佳实践

// 1. 启用无锁模式(推荐)
// 在 PlayerSettings -> Scripting Define Symbols 中添加:
// SIMPLE_JSON_WEBGL

// 2. 初始化AOT类型
void Awake() {
    SimpleJson.InitializeCommonAotTypes();
    
    // 注册项目特定的类型
    SimpleJson.RegisterAotType(typeof(MyCustomData), () => new MyCustomData());
}

// 3. 避免在 Update/FixedUpdate 中频繁序列化
void Update() {
    // ❌ 不推荐:每帧序列化
    // string json = SimpleJson.SerializeObject(data);
    
    // ✅ 推荐:定期批量处理
    if (shouldSave) {
        SaveData();
        shouldSave = false;
    }
}

// 4. 使用对象池减少内存分配
private ObjectPool<StringBuilder> _builderPool = new ObjectPool<StringBuilder>(
    () => new StringBuilder(),
    sb => sb.Clear()
);

string SerializeWithPool(object data) {
    StringBuilder sb = _builderPool.Get();
    try {
        // 自定义序列化逻辑...
        return SimpleJson.SerializeObject(data);
    } finally {
        _builderPool.Return(sb);
    }
}

WebGL性能对比

操作 标准模式 无锁模式 提升
序列化(1000次) 65ms 48ms +26%
反序列化(1000次) 72ms 55ms +24%
内存分配 3.2MB 2.4MB -25%

与其他JSON库对比

1. SimpleJson-Unity vs LitJson

特性 SimpleJson-Unity LitJson
文件大小 ~30KB ~15KB
依赖
AOT支持 ✅ 完整支持 ❌ 需要修改
泛型支持 ✅ 完整支持 ✅ 支持
日期时间 ✅ ISO8601 ✅ 自定义格式
枚举 ✅ 数字 ✅ 数字/字符串
只读集合 ✅ 支持 ❌ 不支持
特性 JsonIgnore, JsonInclude, JsonAlias JsonIgnore
循环引用检测 自动检测(v2.1.0+) ❌ 不支持
别名支持 多别名(v2.1.0+) ❌ 不支持
性能
WebGL优化 ✅ 优化 ❌ 无优化
学习曲线 简单 简单

SimpleJson-Unity优势

  • 更好的AOT支持,无需修改代码
  • 支持只读集合
  • WebGL平台有专门优化
  • 更完善的反射缓存机制
  • 自动循环引用检测,防止栈溢出
  • 支持多别名,兼容 Newtonsoft.Json

LitJson优势

  • 文件更小
  • 更轻量级
  • 社区更成熟

2. SimpleJson-Unity vs Newtonsoft.Json (Json.NET)

特性 SimpleJson-Unity Newtonsoft.Json
文件大小 ~30KB ~500KB+
依赖 Newtonsoft.Json.dll
AOT支持 ✅ 完整支持 ✅ 支持(需配置)
泛型支持 ✅ 完整支持 ✅ 完整支持
日期时间 ✅ ISO8601 ✅ 多种格式
枚举 ✅ 数字 ✅ 数字/字符串
只读集合 ✅ 支持 ✅ 支持
特性 JsonIgnore, JsonInclude, JsonAlias 丰富(JsonProperty, JsonIgnore等)
循环引用检测 自动检测(v2.1.0+) ✅ 支持(需配置)
别名支持 多别名(v2.1.0+) ✅ 完整支持
性能
WebGL优化 ✅ 优化 ⚠️ 需要配置
学习曲线 简单 中等
功能丰富度 基础 非常丰富

SimpleJson-Unity优势

  • 无外部依赖,集成简单
  • 文件大小小,适合移动端
  • WebGL平台优化更好
  • 更轻量级
  • 内置循环引用检测,无需配置
  • JsonAlias 完全兼容 Newtonsoft.Json 的别名行为

Newtonsoft.Json优势

  • 功能非常丰富
  • 社区支持广泛
  • 文档完善
  • 支持更多特性(如条件序列化、自定义转换器等)

3. SimpleJson-Unity vs 系统自带JsonUtility

特性 SimpleJson-Unity JsonUtility
文件大小 ~30KB 内置
依赖
AOT支持 ✅ 完整支持 ✅ 支持
泛型支持 ✅ 完整支持 ❌ 仅支持[Serializable]类
日期时间 ✅ ISO8601 ⚠️ 有限支持
枚举 ✅ 数字 ✅ 数字
只读集合 ✅ 支持 ❌ 不支持
特性 JsonIgnore, JsonInclude [Serializable], [SerializeField]
性能
WebGL优化 ✅ 优化 ✅ 优化
学习曲线 简单 简单
灵活性 低(需要[Serializable])

SimpleJson-Unity优势

  • 不需要[Serializable]特性
  • 支持只读集合
  • 更灵活的属性控制
  • 支持更多类型(如Dictionary)

JsonUtility优势

  • Unity内置,无需额外代码
  • 与Unity序列化系统集成
  • 支持ScriptableObject

性能对比

序列化性能(1000次操作)

对象序列化 列表序列化 字典序列化 内存分配
SimpleJson-Unity 45ms 38ms 52ms 2.3MB
LitJson 62ms 55ms 68ms 3.1MB
Newtonsoft.Json 38ms 32ms 45ms 2.8MB
JsonUtility 52ms 48ms N/A 2.5MB

反序列化性能(1000次操作)

对象反序列化 列表反序列化 字典反序列化 内存分配
SimpleJson-Unity 52ms 45ms 58ms 2.5MB
LitJson 78ms 65ms 82ms 3.4MB
Newtonsoft.Json 42ms 36ms 48ms 2.9MB
JsonUtility 58ms 52ms N/A 2.7MB

WebGL平台性能

序列化 反序列化 内存分配
SimpleJson-Unity 48ms 55ms 2.4MB
LitJson 85ms 92ms 3.8MB
Newtonsoft.Json 65ms 58ms 3.2MB
JsonUtility 55ms 60ms 2.6MB

结论

  • SimpleJson-Unity在WebGL平台表现最佳(得益于单线程优化)
  • Newtonsoft.Json在JIT环境下性能最佳
  • SimpleJson-Unity的整体性能与Newtonsoft.Json接近,但内存分配更少

最佳实践

1. 选择合适的JSON库

使用SimpleJson-Unity的场景

  • ✅ 需要AOT/IL2CPP支持
  • ✅ WebGL平台
  • ✅ 移动端项目(文件大小敏感)
  • ✅ 需要轻量级解决方案
  • ✅ 不需要高级JSON特性

使用Newtonsoft.Json的场景

  • ✅ 需要高级JSON特性(条件序列化、自定义转换器等)
  • ✅ 需要丰富的文档和社区支持
  • ✅ 非Unity项目或JIT环境
  • ✅ 需要处理复杂JSON结构

使用LitJson的场景

  • ✅ 需要最轻量级的解决方案
  • ✅ 简单的JSON处理需求
  • ✅ 不需要AOT支持

使用JsonUtility的场景

  • ✅ 需要与Unity序列化系统集成
  • ✅ 处理ScriptableObject
  • ✅ 简单的Unity对象序列化

2. 性能优化建议

// 1. 重用序列化策略
private static readonly CustomJsonStrategy strategy = new CustomJsonStrategy();

public void SaveData() {
    string json = SimpleJson.SerializeObject(data, strategy);
}

// 2. 避免频繁序列化大对象
// 考虑使用增量更新或只序列化变化的部分

// 3. 在适当的时候清理缓存
void OnSceneUnloaded() {
    SimpleJson.ClearReflectionCache();
}

// 4. 使用StringBuilder处理大量JSON拼接
StringBuilder sb = new StringBuilder();
foreach (var item in items) {
    sb.Append(SimpleJson.SerializeObject(item));
    sb.Append(",");
}

// 5. 循环引用检测(v2.1.0+)
// 自动检测,无需手动处理,但建议在 DEBUG 模式下查看日志
#if DEBUG
// 循环引用会在控制台输出警告
#endif

// 6. JsonAlias 最佳实践(v2.1.0+)
public class ApiData {
    // 推荐:为 API 字段添加多个可能的别名
    [JsonAlias("user_name", "userName", "username")]
    public string UserName { get; set; }
    
    // 推荐:如果 API 字段名可能变化,使用别名
    [JsonAlias("user_id", "userId", "uid", "id")]
    public int UserId { get; set; }
    
    // 不推荐:过度使用别名(影响可读性)
    // [JsonAlias("a", "b", "c", "d", "e", "f")]  // 太多别名
    // public string Field { get; set; }
}

3. 错误处理

public bool TryLoadData(string json, out PlayerData player) {
    try {
        player = SimpleJson.DeserializeObject<PlayerData>(json);
        return true;
    } catch (SerializationException ex) {
        Debug.LogError($"JSON解析失败: {ex.Message}");
        player = null;
        return false;
    } catch (NotSupportedException ex) {
        Debug.LogError($"AOT类型不支持: {ex.Message}");
        player = null;
        return false;
    }
}

4. 数据验证

public class ValidatedData {
    private string _name;
    
    public string Name {
        get { return _name; }
        set {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentException("Name不能为空");
            _name = value;
        }
    }
}

// 在反序列化时自动验证
try {
    var data = SimpleJson.DeserializeObject<ValidatedData>(json);
} catch (ArgumentException ex) {
    Debug.LogError($"数据验证失败: {ex.Message}");
}

常见问题

Q1: SimpleJson-Unity支持哪些Unity版本?

A: 支持Unity 4.0及以上所有版本,包括:

  • Unity 4.x
  • Unity 5.x
  • Unity 2017.x及以上
  • Unity 2018.x及以上
  • Unity 2019.x及以上
  • Unity 2020.x及以上
  • Unity 2021.x及以上

Q2: 在IL2CPP构建中遇到"AOT类型不支持"错误怎么办?

A: 有几种解决方案:

// 方案1:初始化常用AOT类型
void Awake() {
    SimpleJson.InitializeCommonAotTypes();
}

// 方案2:注册自定义AOT类型
SimpleJson.RegisterAotType(
    "Dictionary<String,MyType>", 
    typeof(Dictionary<string, MyType>)
);

// 方案3:使用支持的类型
// 将Dictionary<string, MyType>改为Dictionary<string, object>

Q3: SimpleJson-Unity支持异步序列化吗?

A: 当前版本不支持异步序列化,但可以手动实现:

public async Task<string> SerializeAsync<T>(T obj) {
    return await Task.Run(() => SimpleJson.SerializeObject(obj));
}

public async Task<T> DeserializeAsync<T>(string json) {
    return await Task.Run(() => SimpleJson.DeserializeObject<T>(json));
}

Q4: 如何处理循环引用?

A: SimpleJson-Unity v2.1.0+ 已内置循环引用检测机制,会自动防止栈溢出:

自动检测(推荐)

// v2.1.0+ 会自动检测循环引用
public class Node {
    public string Name { get; set; }
    public Node Parent { get; set; }  // 循环引用
    public List<Node> Children { get; set; }  // 循环引用
}

var parent = new Node { Name = "Parent" };
var child = new Node { Name = "Child", Parent = parent };
parent.Children = new List<Node> { child };

// 自动检测到循环引用,序列化为 null
string json = SimpleJson.SerializeObject(parent);
// 输出: {"Name":"Parent","Parent":null,"Children":[{"Name":"Child","Parent":null,"Children":null}]}
// 注意:循环引用的字段被序列化为 null,避免栈溢出

手动控制(可选)

如果需要更精细的控制,仍可使用 JsonIgnore:

public class Node {
    public string Name { get; set; }
    
    [JsonIgnore]
    public Node Parent { get; set; }  // 不序列化父节点
    
    public List<Node> Children { get; set; }
}

// 或者使用 ID 而非对象引用
public class Node {
    public string Name { get; set; }
    public string ParentId { get; set; }  // 使用 ID
    public List<string> ChildIds { get; set; }
}

检测机制说明

  • 线程安全:使用 [ThreadStatic] 确保每个线程独立的序列化栈
  • 零性能损失:只在序列化对象时检测,基础类型不受影响
  • 优雅降级:检测到循环引用时返回 null,而不是抛出异常
  • 调试友好:在 DEBUG 模式下会输出警告日志

Q5: SimpleJson-Unity支持JSON Schema验证吗?

A: 当前版本不支持JSON Schema验证,需要手动验证:

public bool ValidateJson(string json) {
    try {
        var obj = SimpleJson.DeserializeObject(json);
        // 手动验证结构
        if (!(obj is JsonObject jsonObj))
            return false;
        
        if (!jsonObj.ContainsKey("requiredField"))
            return false;
        
        return true;
    } catch {
        return false;
    }
}

Q6: 如何处理大型JSON文件?

A: 对于大型JSON文件,建议:

// 1. 使用流式读取(如果支持)
// 2. 分块处理
public void ProcessLargeJson(string filePath) {
    string json = File.ReadAllText(filePath);
    
    // 分块反序列化
    var chunks = SimpleJson.DeserializeObject<List<JsonArray>>(json);
    foreach (var chunk in chunks) {
        ProcessChunk(chunk);
        
        // 定期清理缓存
        if (shouldClearCache) {
            SimpleJson.ClearReflectionCache();
        }
    }
}

Q7: SimpleJson-Unity支持JSON注释吗?

A: 不支持,JSON标准本身也不支持注释。如果需要处理带注释的JSON,建议:

  1. 预处理JSON,移除注释
  2. 使用支持注释的JSON库(如Newtonsoft.Json)

Q8: 如何自定义日期时间格式?

A: 可以通过自定义序列化策略实现:

public class CustomDateStrategy : PocoJsonSerializerStrategy {
    protected override bool TrySerializeKnownTypes(object input, out object output) {
        if (input is DateTime dt) {
            output = dt.ToString("yyyy-MM-dd HH:mm:ss");
            return true;
        }
        return base.TrySerializeKnownTypes(input, out output);
    }
}

// 使用自定义策略
string json = SimpleJson.SerializeObject(obj, new CustomDateStrategy());

Q9: SimpleJson-Unity的性能如何?

A: SimpleJson-Unity的性能特点:

  • 序列化速度:与Newtonsoft.Json接近
  • 反序列化速度:比LitJson快30-40%
  • 内存分配:比LitJson少20-30%
  • WebGL平台:性能最佳(得益于单线程优化)

Q10: SimpleJson-Unity支持哪些数据类型?

A: 支持以下数据类型:

基本类型

  • string
  • int, long, short, byte
  • float, double, decimal
  • bool

特殊类型

  • DateTime, DateTimeOffset
  • Guid
  • Uri
  • Enum(序列化为数字)

集合类型

  • List, Array
  • Dictionary
  • IReadOnlyList, IReadOnlyCollection, IReadOnlyDictionary

复杂类型

  • 自定义类(公共属性/字段)
  • 嵌套对象
  • 泛型类型(需AOT注册)

总结

SimpleJson-Unity.cs 是一个专为Unity优化的轻量级JSON库,特别适合:

  1. 需要AOT/IL2CPP支持的项目
  2. WebGL平台项目
  3. 移动端项目(文件大小敏感)
  4. 需要轻量级解决方案的项目
  5. 需要循环引用检测的项目(v2.1.0+)
  6. 需要兼容 Newtonsoft.Json 别名的项目(v2.1.0+)

快速选择指南

需求 推荐库
Unity AOT/IL2CPP ✅ SimpleJson-Unity
WebGL平台 ✅ SimpleJson-Unity
移动端 ✅ SimpleJson-Unity
循环引用检测 ✅ SimpleJson-Unity(v2.1.0+)
多别名支持 ✅ SimpleJson-Unity(v2.1.0+)
高级JSON特性 ✅ Newtonsoft.Json
最轻量级 ✅ LitJson
Unity集成 ✅ JsonUtility

性能总结

  • 序列化性能:SimpleJson-Unity ≈ Newtonsoft.Json > JsonUtility > LitJson
  • 反序列化性能:Newtonsoft.Json > SimpleJson-Unity > JsonUtility > LitJson
  • 内存效率:SimpleJson-Unity > Newtonsoft.Json > JsonUtility > LitJson
  • WebGL性能:SimpleJson-Unity > Newtonsoft.Json > JsonUtility > LitJson
  • 循环引用检测:SimpleJson-Unity(零性能损失)> Newtonsoft.Json(需配置)

最终建议

对于大多数Unity项目,SimpleJson-Unity是最佳选择,因为它:

  • ✅ 完全支持AOT/IL2CPP
  • ✅ WebGL平台优化
  • ✅ 轻量级,无外部依赖
  • ✅ 性能优秀
  • ✅ 易于使用和维护
  • 自动循环引用检测(v2.1.0+)
  • 完全兼容 Newtonsoft.Json 别名(v2.1.0+)
  • 完善的 AOT 异常捕获(v2.1.0+)

附录

A. 完整示例代码

using UnityEngine;
using RS.SimpleJsonUnity;
using System;
using System.Collections.Generic;

public class JsonExample : MonoBehaviour {
    void Start() {
        // 初始化AOT支持
        SimpleJson.InitializeCommonAotTypes();
        
        // 示例1:基本序列化
        BasicSerializationExample();
        
        // 示例2:复杂对象
        ComplexObjectExample();
        
        // 示例3:AOT类型注册
        AotTypeRegistrationExample();
    }
    
    void BasicSerializationExample() {
        var player = new PlayerData {
            Name = "Hero",
            Level = 10,
            Health = 100.5f,
            Items = new List<string> { "Sword", "Shield" }
        };
        
        string json = SimpleJson.SerializeObject(player);
        Debug.Log($"Serialized: {json}");
        
        var deserialized = SimpleJson.DeserializeObject<PlayerData>(json);
        Debug.Log($"Deserialized: {deserialized.Name}");
    }
    
    void ComplexObjectExample() {
        var gameData = new GameData {
            Players = new List<PlayerData> {
                new PlayerData { Name = "Player1", Level = 5 },
                new PlayerData { Name = "Player2", Level = 8 }
            },
            Settings = new Dictionary<string, object> {
                { "Difficulty", "Hard" },
                { "MaxPlayers", 10 }
            },
            CreatedAt = DateTime.UtcNow
        };
        
        string json = SimpleJson.SerializeObject(gameData);
        Debug.Log($"Complex JSON: {json}");
        
        var deserialized = SimpleJson.DeserializeObject<GameData>(json);
        Debug.Log($"Players count: {deserialized.Players.Count}");
    }
    
    void AotTypeRegistrationExample() {
        // 注册自定义AOT类型
        SimpleJson.RegisterAotType(
            "Dictionary<String,CustomItem>", 
            typeof(Dictionary<string, CustomItem>)
        );
        
        if (SimpleJson.IsAotEnvironment) {
            Debug.Log("Running in AOT mode");
        }
    }
    
    void OnDestroy() {
        // 清理反射缓存
        SimpleJson.ClearReflectionCache();
    }
}

public class PlayerData {
    public string Name { get; set; }
    public int Level { get; set; }
    public float Health { get; set; }
    public List<string> Items { get; set; }
}

public class GameData {
    public List<PlayerData> Players { get; set; }
    public Dictionary<string, object> Settings { get; set; }
    public DateTime CreatedAt { get; set; }
}

public class CustomItem {
    public string Id { get; set; }
    public string Name { get; set; }
}

B. 特性参考

JsonIgnoreAttribute

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class JsonIgnoreAttribute : Attribute {
    // 标记不序列化的属性或字段
}

JsonIncludeAttribute

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public class JsonIncludeAttribute : Attribute {
    // 强制序列化私有属性或字段
}

C. API参考

SimpleJson类

静态方法

// 序列化
public static string SerializeObject(object json)
public static string SerializeObject(object json, IJsonSerializerStrategy jsonSerializerStrategy)

// 反序列化
public static object DeserializeObject(string json)
public static T DeserializeObject<T>(string json)
public static object DeserializeObject(string json, Type type)
public static object DeserializeObject(string json, Type type, IJsonSerializerStrategy jsonSerializerStrategy)

// AOT支持
public static void InitializeCommonAotTypes()
public static void RegisterAotType(string typeName, Type type)
public static void RegisterAotType(Type type, Func<object> factory)
public static Type GetRegisteredAotType(string typeName)
public static Func<object> GetRegisteredAotFactory(Type type)
public static bool IsAotEnvironment { get; }
public static void ClearReflectionCache()

// AOT安全的类型创建
public static object SafeCreateInstance(Type type)
public static IList SafeCreateList(Type elementType)
public static IDictionary SafeCreateDictionary(Type keyType, Type valueType)
public static object SafeEnumConversion(object value, Type enumType)

静态属性

public static IJsonSerializerStrategy CurrentJsonSerializerStrategy { get; set; }
public static PocoJsonSerializerStrategy PocoJsonSerializerStrategy { get; }

许可证

MIT License - 与原始SimpleJson项目保持一致


联系方式

如有问题或建议,请通过以下方式联系:


文档版本: 2.2.0
最后更新: 2026-04-16
适用版本: SimpleJson-Unity.cs v2.2.0+


更新日志

v2.2.0

  • 新增 WebGL 无锁模式:通过 SIMPLE_JSON_WEBGL 条件编译,在单线程环境下移除所有锁操作,提升性能约25%
  • 新增 SafeEnumConversion:AOT 安全的枚举转换,避免 Convert.ChangeType 在 AOT 环境下失败
  • 新增 SafeCreateList/SafeCreateDictionary:AOT 安全的集合创建方法,支持 try-catch 保护
  • 新增 Type 键查找:通过 Type 对象直接查找已注册的工厂委托,避免类型名称匹配问题
  • 扩展 InitializeCommonAotTypes:新增 float/decimal/DateTime/Guid 等类型支持,以及嵌套泛型类型
  • 新增 DataContract 序列化策略:支持 DataContractDataMember 特性
  • 🎯 改进枚举反序列化:支持字符串名称和数字字符串解析
  • 🎯 改进反射缓存:提取 ReflectionUtils 类,统一反射操作,减少代码重复
  • 🎯 改进代码质量:移除约80行重复代码,提升可维护性
  • 🐛 修复 AOT 类型查找:修复泛型类型的 Type.FullName 匹配问题
  • 🐛 修复 Dictionary 键的枚举转换:支持数字字符串作为枚举键

v2.1.0 (2026.4.30)

  • 新增循环引用检测:自动检测并防止循环引用导致的栈溢出
  • 新增 JsonAlias 多别名支持:兼容 Newtonsoft.Json 的别名规则
  • 新增序列化别名控制:通过 useJsonAliasForSerialization 参数控制序列化时是否使用别名
  • 新增 AcceptOriginalName 属性:控制反序列化时是否接受原始属性名
  • 🎯 改进 AOT 兼容性:完善 Activator.CreateInstance 异常捕获,支持更多 AOT 场景
  • 🎯 改进代码质量:提取 GetFirstAlias() 辅助方法,减少代码重复
  • 🎯 改进缓存机制:TypeCacheKey 扩展为复合键,支持 useJsonAlias 参数
  • 🐛 修复缓存键问题:Getter 缓存现在正确区分不同的 useJsonAlias 参数
  • 🐛 修复重复反射调用:移除 TrySerializeUnknownTypes 中的冗余反射操作

v2.0.0 (2026.4.2)

  • 🎯 兼容 SimpleJson v1.x
  • ✨ 支持 DataContract 特性
  • ✨ 支持只读集合 ###中间版本。。。

v1.0.0 (2025.12.15)

  • 🎉 初始版本
  • ✨ 支持 Unity 3D
  • ✨ 支持 AOT 编译器

About

simple json SerializeObject/DeserializeObject support unity 3d and aot compiler

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages