Unity(C#)将json数据存储到Excel(.csv)文件中

本文介绍了一个将JSON数据转换为CSV文件的方法,适用于游戏策划查看游戏中战斗数值的需求。使用Unity和C#实现,涉及Newtonsoft.Json.dll进行反序列化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网上找了很多将json数据存储到Excel(.csv)文件的实现方案,发现要么语言不适用,要么需要的库文件难找或者导入Unity项目又冲突,再或者就是直接在线转换工具还需要钱等等坑,于是下定决心自己搞一个出来,当真是不容易啊。

背景:策划想要直观的查看游戏中的战斗数值,将战斗数据输出到Excel表中;
工具:Unity,C#,Newtonsoft.Json.dll(反序列化json数据要用的库文件);

动态链接库bd网盘下载地址:https://pan.baidu.com/s/1Mz_Kvv21S1zNojkDIn4NLA
密码:yi7s

核心demo代码:

using System.Collections.Generic;
using System.Data;
using System.IO;
using UnityEngine;
using Newtonsoft.Json;
using System.Reflection;
using System;

[Serializable]
public class Job
{
    public string jobName;
    public int salary;
}

[Serializable]
public class Person
{
    //直接使用字段
    public string name; //属性写法加上:{ get; set; }
    public string native; //属性写法加上:{ get; set; }
    public int age; //属性写法加上:{ get; set; }
    public Job job;
}

public class JsonToExcel
{
    //json  转 DataTable  类型   然后导出  excel
    //参数1 string json json数据 参数2 tabName导出成Excel后的名称(不需要带.csv后缀,后面加上了)
    public static void JsonToCsv(string json, string path)
    {
        //json数据转成  DataTable   类型
        DataTable dataTab = JsonToDataTable<Person>(json);
        //DataTable数据存储到 .csv 表
        DataTableToCsv(dataTab, path);//不会跳转单元格,每一行的数据在一个单元里面
    }

    //json  转 DataTable
    private static DataTable JsonToDataTable<T>(string json)
    {
        DataTable dataTable = new DataTable(); //实例化
        DataTable result;
        try
        {
            List<T> arrayList = JsonConvert.DeserializeObject<List<T>>(json);
            if (arrayList.Count <= 0)
            {
                result = dataTable;
                return result;
            }

            foreach (T item in arrayList)
            {
                Dictionary<string, object> dictionary = GetFields<T>(item);//如果Test类中的都是属性就使用GetProperties方法获取dictionary
                //Columns
                if (dataTable.Columns.Count == 0)
                {
                    foreach (string current in dictionary.Keys)
                    {
                        Debug.Log("增加一列:" + current + ",类型:" + dictionary[current].GetType());
                        dataTable.Columns.Add(current, dictionary[current].GetType());
                    }
                }
                //Rows
                DataRow dataRow = dataTable.NewRow();
                foreach (string current in dictionary.Keys)
                {
                    Debug.Log("增加一行:" + current + " =" + dictionary[current]);
                    dataRow[current] = dictionary[current];
                }
                dataTable.Rows.Add(dataRow); //循环添加行到DataTable中
            }
        }
        catch
        {

        }
        result = dataTable;
        return result;
    }

    //导出Excel
    private static void DataTableToCsv(DataTable table, string file)
    {
        file = file + ".csv";
        if (File.Exists(file))
        {
            File.Delete(file);
        }
        if (table.Columns.Count <= 0)
        {
            Debug.LogError("table.Columns.Count <= 0");
            return;
        }

        string title = "";
        FileStream fs = new FileStream(file, FileMode.OpenOrCreate);
        //StreamWriter sw = new StreamWriter(new BufferedStream(fs), System.Text.Encoding.Default);//这个中文会乱码
        StreamWriter sw = new StreamWriter(new BufferedStream(fs), System.Text.Encoding.UTF8);
        for (int i = 0; i < table.Columns.Count; i++)
        {
            //title += table.Columns[i].ColumnName + "\t"; //栏位:自动跳到下一单元格,然而我这里运行后并没有
            title += table.Columns[i].ColumnName + ","; //栏位:自动跳到下一单元格,老铁没毛病
        }

        title = title.Substring(0, title.Length - 1) + "\n";
        sw.Write(title);
        foreach (DataRow row in table.Rows)
        {
            string line = "";
            for (int i = 0; i < table.Columns.Count; i++)
            {
                //line += row[i].ToString().Trim() + "\t"; //内容:自动跳到下一单元格,然而我这里运行后并没有
                line += row[i].ToString().Trim() + ","; //内容:自动跳到下一单元格,老铁没毛病
            }
            line = line.Substring(0, line.Length - 1) + "\n";
            sw.Write(line);
        }
        sw.Close();
        fs.Close();
    }

    /// <summary>
    ///  使用反射机制获取类中的字段-值列表:只获取一层的,不获取子对象的字段
    /// </summary>
    /// <returns>所有字段名称</returns>
    public static Dictionary<string, object> GetFields<T>(T t)
    {
        Dictionary<string, object> keyValues = new Dictionary<string, object>();
        if (t == null)
        {
            return keyValues;
        }
        System.Reflection.FieldInfo[] fields = t.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
        if (fields.Length <= 0)
        {
            return keyValues;
        }
        foreach (System.Reflection.FieldInfo item in fields)
        {
            string name = item.Name; //名称
            object value = item.GetValue(t);  //值

            if (item.FieldType.IsValueType || item.FieldType.Name.StartsWith("String"))
            {
                keyValues.Add(name, value);
            }
            else
            {
                Debug.Log("值类型:" + value.GetType().Name);
                //递归将子类中的字段加入进来
                Dictionary<string, object> subKeyValues = GetFields<object>(value);
                foreach (KeyValuePair<string, object> temp in subKeyValues)
                {
                    keyValues.Add(temp.Key, temp.Value);
                }
            }
        }
        return keyValues;
    }

    /// <summary>
    /// 使用反射机制获取类中的属性-值列表:只获取一层的,不获取子对象的属性
    /// </summary>
    /// <returns>所有属性名称</returns>
    public static Dictionary<string, object> GetProperties<T>(T t)
    {
        Dictionary<string, object> keyValues = new Dictionary<string, object>();
        if (t == null)
        {
            return keyValues;
        }
        System.Reflection.PropertyInfo[] properties = t.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
        if (properties.Length <= 0)
        {
            return keyValues;
        }
        foreach (System.Reflection.PropertyInfo item in properties)
        {
            string name = item.Name; //名称
            object value = item.GetValue(t, null);  //值

            if (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String"))
            {
                keyValues.Add(name, value);
            }
            else
            {
                Debug.Log("值类型:" + value.GetType().Name);
                //递归将子类中的字段加入进来
                Dictionary<string, object> subKeyValues = GetProperties<object>(value);
                foreach (KeyValuePair<string, object> temp in subKeyValues)
                {
                    keyValues.Add(temp.Key, temp.Value);
                }
            }
        }
        return keyValues;
    }
}

测试代码:

        //JsonToExcel.jsonToDataTable("{'name':'老张', 'native':'湖北', 'age':46}", Application.dataPath + "/aaa");//不行,必须得是数组形式(最外围是[]包围的)
        //JsonToExcel.jsonToDataTable("[{'name':'老杨', 'native':'湖南', 'age':36},{'name':'老张', 'native':'湖北', 'age':46}]", Application.dataPath + "/aaa");//可以
        //JsonToExcel.jsonToDataTable("[{'name':'老杨', 'native':'湖南', 'age':36, {'jobName':'搬砖程序', 'salary':100}},{'name':'老张', 'native':'湖北', 'age':46, {'jobName':'农名程序', 'salary':50}}]", Application.dataPath + "/aaa");//不行,json格式错误,子对象也要有名字,对比下面少了job
        JsonToExcel.JsonToCsv("[{'name':'老杨', 'native':'湖南', 'age':36, 'job':{'jobName':'搬砖程序', 'salary':100}},{'name':'老张', 'native':'湖北', 'age':46, 'job':{'jobName':'农名程序', 'salary':50}}]", Application.dataPath + "/aaa");//可以(这里有子对象的数据,打包到excel表中后会将子类中所有字段或者属性都作为标头)

生成了我想要的.csv文件,没有乱码、能正常换行跳转单元存储:
在这里插入图片描述
后面正式的操作,只需要将要存储的数据形式,封装成一个类替换咱的Person类就好啦!
完成!!!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值