一、分析
最近写开放世界沙盒游戏,需要把整个世界序列化,反序列化。
可选方案有
1-C#自带的序列化工具-直接序列化成2进制文件,缺点是不支持Dictionay,Vector3等复杂对象的支持。有点是比较快,而且不需要引入其他插件。可以增加字段,但是不能删除字段。
2-自己写文本序列化:优点,灵活。缺点,麻烦。
3-使用Protobuf序列化:优点,快,省空间,但是我又不是发网络协议,用不着你省空间。缺点:需要自己定义PB结构体,生成一堆烂七八糟的代码。
4-Json.Net这是我最后选择的方案。有点,比较快,空间浪费点不过无所谓。支持Dictionary,虽然不支持Vector3这种Unity自带结构体,但那是因为Vector3有循环引用引起的,自己创建一个桥接类处理一下就好。删除增加字段都可以。删除的字段直接忽略了,增加的字段,使用默认值。
二、Json.Net简要用法
测试用的类:
public struct JsonVector3
{
public float x;
public float y;
public float z;
public JsonVector3(Vector3 v3){
x = v3.x;
y = v3.y;
z = v3.z;
}
public override string ToString(){
return string.Format("X:{0}-Y:{1}-Z:{2}", x, y, z);
}
public Vector3 ToVector3(){
return new Vector3(x,y,z);
}
}
public class TestClass
{
public class InnerClass{
public InnerClass(string name, int count,
int slot1, int slot2)
{
itemName = name;
itemCount = count;
itemSlot.Add( slot1 );
itemSlot.Add( slot2 );
}
public string itemName;
public int itemCount;
public List itemSlot = new List();
public override string ToString(){
return string.Format("Name:{0},Count{1},
Slot1{2},SLot{3}",itemName,itemCount,
itemSlot[0],itemSlot[1]);
}
}
public string PlayerNBame = "Wh";
public bool sex;
private int hp = 100;
//public Vector3 position;
public JsonVector3 position;
public List skillId = new List();
public Dictionary itemTable = new Dictionary();
public TestClass(int hp){
this.hp = hp;
}
public override string ToString(){
StringBuilder sb = new StringBuilder();
sb.Append(PlayerNBame);
if (sex){
sb.Append("Male,");
}
else{
sb.Append("Female,");
}
sb.Append(hp);
sb.Append(",");
sb.Append(position);
sb.Append(",");
foreach (var id in skillId){
sb.Append(id);
sb.Append(",");
}
foreach (var itemId in itemTable.Keys){
sb.Append(itemId);
sb.Append("-");
sb.Append(itemTable[itemId]);
sb.Append(",");
}
return sb.ToString().Substring(0, sb.Length - 1);
}
}
最基础的用法,序列化一个类,并反序列化之。
TestClass test = new TestClass(140);//[1]
test.position = new JsonVector3( Vector3.one * 3.15f );//[2]
test.PlayerNBame = "KKK";
test.skillId.Add(1);//[3]
test.skillId.Add(3);
test.skillId.Add(9);
test.itemTable[1] = new TestClass.InnerClass("Pistal",1,4,3);
test.itemTable[2] =new TestClass.InnerClass("Pistal",1,2,5);
//[4],[5]
string jsonString = JsonConvert.SerializeObject(test);
Debug.Log( jsonString );
StreamWriter sw = new StreamWriter( Application.persistentDataPath +"/quickSave.txt" );
sw.WriteLine( jsonString );//[6]
sw.Flush();
sw.Close();
StreamReader sr = new StreamReader(Application.persistentDataPath +"/quickSave.txt" );
string readString = sr.ReadToEnd();
TestClass deserializeObject = JsonConvert.DeserializeObject(readString);
Debug.Log(deserializeObject);
结果:
Json序列化结果:
{"PlayerNBame":"KKK","sex":false,"position":{"x":3.15,"y":3.15,"z":3.15},"skillId":[1,3,9],"itemTable":{"1":{"itemName":"Pistal","itemCount":1,"itemSlot":[4,3]},"2":{"itemName":"Pistal","itemCount":1,"itemSlot":[2,5]}}}
反序列化结果:
KKKFemale,0,X:3.15-Y:3.15-Z:3.15,1,3,9,1-Name:Pistal,Count1,Slot14,SLot3,2-Name:Pistal,Count1,Slot12,SLot5
Json.Net不需要你提供默认的无参数构造函数
Json.Net支持结构体序列化,支持将结构体作为成员变量序列化
json.Net支持序列化反序列化List
json.Net支持序列化反序列化Dictionary
Json.Net支持序列化内部类
Json.Net可以认为是一行字符串,用一句WriteLine就可以写入磁盘文件。
Json.Net允许删除字段,删除的字段,不影响反序列化。
Json.Net允许增加字段,增加的字段,反序列化时会被赋予默认值
Json.Net不支持Vector3,是因为检测到了循环引用。