C#Like是Unity的热更方案,使用纯C#语言写出可以热更新的代码,就像可以在所有平台使用DLL(动态链接库)文件一样.遵从KISS设计原则,让用户轻松构建或升级成Unity的热更新项目.
简介
本篇主要介绍唯一可以在C#Like热更新框架使用的JSON库KissJSON,为C#Like度身定做的,后来也发布源码到GitHub,让所有的C#代码都可以免费使用.
这个世界上的JSON库何其多,KissJSON跟其他的JSON库比,有什么特别过人之处?
- 完全兼容C#Like,可在热更脚本里使用
- JSONData与内置类型无缝互转,直接当做内置类型使用,例如数值计算
- JSON字符串与JSONData与类/结构体之间轻松转换
用法:
1 可与JSONData之间直接互转的内置类型:
- 内置类型: string sbyte ushort uint ulong byte short int long bool float double DateTime
- 可空内置类型: sbyte? ushort? uint? ulong? byte? short? int? long? bool? float? double? DateTime?
- 枚举
- List<内置类型>
- Dictionary<string,内置类型>
2 JSONData与内置类型无缝互转,直接当做内置类型使用,例如数值计算:
- 内置类型 ->JSONData
JSONData iData = 2;
Console.WriteLine("JSONData iData = 2; test iData = " + iData);//输出 2
JSONData fData = 88.8f;
Console.WriteLine("JSONData fData = 88.8f; test fData = " + fData);//输出 88.8
List<string> listValue = new List<string>();
listValue.Add("test list str1");
listValue.Add("test list str2");
JSONData listData = listValue;
Console.WriteLine("JSONData listData = listValue; test listData = " + listData);//输出 ["test list str1","test list str2"]
Dictionary<string, int> dictValue = new Dictionary<string, int>();
dictValue.Add("key1", 11);
dictValue.Add("key2", 22);
JSONData dictData = dictValue;
Console.WriteLine("JSONData dictData = dictValue; test dictData = " + dictData);//输出 {"key1":11,"key2":22}
- JSONData -> 内置类型
int iValue = iData;
Console.WriteLine("int iValue = iData; test iValue = " + iValue);//输出 2
float fValue = fData;
Console.WriteLine("float fValue = fData; test fValue = " + fValue);//输出 88.8
List<string> listValue2 = listData;
string strTemp = "";
foreach (var str in listValue2)
strTemp += str + ",";
Console.WriteLine("List<string> listValue2 = listData; test listValue2 = " + strTemp);//输出 test list str1,test list str2,
Dictionary<string, int> dictValue2 = dictData;
strTemp = "";
foreach (var item in dictValue2)
strTemp += "(" + item.Key + "=" + item.Value + ")";
Console.WriteLine("Dictionary<string, int> dictValue2 = dictData; test dictValue2 = " + strTemp);//输出 (key1=11)(key2=22)
- JSONData 与 内置类型 之间数值运算
JSONData exprData1 = 2;
JSONData exprData2 = 3;
JSONData exprData3 = exprData1 * exprData2;
Console.WriteLine("test Math Expression; exprData3 = exprData1 * exprData2; exprData3 = " + exprData3);//输出 6
exprData3 = exprData1 << 5;
Console.WriteLine("test Math Expression; exprData3 = exprData1 << 5; exprData3 = " + exprData3);//输出 64
exprData3 = exprData1 - exprData2;
Console.WriteLine("test Math Expression; exprData3 = exprData1 - exprData2; exprData3 = " + exprData3);//输出 -1
exprData3 *= exprData2;//exprData3=-1;exprData2=3
Console.WriteLine("test Math Expression; exprData3 *= exprData2; exprData3 = " + exprData3);//输出 -3
iData = 2;
if (iData > 1)
Console.WriteLine("test Math Expression; iData = 2, enter if (iData > 1)");//进入这里
else
Console.WriteLine("test Math Expression; iData = 2, not enter if (iData > 1)");
3 JSON字符串与JSONData与类之间轻松转换:
- JSON字符串 -> JSONData
string strJson = @"{
"str": "{test \"str",
"i": 11,
"j": 2.3,
"k": [
3,
null,
{
"m": true
}
],
"l": {
"x": 1,
"y": "abc"
}
";
JSONData data = KissJson.ToJSONData(strJson);
//accept JSONData by ["key"] and [index]
Console.WriteLine("JSON string => JSONData; test data[\"str\"] = " + data["str"]);//输出 {test "str
Console.WriteLine("JSON string => JSONData; test data[\"i\"] = " + data["i"]);//输出 11
Console.WriteLine("JSON string => JSONData; test data[\"j\"] = " + data["j"]);//输出 2.3
Console.WriteLine("JSON string => JSONData; test data[\"k\"] = " + data["k"]);//输出 [3,null,{"m":true}]
Console.WriteLine("JSON string => JSONData; test data[\"l\"] = " + data["l"]);//输出 {"x":1,"y":"abc"}
Console.WriteLine("JSON string => JSONData; test data[\"k\"][0] = " + data["k"][0]);//输出 3
Console.WriteLine("JSON string => JSONData; test data[\"l\"][\"y\"] = " + data["l"]["y"]);//输出 abc
Console.WriteLine("JSON string => JSONData; test data[\"k\"][2][\"m\"] = " + data["k"][2]["m"]);//输出 true
- JSONData -> JSON字符串
JSONData listData3 = JSONData.NewDictionary();
listData3.Add("key1", 10); //类似Dictionary的函数'Add(key,value)'的方式加数据
listData3["key2"] = "test string"; //类似Dictionary/List索引'this[]'的方式加数据
listData3["key3"] = JSONData.NewList(); //我们加一个List类型的JSONData
if (listData3.ContainsKey("key3")) //确保'key3'是否存在,如果你不确认的情况下
listData3["key3"].Add(1); //插入一些数据到list里
listData3["key3"].Insert(0,"string2"); //插入一些数据到list里, 我们这里不检查'key3'是否存在,因为我们已经确认它是存在的
listData3["key4"] = JSONData.NewDictionary(); //我们加一个Dictionary类型的JSONData
listData3["key4"]["x"] = 1;
listData3["key4"]["y"] = 2;
listData3["key4"]["z"] = 3;
Debug.Log("test JSONData => JSON string; strJson = " + listData3.ToJson());//输出 {"key1":10,"key2":"test string","key3":["string2",1],"key4":{"x":1,"y":2,"z":3}}
- 与JSON字符串/JSONData互转相关的类/结构体
/// <summary>
/// 测试 类 <=> JSON字符串
/// </summary>
public class TestJsonDataSub
{
public int? id;//测试可空类型
public string name;
public Vector2 v2;//你可以添加其他类型,例如Color/Rect/Vector3/...
public List<string> info;
public Dictionary<string, int> maps;
}
//类被标为KissJsonDontSerialize的类会被JSON解析器忽略
[KissJsonDontSerialize]
public class TestJsonDataSub2
{
public int id;
}
/// <summary>
/// 测试 类 <=> JSON字符串
/// </summary>
public class TestJsonData
{
[KissJsonDontSerialize]
public string str;//被标为KissJsonDontSerialize的属性会被JSON解析器忽略
public int i;
public DayOfWeek j;//测试枚举(非热更脚本)
public TestHotUpdateEnum z;//测试枚举(热更脚本)
public List<int?> k;
public Dictionary<string, TestJsonDataSub> datas;//测试Dictionary
public TestJsonDataSub data;//测试单个的类中类
public TestJsonDataSub2 data2;//这个会被JSON解析器忽略,因为TestJsonDataSub2这个类被标为KissJsonDontSerialize
}
/// <summary>
/// 测试枚举
/// </summary>
public enum TestHotUpdateEnum
{
Morning,
Afternoon,
Evening
}
/// <summary>
/// 测试结构体
/// </summary>
public struct Vector2
{
public float x;
public float y;
public override string ToString()
{
return $"({x:F2},{y:F2})";
}
}
- JSON字符串 -> 类/结构体
strJson = "{\"str\":\"{test str\",\"i\":11,\"j\":1,\"z\":2,\"k\":[3,null,7],\"datas\":{\"aa\":{\"id\":1,\"name\":\"aaa\",\"v2\":{\"x\":1,\"y\":2},\"info\":[\"a\",\"xd\",\"dt\"],\"maps\":{\"x\":1,\"y\":2}},\"bb\":{\"id\":2,\"name\":\"bbb\",\"v2\":{\"x\":3,\"y\":4},\"info\":[\"x\",\"x3d\",\"ddt\"],\"maps\":{\"x\":2,\"y\":3}}},\"data\":{\"id\":3,\"name\":\"ccc\",\"v2\":{\"x\":3,\"y\":1},\"info\":[\"ya\",\"xyd\",\"drt\"],\"maps\":{\"x\":3,\"y\":4}}}";
TestJsonData testJsonData = (TestJsonData)KissJson.ToObject(typeof(TestJsonData), strJson);//JSON 字符串 => 类
测试 JSONData => 类
//TestJsonData testJsonData = (TestJsonData)KissJson.ToObject(typeof(TestJsonData), KissJson.ToJSONData(strJson));//JSONData => 类
Console.WriteLine(testJsonData.str);//输出 Null
Console.WriteLine(testJsonData.i);//输出 11
//"j":"Monday"和"j":"1"和"j":1都会识别为'DayOfWeek.Monday'
//推荐使用"j":1,因为ToJson()会输出为"j":1
Console.WriteLine(testJsonData.j);//输出 Monday
Console.WriteLine((int)testJsonData.j);//输出 1
Console.WriteLine(testJsonData.z);//输出 2
foreach (var item in testJsonData.k)
Console.WriteLine(item);//输出 3/输出 null/输出 7
foreach (var datas in testJsonData.datas)
{
Console.WriteLine(datas.Key);//输出 aa/输出 bb
Console.WriteLine(datas.Value.v2);//输出 (1.0, 2.0)/输出 (3.0, 4.0)
}
- 类/结构体 -> JSON字符串
strTemp = KissJson.ToJson(testJsonData);//类/结构体 => JSON字符串
Console.WriteLine(strTemp);//输出 {"i":11,"j":1,"z":2,"k":[3,null,7],"datas":{"aa":{"id":1,"name":"aaa","v2":{"x":1,"y":2},"info":["a","xd","dt"],"maps":{"x":1,"y":2}},"bb":{"id":2,"name":"bbb","v2":{"x":3,"y":4},"info":["x","x3d","ddt"],"maps":{"x":2,"y":3}}},"data":{"id":3,"name":"ccc","v2":{"x":3,"y":1},"info":["ya","xyd","drt"],"maps":{"x":3,"y":4}}}
- 类/结构体 -> JSONData
data = KissJson.ToJSONData(testJsonData);
4 格式化JSON字符串:
Console.WriteLine(data.ToJson(true));//格式化JSON字符串,更好的可读性
Console.WriteLine(data.ToJson());//不格式化JSON字符串,可读性差但JSON字符串很短,更适合传输
格式化JSON字符串为:
{
"i": 11,
"j": 1,
"z": 2,
"k": [
3,
null,
7
],
"datas": {
"aa": {
"id": 1,
"name": "aaa",
"v2": {
"x": 1,
"y": 2
},
"info": [
"a",
"xd",
"dt"
],
"maps": {
"x": 1,
"y": 2
}
},
"bb": {
"id": 2,
"name": "bbb",
"v2": {
"x": 3,
"y": 4
},
"info": [
"x",
"x3d",
"ddt"
],
"maps": {
"x": 2,
"y": 3
}
}
},
"data": {
"id": 3,
"name": "ccc",
"v2": {
"x": 3,
"y": 1
},
"info": [
"ya",
"xyd",
"drt"
],
"maps": {
"x": 3,
"y": 4
}
}
}
不格式化JSON字符串:
{"i":11,"j":1,"z":2,"k":[3,null,7],"datas":{"aa":{"id":1,"name":"aaa","v2":{"x":1,"y":2},"info":["a","xd","dt"],"maps":{"x":1,"y":2}},"bb":{"id":2,"name":"bbb","v2":{"x":3,"y":4},"info":["x","x3d","ddt"],"maps":{"x":2,"y":3}}},"data":{"id":3,"name":"ccc","v2":{"x":3,"y":1},"info":["ya","xyd","drt"],"maps":{"x":3,"y":4}}}
5 深复制JSONData:
JSONData clone = JSONData.DeepClone(data);//深复制JSONData对象, 'clone'和'data'是两个独立的对象.
JSONData notClone = data; //仅仅是复制,相当于'notClone'是'data'的别名,它们是同一个对象.
data["i"] = 100;//修改'data'对象,不会影响到'clone'对象的数值.
Console.WriteLine(clone.ToJson());
Console.WriteLine(notClone.ToJson());
本系列文章导读:
- Unity热更新方案C#Like(一)-序言
- Unity热更新方案C#Like(二)-导出官方示范的例子,确认方案可行性
- Unity热更新方案C#Like(三)-详解支持的C#特性:类
- Unity热更新方案C#Like(四)-详解支持的C#特性:委托和Lambda
- Unity热更新方案C#Like(五)-详解支持的C#特性:运算表达式
- Unity热更新方案C#Like(六)-详解支持的C#特性:循环语法
- Unity热更新方案C#Like(七)-详解支持的C#特性:get/set访问器
- Unity热更新方案C#Like(八)-详解支持的C#特性:多线程
- Unity热更新方案C#Like(九)-详解支持的C#特性:Using和命名空间
- Unity热更新方案C#Like(十)-详解支持的C#特性:宏和区域
- Unity热更新方案C#Like(十一)-详解支持的C#特性:枚举
- Unity热更新方案C#Like(十二-详解支持的C#特性:参数修饰符
- Unity热更新方案C#Like(十三)-详解支持的C#特性:函数重载和默认参数
- Unity热更新方案C#Like(十四)-详解支持的C#特性:异常处理
- Unity热更新方案C#Like(十五)-详解支持的C#特性:关键字:unsafe typeof nameof $ @ #pragma #warning #error
- Unity热更新方案C#Like(十六)-详解支持的C#特性:其他杂项:初始值设定项,表达式主体,内联变量声明
- Unity热更新方案C#Like(十七)-详解支持的长链接Socket和WebSocket
- Unity热更新方案C#Like(十八)-详解如何和Unity交互
- Unity热更新方案C#Like(十九)-详解KissJSON:唯一可以在本热更新框架使用的JSON库
- Unity热更新方案C#Like(二十)-详解KissCSV:一个简易实用的CSV表格读取方式
- Unity热更新方案C#Like(廿一)-详解KissFrameworkServer:对应的示范例子和官网所用的服务器框架
- Unity热更新方案C#Like(廿二)-详解内置的例子C#Like Demo:飞机大战,简易聊天室,简易账号/物品/邮件系统
- Unity热更新方案C#Like(廿三)-实战:示范如何把Unity官方免费例子Tanks! Tutorial转成可热更新项目
- Unity热更新方案C#Like(廿四)-实战:示范如何把Unity官方免费例子Platformer Microgame转成可热更新项目
- Unity热更新方案C#Like(廿五)-实战:示范如何建立初始包CSharpLikeFreeDemo项目
- Unity热更新方案C#Like(廿六)-(可选)详解免费版的演示如何升级到完整版的演示