excel2json是一款将Excel表格文件快速生成json和C#数据类的高效插件,详情了解如下:

https://neil3d.github.io/coding/excel2json.html

该插件有两种模式,分别是命令行和图像界面;当然了,为了更方便愉快的进行大规模转换,可以写两个批处理文件来执行:

Single文件表示执行单个选中文件,AutoAll表示执行该路径下所有xlsx文件;输出文件夹的位置为output,如果该目录下无output文件夹,则自动创建:

Single.bat详情如下:

  1. @SET OUTPUT_FOLDER=.\output
  2. @SET EXE=.\tool\excel2json.exe
  3.  
  4. if not exist %OUTPUT_FOLDER% md %OUTPUT_FOLDER%
  5.  
  6. @echo off
  7. set path=%
  8. echo 源文件路径%path%
  9. set name=%~n1
  10. echo 源文件名%name%
  11. set outputpath=%OUTPUT_FOLDER%\%name%
  12. echo 输出文件路径%outputpath%
  13.  
  14. @CALL %EXE% --excel %path% --json %outputpath%.json --header --csharp %outputpath%.cs -a
  15.  
  16. pause

前两行为参数设置,分别为输出文件夹路径和可执行文件路径,一个%表示参数,后面使用该参数作为变量时格式为[%参数%]。[.\]代表相对路径

第四行,如果不存在该路径文件夹则自动创建,注意如果没有这一行也没有对应参数所指示的路径,这时并不会自动创建路径而是会直接报错

第七行,得到当前选中的第一个文件路径作为参数

第九行,得到当前选中的第一个文件的文件名(不包含后缀)

类似的还有:

%~d1\   得到当前选中的第一个文件所在磁盘符

%~dp1  得到当前选中的第一个文件路径位置(不包含文件名和文件后缀名)

%~nx1 得到当前选中的第一个文件的文件名和后缀

这里主要是为了保持输出文件的名称与选择的文件名称一致,所以最终的输出路径为设置的输出路径位置+源文件名

最后调用@CALL 执行参数对应路径下的exe文件,根据excel2json提供的命令行参数设置启动参数。

AutoAll.bat详情如下:

  1. @SET EXCEL_FOLDER=.\
  2. @SET OUTPUT_FOLDER=.\output
  3. @SET EXE=.\tool\excel2json.exe
  4.  
  5. @ECHO Converting excel files in folder %EXCEL_FOLDER% ...
  6. if not exist %OUTPUT_FOLDER% md %OUTPUT_FOLDER%
  7.  
  8. for /f "delims=" %%i in ('dir /b /a-d /s %EXCEL_FOLDER%\*.xlsx') do (
  9. @echo processing %%~nxi
  10. @CALL %EXE% --excel %EXCEL_FOLDER%\%%~nxi --json %OUTPUT_FOLDER%\%%~ni.json --header --csharp %OUTPUT_FOLDER%\%%~ni.cs -a
  11. )
  12. pause

上面这个批处理文件在帮助页面中有实例,最主要是做了一个路径内的文件查询和批量执行:

dir /b /a-d /s  从指定路径遍历搜索文件,路径参数即为当前路径下的所有.xlsx文件,当然了,也可以动态修改前面的excel所在文件夹参数配置

%%~nxi与%%~ni 和上面的类似只不过不是1而是循环体中的变量i,表示对应数目索引的文件

需要注意的是,在cmd模式下的循环变量是一个百分号加循环标识符(即%i)而在批处理文件中需要两个百分号才行(%%i)

下面提供已经写好批处理的文件下载链接:

https://files.cnblogs.com/files/koshio0219/excel2json.zip

这里的批处理统一将Execl导出为数组类型,方便在Unity中进一步反序列化,如果需要字典类型,可以继续修改或添加帮助中指定的参数,也可以直接利用图形界面分别导出

之所以默认导出数组类型,因为Unity默认的JsonUtility解析字典类型几乎是不可能,即使强行可以,那也是用的两个List做对应关系,

跟真正的字典类型导出的Json文件格式区别很大,直接解析出来就是个空文件。当然了,如果只是用于数据保存和读写是这么做是完全可以的,

只要读和写都是用的同一个序列化和反序列化的方式即可。但excel2json本身也并不是专门为了Unity的序列化而做的;

查看该工程的源代码就可以知道,该工程用的序列化方式为Newtonsoft.Json,如果实在需要用字典类型来解析,可以直接导入该Dll使用;

下面分别进行数组型Json与字典型Json的反序列化讨论:

1.数组型Json(或List型)

比如下面这段测试Json和C#文件:(通过excel2json导出)

  1. [
  2. {
  3. "ID": "4l523",
  4. "Hp": ,
  5. "Atk": 6.3,
  6. "Def": ,
  7. "State": ""
  8. },
  9. {
  10. "ID": "p6",
  11. "Hp": ,
  12. "Atk": ,
  13. "Def": 2.3,
  14. "State": ""
  15. },
  16. {
  17. "ID": 0.3,
  18. "Hp": 0.2,
  19. "Atk": "2.3,7",
  20. "Def": ,
  21. "State": ""
  22. }
  23. ]
  1. [System.Serializable]
  2. public class Buff
  3. {
  4. public string ID; // 编号
  5. public int Hp; // 血量
  6. public float Atk; // 攻击
  7. public float Def; // 防御
  8. public BuffData State; // 状态
  9. }

为了进行测试,我在Excel表格中故意填错一些与当前类型不匹配的数据,例如第三组中的ID,Hp,Atk,Def都设置得与当前的数据类型不同,且Atk一个表格中填了两个数字;

Unity解析数组(或List)Json文件也不能直接反序列化,例如直接写为:

var data = JsonUtility.FromJson<Buff[]>(json.text);

只会得到一个空的数据结构。

这里需要一个额外的序列化转换:

  1. using UnityEngine;
  2.  
  3. public class JsonHelper
  4. {
  5. public static T[] GetJsonArray<T>(string json)
  6. {
  7. string newJson = "{ \"array\": " + json + "}";
  8. Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(newJson);
  9. return wrapper.array;
  10. }
  11.  
  12. [System.Serializable]
  13. private class Wrapper<T>
  14. {
  15. public T[] array;
  16. }
  17. }

需要注意的是,如果以该方式反序列化数组,之前导出的Json文件不能包含文件名,在上面的脚本中统一将文件名添加为array。

newJson的文件名称必须与Wrapper类中的泛型数组T[]的名字保持一致,才能反序列化出指定数据。

如果不利用泛型的话,需要每一个文件单独再写一个类来进行反序列化,同样的数组的标识符必须与Json中的Array文件名称保持一致。

为了更方便的通过ID来读取数据,也可以将得到的数组再重新写入一个字典中,通过反射在获取ID的值作为键,前提是规定每一个Json文件中必须有ID这一字段:

  1. public class JsonDatas<T>
  2. {
  3. public Dictionary<string, T> Dict = new Dictionary<string, T>();
  4. public static JsonDatas<T> FromJson(string json)
  5. {
  6. var re = new JsonDatas<T>();
  7. var datas = JsonHelper.GetJsonArray<T>(json);
  8. foreach(var data in datas)
  9. {
  10. var info = data.GetType().GetField("ID");
  11. var idstr = info.GetValue(data).ToString();
  12. re.Dict.Add(idstr, data);
  13. }
  14. return re;
  15. }
  16.  
  17. public T Get(string ID)
  18. {
  19. return Dict[ID];
  20. }
  21. }

这里反射取字段值得时候遇到了一个坑,特意记录一下:

Type.GetField(string name) 这个是取字段的值,取不了属性

Type.GetProperty(string name) 这个是取属性的值,取不了字段

这两个取出来的内容是不一样的,请注意区分,不然半天也查不出错误出在哪里(说的就是我本人)

调试后的结果如下,能够成功解析出Json了:

这里特意来看看第三组数据为什么没有报错 ,神奇的是,JsonUtility竟然自动帮你转化为了对应的类型:

ID  0.3被转为了“0.300000”;Hp 0.2 变为了0;更震惊的是,Atk竟然也没有报错,而是成功解析出了逗号前面的数字,emm有点迷。

个人猜想是JsonUtility先尝试将错误的数据类型转为正确类型,如果无法转换,则从头开始读,读取到该类型下无法识别的字符就自动终止。(只是随便猜猜不用太当真)

2.字典型Json

如果非要导出字典型Json来反序列化,那就不能再用Unity自带的JsonUtility了,而是最好导入和序列化时用的是一样的Newtonsoft.Json

下面提供与Unity适配的Newtonsoft.Json包JsonNet.9.0.1.unitypackage下载地址:

https://files.cnblogs.com/files/koshio0219/JsonNet.9.0.1.zip

如果是反序列化单个不带任何签名的字典,只用一句话就可以了,不需要建立任何新类:

var data = JsonConvert.DeserializeObject<Dictionary<string, Buff>>(json.text);

试比较带签名和不带签名的Json:

  1. {
  2. "Buff": {
  3. "4l523": {
  4. "ID": "4l523",
  5. "Hp": ,
  6. "Atk": 6.3,
  7. "Def": ,
  8. "State": ""
  9. },
  10. "p6": {
  11. "ID": "p6",
  12. "Hp": ,
  13. "Atk": ,
  14. "Def": 2.3,
  15. "State": ""
  16. },
  17. "0.3": {
  18. "ID": 0.3,
  19. "Hp": ,
  20. "Atk": ,
  21. "Def": ,
  22. "State": ""
  23. }
  24. }
  25. }

  1. {
  2. "4l523": {
  3. "ID": "4l523",
  4. "Hp": ,
  5. "Atk": 6.3,
  6. "Def": ,
  7. "State": ""
  8. },
  9. "p6": {
  10. "ID": "p6",
  11. "Hp": ,
  12. "Atk": ,
  13. "Def": 2.3,
  14. "State": ""
  15. },
  16. "0.3": {
  17. "ID": 0.3,
  18. "Hp": ,
  19. "Atk": ,
  20. "Def": ,
  21. "State": ""
  22. }
  23. }

只要带有签名或者存在多个表单文件在同一个Json中,就只能重新建立新类并解析该新类了,新类中的变量顺序和标识符都必须与Json文件中的顺序与签名保持一致:

  1. public class Buffs
  2. {
  3. //变量名称Buff必须与Json中的签名Buff一样
  4. public Dictionary<string, Buff> Buff = new Dictionary<string, Buff>();
  5. }

叫人失落的是,Newtonsoft.Json并不会良心的帮你把错误的数据自动转换,而是直接给你抛出一个错误,这一点和JsonUtility不同。

补充:

一个有趣的实验——强行用Unity中的字典序列化方式来序列化Json文件会是怎样?

开始之前,我们要明白的是,Unity默认根本就没有给出任何字典序列化的方式,它只能蠢蠢的序列化List或者Array,但这并不能阻止我们,我们可以讨巧的利用ISerializationCallbackReceiver接口来实现一个伪序列化:

  1. using UnityEngine;
  2. using System;
  3. using System.Collections.Generic;
  4.  
  5. // Dictionary<TKey, TValue>
  6. [Serializable]
  7. public class Serialization<TKey, TValue> : ISerializationCallbackReceiver
  8. {
  9. [SerializeField]
  10. List<TKey> keys;
  11. [SerializeField]
  12. List<TValue> values;
  13.  
  14. Dictionary<TKey, TValue> target;
  15. public Dictionary<TKey, TValue> ToDictionary() { return target; }
  16.  
  17. public Serialization(Dictionary<TKey, TValue> target)
  18. {
  19. this.target = target;
  20. }
  21.  
  22. public void OnBeforeSerialize()
  23. {
  24. keys = new List<TKey>(target.Keys);
  25. values = new List<TValue>(target.Values);
  26. }
  27.  
  28. public void OnAfterDeserialize()
  29. {
  30. var count = Math.Min(keys.Count, values.Count);
  31. target = new Dictionary<TKey, TValue>(count);
  32. for (var i = ; i < count; ++i)
  33. {
  34. target.Add(keys[i], values[i]);
  35. }
  36. }
  37. }

把之前反序列化出的数据再用该伪序列化方式来序列化为Json文件:

  1. var SerializedBuff= new Serialization<string, Buff>(new Dictionary<string, Buff>());
  2. var data = JsonConvert.DeserializeObject<Buffs>(json.text);
  3. foreach(var item in data.Buff)
  4. {
  5. SerializedBuff.ToDictionary().Add(item.Key, item.Value);
  6. }
  7. var jsont = JsonUtility.ToJson(SerializedBuff);
  8. Debug.Log(jsont);

实验结果如下:

  1. {
  2. "keys":[
  3. "4l523",
  4. "p6",
  5. "0.3"],
  6. "values":[
  7. {
  8. "ID":"4l523",
  9. "Hp":,
  10. "Atk":6.300000190734863,
  11. "Def":7.0,
  12. "State":{
  13. }
  14. },
  15. {
  16. "ID":"p6",
  17. "Hp":,
  18. "Atk":8.0,
  19. "Def":2.299999952316284,
  20. "State":{
  21. }
  22. },
  23. {
  24. "ID":"0.3",
  25. "Hp":,
  26. "Atk":7.0,
  27. "Def":9.0,
  28. "State":{
  29. }
  30. }]
  31. }

我们发现它根本不是一个字典类型,序列化之后的结构和原来的结构相差非常大,实际上是Keys在一起Values在一起,只是它们的索引是相互对应的。

Unity 基于excel2json批处理读取Excel表并反序列化的更多相关文章

  1. Python+Selenium进行UI自动化测试项目中,常用的小技巧1:读取excel表,转化成字典(dict)输出

    从今天开始我将会把在项目中遇到的问题,以及常用的一些技巧来分享出来,以此来促进自己的学习和提升自己:更加方便我以后的查阅. 现在要说的是:用Python来读取excel表的数据,返回字典(dict), ...

  2. Aspose.cells 读取Excel表中的图片问题

    一.说明 本文主要是讲解,怎么使用aspose.cells读取Excel表中的图片,并把图片转换成流或是image对象. 二.开发环境说明 开发工具vs2012,c#语言, 三.Aspose.cell ...

  3. Jmeter读取excel表中用例数据实现接口压测

    传统的接口测试,都是在接口中手动输入不同用例准备的多种场景参数数据,一遍一遍的输入来执行多个不同的用例,但是现在利用excel表格准备各种类型的数据,使用Jmeter中Jmeter CSV Data ...

  4. Python xlrd模块读取Excel表中的数据

    1.xlrd库的安装 直接使用pip工具进行安装(当然也可以使用pycharmIDE进行安装,这里就不详述了) pip install xlrd 2.xlrd模块的一些常用命令 ①打开excel文件并 ...

  5. C#读取Excel表中的数据时,为何有些行的字段内容读取不到

    转载:http://bbs.csdn.net/topics/360220285 1.当某列数据中含有混合类型时,在.NET中使用Microsoft.Jet.OLEDB.4.0来读取Excel文件造成数 ...

  6. Java读取excel表,getPhysicalNumberOfCells()和getLastCellNum区别

    excel表存入数据库,发现有时报数组下标越界异常.调试发现用了 getPhysicalNumberOfCells(),这个是用来获取不为空的的列个数. getLastCellNum是获取最后一个不为 ...

  7. python读取excel表

    from xlrd import open_workbookimport re #创建一个用于读取sheet的生成器,依次生成每行数据,row_count 用于指定读取多少行, col_count 指 ...

  8. 基于注解的读取excel的工具包

    easyexcel-wraper easyexcel-wraper是什么? 一个方便读取excel内容,且可以使用注解进行内容验证的包装工具 easyexcel-wraper有哪些功能? 在easye ...

  9. unity 读取excel表 生成asset资源文件

    做unity 项目也有一段时间了,从unity项目开发和学习中也遇到了很多坑,并且也从中学习到了很多曾经未接触的领域.项目中的很多功能模块,从今天开始把自己的思路和代码奉上给学渣们作为一份学习的资料. ...

随机推荐

  1. jQurey zTree Demo 3.5

    https://jeesite.gitee.io/front/jquery-ztree/3.5/demo/cn/index.html

  2. BZOJ 4055 Misc

    原题传送门 比较复杂的一道DP. 设两点(i,j)之间最短路为dis[i][j],则 可转化为: 将该式前后分立,可得: 其中,可以单独求出,后面的部分则需要DP. 设为b(x),枚举i,并计算出从i ...

  3. 关于SQL SERVER 的日期格式化

    --日期格式化Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AM Select CONVERT(varchar(100), G ...

  4. C#6.0到C#8.0的新特性

    C#6.0新特性 C#7.0新特性 C#8.0新特性

  5. Redundant Paths 分离的路径【边双连通分量】

    Redundant Paths 分离的路径 题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields ...

  6. 转载--未看关于移动端Web远程开发调试

    移动端Web开发调试之Chrome远程调试(Remote Debugging) http://blog.csdn.net/freshlover/article/details/42528643 移动端 ...

  7. sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class

    1.首先,问题出现的点是在泛型 我出现问题的原因是,和泛型有关系,要调整泛型 2.我把问题出现的过程描述一哈子 1.基础类 @tk.mybatis.mapper.annotation.Register ...

  8. Vue 项目推荐,Github 过万 Star

    电鸭社区-远程工作-自由职业-兼职外包-自由从这开始 嗨,我是 Martin,也叫老王.不少小伙伴,说自己是转行.自学,没有项目,今天推荐一个 Vue 实战项目 还记得 Martin 仿写过在线 Ma ...

  9. zsh切换bash提示chsh: no changes made问题

    前提纪要:1.我们都知道mac有默认bash工具,在下载zsh后,把一切都配置好后,输入切换命令:chsh - s /bin/zsh ,总是提示 chsh: no changes made错误.那我我 ...

  10. 二叉树的镜像(剑指offer-18)

    题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 解析 先前序遍历这棵树的每个结点,如果遍历到的结点有子结点,就交换它的两个子节点, 当交换完所有的非叶子结点的左右子结点之后,就得到了树的镜像 ...