0%

Unity集换式卡牌游戏_Dictionry序列化成json

在开始讲解这一章节前,我们需要了解,什么是 Json.

Json

他的全称是 JavaScript Object Notation 【JavaScript 对象表示法】

JSON 是存储和交换文本信息的语法。类似 XML。json是基于ECMAScript语法,但这并不意味着 json 必须在 js 中使用,或者必须要产生什么联系, json 在 js 中的处理也并没有比其他语言占有更多优势。只是因为语法相似,而使得js开发者能更快的上手 json 而已。

JSON采用完全独立于任何程序语言的文本格式,但是也使用了类似于 C 语言家族的习惯(包括 C、C++、C#、Java、JavaScript、Perl、Python 等)。这些特性使 JSON 成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

典型的 Json 数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
对象:
{
"name": "火球术",
"cost": 1,
"Owner": "法师"
}

数组:
["hello",3.1415,"json"]

数组嵌套对象:
[{"name":"admin","age":18},
{"name":"root","age":16},
{"name":"张三","age":20}]

Json 语法规则

  • 数据在 键值对
  • 数据由逗号 , 分隔
  • 使用斜杆 \ 来转义字符
  • 大括号 {} 保存对象
  • 中括号 [] 保存数组,数组可以包含多个对象

json 的值

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false)
  • 数组(在中括号中)
  • 对象(在大括号中)
  • null

JsonUtility

JsonUtility 是 Unity 提供的一个工具类,用于序列化和反序列化 Json 数据。

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 序列化
string json = JsonUtility.ToJson(obj);

// 反序列化
myObject = JsonUtility.FromJson<T>(json);

// 从 Json 文本中读取数据并将其反序列化到现有对象中。
FromJsonOverwrite(string text, object objectToOverwrite)


ToJson(object target, bool prettyPrint)
target:对象转换为 Json 数据文本
prettyPrint:决定最终的 Json 数据文本是否是一个格式化后的数据文本。
即是否使用 Json 文本的 Format 化。

FromJson(string text)
将 Json 数据文本转存至类中 public 或 附有 SerializeField 特性的字段上赋值。
使用时无需管理值具体分配。其将基于字段命名自行匹配并赋值。
此代码将创建一个新的 T 实例,并使用 JSON 数据设置该实例的值。如果 JSON 数据包含的某些值未映射到 T 中的字段,则序列化程序将忽略这些值。如果 JSON 数据缺少 T 中某些字段的值,则序列化程序会在返回的对象中保留这些字段的构造值。

FromJsonOverwrite(string text, object objectToOverwrite)
在现有对象上反序列化 JSON 数据,从而覆盖所有现有数据。
使用时无需管理值具体分配。其将基于字段命名自行匹配并赋值。
如果 JSON 数据不包含某个字段的值,则序列化程序不会更改该字段的值。
JSON 序列化程序 API 支持 MonoBehaviour 和 ScriptableObject 子类以及普通结构和类。但是,将 JSON 反序列化为 MonoBehaviour 或 ScriptableObject 子类时,必须使用 FromJsonOverwrite 方法。如果尝试使用 FromJson,则 Unity 会抛出异常,因为不支持此行为。

注意事项

  • 仅支持 MonoBehaviour / ScriptableObject 继承类的序列化
  • 仅支持 [Serializable] 的普通类与结构体
  • 仅序列化 public 或 [SerializeField] 标签的字段
  • 在内部,此方法使用 Unity 序列化器;因此传入的对象必须受序列化器支持:它必须是 MonoBehaviour、ScriptableObject 或应用了 Serializable 属性的普通类/结构。要包含的字段的类型必须受序列化器支持;不受支持的字段以及私有字段、静态字段和应用了 NonSerialized 属性的字段会被忽略。
  • 支持 List、Array 数据类型,但不支持 Dictionary、Query、Stack 等集合
  • 支持 Enum 枚举,但默认存储值为数值类型

字典的序列化和反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using System.Collections.Generic;
using UnityEngine;
using System;

public class SerializeDictionary
{
public static string DicToJson<TKey, TValue>(Dictionary<TKey, TValue> dic)
{
return JsonUtility.ToJson(new SerializeDictionary<TKey, TValue>(dic));
}

public static Dictionary<TKey, TValue> DicFromJson<TKey, TValue>(string str)
{
return JsonUtility.FromJson<SerializeDictionary<TKey, TValue>>(str).ToDictionary();
}
}

[Serializable]
public class SerializeDictionary<TKey, TValue> : ISerializationCallbackReceiver
{
[SerializeField]
List<TKey> keys;
[SerializeField]
List<TValue> values;

Dictionary<TKey, TValue> target;
public Dictionary<TKey, TValue> ToDictionary() { return target; }

public SerializeDictionary(Dictionary<TKey, TValue> target)
{
this.target = target;
}

public void OnBeforeSerialize()
{
keys = new List<TKey>(target.Keys);
values = new List<TValue>(target.Values);
}

public void OnAfterDeserialize()
{
var count = Math.Min(keys.Count, values.Count);
target = new Dictionary<TKey, TValue>(count);
for (var i = 0; i < count; ++i)
{
target.Add(keys[i], values[i]);

}
}
}

本文作于2023-08-21,首发于个人博客https://rdququ.top/

欢迎关注我的其它发布渠道