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

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

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

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

Single.bat详情如下:

 @SET OUTPUT_FOLDER=.\output
@SET EXE=.\tool\excel2json.exe if not exist %OUTPUT_FOLDER% md %OUTPUT_FOLDER% @echo off
set path=%
echo 源文件路径%path%
set name=%~n1
echo 源文件名%name%
set outputpath=%OUTPUT_FOLDER%\%name%
echo 输出文件路径%outputpath% @CALL %EXE% --excel %path% --json %outputpath%.json --header --csharp %outputpath%.cs -a pause

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

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

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

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

类似的还有:

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

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

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

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

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

AutoAll.bat详情如下:

 @SET EXCEL_FOLDER=.\
@SET OUTPUT_FOLDER=.\output
@SET EXE=.\tool\excel2json.exe @ECHO Converting excel files in folder %EXCEL_FOLDER% ...
if not exist %OUTPUT_FOLDER% md %OUTPUT_FOLDER% for /f "delims=" %%i in ('dir /b /a-d /s %EXCEL_FOLDER%\*.xlsx') do (
@echo processing %%~nxi
@CALL %EXE% --excel %EXCEL_FOLDER%\%%~nxi --json %OUTPUT_FOLDER%\%%~ni.json --header --csharp %OUTPUT_FOLDER%\%%~ni.cs -a
)
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导出)

  [
{
"ID": "4l523",
"Hp": ,
"Atk": 6.3,
"Def": ,
"State": ""
},
{
"ID": "p6",
"Hp": ,
"Atk": ,
"Def": 2.3,
"State": ""
},
{
"ID": 0.3,
"Hp": 0.2,
"Atk": "2.3,7",
"Def": ,
"State": ""
}
]
 [System.Serializable]
public class Buff
{
public string ID; // 编号
public int Hp; // 血量
public float Atk; // 攻击
public float Def; // 防御
public BuffData State; // 状态
}

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

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

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

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

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

 using UnityEngine;

 public class JsonHelper
{
public static T[] GetJsonArray<T>(string json)
{
string newJson = "{ \"array\": " + json + "}";
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(newJson);
return wrapper.array;
} [System.Serializable]
private class Wrapper<T>
{
public T[] array;
}
}

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

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

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

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

 public class JsonDatas<T>
{
public Dictionary<string, T> Dict = new Dictionary<string, T>();
public static JsonDatas<T> FromJson(string json)
{
var re = new JsonDatas<T>();
var datas = JsonHelper.GetJsonArray<T>(json);
foreach(var data in datas)
{
var info = data.GetType().GetField("ID");
var idstr = info.GetValue(data).ToString();
re.Dict.Add(idstr, data);
}
return re;
} public T Get(string ID)
{
return Dict[ID];
}
}

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

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:

 {
"Buff": {
"4l523": {
"ID": "4l523",
"Hp": ,
"Atk": 6.3,
"Def": ,
"State": ""
},
"p6": {
"ID": "p6",
"Hp": ,
"Atk": ,
"Def": 2.3,
"State": ""
},
"0.3": {
"ID": 0.3,
"Hp": ,
"Atk": ,
"Def": ,
"State": ""
}
}
}

 {
"4l523": {
"ID": "4l523",
"Hp": ,
"Atk": 6.3,
"Def": ,
"State": ""
},
"p6": {
"ID": "p6",
"Hp": ,
"Atk": ,
"Def": 2.3,
"State": ""
},
"0.3": {
"ID": 0.3,
"Hp": ,
"Atk": ,
"Def": ,
"State": ""
}
}

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

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

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

补充:

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

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

 using UnityEngine;
using System;
using System.Collections.Generic; // Dictionary<TKey, TValue>
[Serializable]
public class Serialization<TKey, TValue> : ISerializationCallbackReceiver
{
[SerializeField]
List<TKey> keys;
[SerializeField]
List<TValue> values; Dictionary<TKey, TValue> target;
public Dictionary<TKey, TValue> ToDictionary() { return target; } public Serialization(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 = ; i < count; ++i)
{
target.Add(keys[i], values[i]);
}
}
}

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

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

实验结果如下:

 {
"keys":[
"4l523",
"p6",
"0.3"],
"values":[
{
"ID":"4l523",
"Hp":,
"Atk":6.300000190734863,
"Def":7.0,
"State":{
}
},
{
"ID":"p6",
"Hp":,
"Atk":8.0,
"Def":2.299999952316284,
"State":{
}
},
{
"ID":"0.3",
"Hp":,
"Atk":7.0,
"Def":9.0,
"State":{
}
}]
}

我们发现它根本不是一个字典类型,序列化之后的结构和原来的结构相差非常大,实际上是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. 入门大数据---SparkSQL联结操作

    一. 数据准备 本文主要介绍 Spark SQL 的多表连接,需要预先准备测试数据.分别创建员工和部门的 Datafame,并注册为临时视图,代码如下: val spark = SparkSessio ...

  2. 入门大数据---Flink学习总括

    第一节 初识 Flink 在数据激增的时代,催生出了一批计算框架.最早期比较流行的有MapReduce,然后有Spark,直到现在越来越多的公司采用Flink处理.Flink相对前两个框架真正做到了高 ...

  3. Unicode 环境下的字符串的操作

    1.CString转int int i _ttoi( str ); 2.保存中文和读取中文: CSdtioFile在Unicode环境下默认是不支持中文的,若需要存储和读取中文需要设置代码页: #in ...

  4. Linux服务器定时脚本

    crontab -e 进入编辑模式,同vi编辑器操作. 用户所建立的crontab文件中,每一行都代表一项任务,每行的每个字段代表一项设置,它的格式共分为六个字段,前五段是时间设定段,第六段是要执行的 ...

  5. SpringBoot01-启动类启动做了那些事情

    1.第一个步骤进入SpringApplication构造函数 public SpringApplication(ResourceLoader resourceLoader, Class<?> ...

  6. USACO07 MAR Face The Right Way G

    疫情当下,美帝又开始倒牛奶了,这一幕似曾相识啊~~~ 这个题目非常的应景,又是美国佬的奶牛 [题目地址] [一句话题意] N头牛排成一列1<=N<=5000.每头牛或者向前或者向后. 为了 ...

  7. 洛谷 P2882 [USACO07MAR]Face The Right Way G

    题目传送门 题目描述 Farmer John has arranged his N (1 ≤ N ≤ 5,000) cows in a row and many of them are facing ...

  8. Python 最强 IDE 详细使用指南!

    PyCharm 是一种 Python IDE,可以帮助程序员节约时间,提高生产效率.那么具体如何使用呢?本文从 PyCharm 安装到插件.外部工具.专业版功能等进行了一一介绍,希望能够帮助到大家.作 ...

  9. Tomcat 架构原理解析到架构设计借鉴

    Tomcat 发展这么多年,已经比较成熟稳定.在如今『追新求快』的时代,Tomcat 作为 Java Web 开发必备的工具似乎变成了『熟悉的陌生人』,难道说如今就没有必要深入学习它了么?学习它我们又 ...

  10. web网页动态分享facebook和twitter

    介绍 facebook分享 http://www.facebook.com/sharer.php?t=${text}u=encodeURIComponent('静态html') twitter分享 h ...