【C#】实现Json转Lua (Json2Lua)

关键词: C#、JsonToLua、Json2Lua、对象序列化Lua

前提需引入NewtonsofJson,引入方法可先在Visual Studio 2019

将Newtonsoft.Json.dll文件导入Unity的Plugins下。

Json格式字符串转Lua格式字符串,效果如下:

json字符串

cs 复制代码
{
	"1": "asd",
	"2": true,
	"3": 1.5,
	"4": 123,
	"a": {
		"b": "c",
		"d": [1, 2, 3]
	}
}

lua字符串 (.lua文件一般直接return {}表 故会加上 "return " 如果不需要可以自行修改代码。)

cs 复制代码
return {
	[1] = "asd",
	[2] = true,
	[3] = 1.5,
	[4] = 123,
	a = {
		b = "c",
		d = { 1, 2, 3 }
	}
}

使用方法:

cs 复制代码
string json = "{\"1\":\"asd\",\"2\":true,\"3\":1.5,\"4\":123,\"a\":{\"b\":\"c\",\"d\":[1,2,3]}}";
string lua = Milk.Json.MilkJsonUtility.Json2Lua(json, true);

类说明:

LuaObject:封装Json基础类型对象,核心GetString方法返回对象的字符串形式。

LuaTable:封装JsonArray或JsonObject类型对象,主要是将数组或对象内的成员封装为LuaObject存储起来,数组存储于list,对象成员存储于map,核心GetString方法返回表的字符串形式。

LuaTable类静态方法:public static LuaTable CreateFromJson(string json)

由该方法进行转化json为lua,使用JObject.Parse(json)转为Json对象,后经过判断是数组还是对象类型进行使用不同函数转化(JsonArray2LuaTable、JsonObject2LuaTable)

JsonArray2LuaTable:将Json数组成员一一转化为LuaTable

JsonObject2LuaTable:将Json对象成员一一转化为LuaTable

cs 复制代码
namespace Milk.Json
{
    public static class MilkJsonUtility
    {
        /// <summary>
        /// 将Json格式字符串转成Lua表形式字符串
        /// </summary>
        /// <param name="json"></param>
        /// <param name="indented">是否缩进</param>
        /// <returns></returns>
        public static string Json2Lua(string json, bool indented = false)
        {
            var table = LuaTable.CreateFromJson(json);
            return $"return {table.GetString(indented)}";
        }
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Text;

namespace Milk.Json
{
    public enum LuaValueType
    {
        Table,
        String,
        Num,
        Boolean,
        nil
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json.Linq;

namespace Milk.Json
{
    public class LuaTable
    {
        //存放table中的有序部分
        private List<LuaObject> list = new List<LuaObject>();

        //存放table中的无序部分
        private Dictionary<string, LuaObject> map = new Dictionary<string, LuaObject>();

        //所在层级
        private int layer = 0;

        public LuaTable(int _layer)
        {
            layer = _layer + 1;
        }

        #region 有序数组添加

        /// <summary>
        /// [有序]添加string value
        /// </summary>
        /// <param name="value"></param>
        public void AddItem(string value)
        {
            list.Add(new LuaObject(value));
        }

        /// <summary>
        /// [有序]num value
        /// </summary>
        /// <param name="value"></param>
        public void AddItem(int value)
        {
            list.Add(new LuaObject(value));
        }

        /// <summary>
        /// [有序]num value
        /// </summary>
        /// <param name="value"></param>
        public void AddItem(float value)
        {
            list.Add(new LuaObject(value));
        }

        /// <summary>
        /// [有序]bool value
        /// </summary>
        /// <param name="value"></param>
        public void AddItem(bool value)
        {
            list.Add(new LuaObject(value));
        }

        public void AddItem(LuaTable value)
        {
            list.Add(new LuaObject(value));
        }

        /// <summary>
        /// 加入nil
        /// </summary>
        public void AddItemNil()
        {
            list.Add(new LuaObject());
        }

        #endregion


        #region Key_Value添加

        public void AddItem(string key, string value)
        {
            //查重
            if (!map.ContainsKey(key))
            {
                map.Add(key, new LuaObject(value));
            }
        }

        public void AddItem(string key, int value)
        {
            //查重
            if (!map.ContainsKey(key))
            {
                map.Add(key, new LuaObject(value));
            }
        }

        public void AddItem(string key, float value)
        {
            //查重
            if (!map.ContainsKey(key))
            {
                map.Add(key, new LuaObject(value));
            }
        }

        public void AddItem(string key, bool value)
        {
            //查重
            if (!map.ContainsKey(key))
            {
                map.Add(key, new LuaObject(value));
            }
        }

        public void AddItem(string key, LuaTable value)
        {
            //查重
            if (!map.ContainsKey(key))
            {
                map.Add(key, new LuaObject(value));
            }
        }

        public void AddItemNil(string key)
        {
            //查重
            if (!map.ContainsKey(key))
            {
                map.Add(key, new LuaObject());
            }
        }

        #endregion

        private bool IsNumeric(string str)
        {
            int number;
            return int.TryParse(str, out number);
        }

        private string IndentedLayer(string str, bool indented, int change = 0)
        {
            if (indented)
            {
                for (int i = 0; i < layer + change; i++)
                {
                    str = "\t" + str;
                }
            }
            return str;
        }

        public string GetString(bool indented = false)
        {
            string str = "{";
            bool hasList = list.Count > 0;
            bool hasMap = map.Count > 0;
            bool isNeedIndented = false;
            if (indented && (hasList || hasMap))
            {
                isNeedIndented = true;
                if (hasList)
                {
                    LuaValueType type = list[0].GetLuaValueType();
                    if (type == LuaValueType.Boolean || type == LuaValueType.Num)
                    {
                        isNeedIndented = false;
                    }
                }
                if (isNeedIndented)
                    str += "\n";
            }
            if (hasList)
            {
                int count = 0;
                foreach (var item in list)
                {
                    count++;
                    if (!isNeedIndented)
                    {
                        if (indented && count == 1)
                            str += " ";
                        str += item.GetString(indented);
                        if (count < list.Count)
                            str += ",";
                        if (indented)
                            str += " ";
                    }
                    else
                    {
                        str += IndentedLayer(item.GetString(indented), indented);
                        if (count < list.Count)
                            str += ",";
                        if (indented)
                            str += "\n";
                    }
                }
            }

            if (hasMap)
            {
                int count = 0;
                foreach (var item in map)
                {
                    count++;
                    var key = item.Key.Replace('$', '_');
                    if (IsNumeric(key))
                    {
                        key = $"[{key}]";
                    }
                    if (indented)
                        str += IndentedLayer($"{key} = {item.Value.GetString(indented)}", indented);
                    else
                        str += IndentedLayer($"{key}={item.Value.GetString(indented)}", indented);
                    if (count < map.Count)
                        str += ",";
                    if (indented)
                        str += "\n";
                }
            }

            if (!isNeedIndented)
            {
                str += "}";
            }
            else
            {
                str += IndentedLayer("}", indented, -1);
            }

            return str;
        }

        public static LuaTable CreateFromJson(string json)
        {
            var jsonObject = JObject.Parse(json);
            if (jsonObject.Type == JTokenType.Array)
            {
                return JsonArray2LuaTable(jsonObject.ToObject<JArray>(), 0);
            }
            else
            {
                return JsonObject2LuaTable(jsonObject, 0);
            }
        }

        /// <summary>
        /// 递归方法
        /// </summary>
        static LuaTable JsonObject2LuaTable(JObject jsonObj, int layer)
        {
            var curLuaTable = new LuaTable(layer);

            //构建无序Table(lua表 key-value形式)
            foreach (var item in jsonObj)
            {
                switch (item.Value.Type)
                {
                    case JTokenType.Boolean:
                        curLuaTable.AddItem(item.Key, (bool)item.Value);
                        break;
                    case JTokenType.Array:
                        curLuaTable.AddItem(item.Key, JsonArray2LuaTable(item.Value.ToObject<JArray>(), layer + 1));
                        break;
                    case JTokenType.String:
                        curLuaTable.AddItem(item.Key, (string)item.Value);
                        break;
                    case JTokenType.Date: //转成string
                        curLuaTable.AddItem(item.Key, (string)item.Value);
                        break;
                    case JTokenType.Float:
                        curLuaTable.AddItem(item.Key, (float)item.Value);
                        break;
                    case JTokenType.Integer:
                        curLuaTable.AddItem(item.Key, (int)item.Value);
                        break;
                    case JTokenType.None:
                        curLuaTable.AddItemNil(item.Key);
                        break;
                    case JTokenType.Null:
                        curLuaTable.AddItemNil(item.Key);
                        break;
                    case JTokenType.Object:
                        curLuaTable.AddItem(item.Key, JsonObject2LuaTable(item.Value.ToObject<JObject>(), layer + 1));
                        break;
                    case JTokenType.TimeSpan:
                        curLuaTable.AddItem(item.Key, (float)item.Value);
                        break;
                }
            }

            return curLuaTable;
        }

        static LuaTable JsonArray2LuaTable(JArray jsonArray, int layer)
        {
            var curLuaTable = new LuaTable(layer);
            //构建有序Table(lua表)
            foreach (var item in jsonArray)
            {
                //检查子项类型
                switch (item.Type)
                {
                    case JTokenType.Boolean:
                        curLuaTable.AddItem((bool)item);
                        break;
                    case JTokenType.Array:
                        curLuaTable.AddItem(JsonArray2LuaTable(item.ToObject<JArray>(), layer + 1));
                        break;
                    case JTokenType.String:
                        curLuaTable.AddItem((string)item);
                        break;
                    case JTokenType.Object:
                        curLuaTable.AddItem(JsonObject2LuaTable(item.ToObject<JObject>(), layer + 1));
                        break;
                    case JTokenType.Date:
                        curLuaTable.AddItem((string)item);
                        break;
                    case JTokenType.Float:
                        curLuaTable.AddItem((float)item);
                        break;
                    case JTokenType.Integer:
                        curLuaTable.AddItem((int)item);
                        break;
                    case JTokenType.None:
                        curLuaTable.AddItemNil();
                        break;
                    case JTokenType.Null:
                        curLuaTable.AddItemNil();
                        break;
                    case JTokenType.TimeSpan:
                        curLuaTable.AddItem((float)item);
                        break;
                }
            }

            return curLuaTable;
        }
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Text;

namespace Milk.Json
{
    public class LuaObject
    {
        private LuaValueType type;

        private float valueNumber;
        private string valueString;
        private bool valueBoolean;
        private LuaTable valueTable;

        public LuaObject(string value)
        {
            type = LuaValueType.String;
            valueString = value;
        }

        public LuaObject(float value)
        {
            type = LuaValueType.Num;
            valueNumber = value;
        }

        public LuaObject(int value)
        {
            type = LuaValueType.Num;
            valueNumber = value;
        }

        public LuaObject(bool value)
        {
            type = LuaValueType.Boolean;
            valueBoolean = value;
        }

        public LuaObject(LuaTable value)
        {
            type = LuaValueType.Table;
            valueTable = value;
        }

        public LuaObject()
        {
            type = LuaValueType.nil;
        }

        public string GetString(bool indented = false)
        {
            switch (type)
            {
                case LuaValueType.Table:
                    return valueTable.GetString(indented);
                //break;
                case LuaValueType.Boolean:
                    if (valueBoolean)
                    {
                        return "true";
                    }
                    else
                    {
                        return "false";
                    }
                //break;
                case LuaValueType.Num:
                    return valueNumber.ToString();
                //break;
                case LuaValueType.String:
                    return "\""+ valueString+"\"";
                case LuaValueType.nil:
                    return "nil";
                default:
                    return "";
            }
        }

        public LuaValueType GetLuaValueType()
        {
            return type;
        }
    }
}
相关推荐
吳所畏惧43 分钟前
C#轻松实现Winform监控文件夹变化以及监控文件新增、修改、删除、重命名等操作保姆级详细教程
开发语言·windows·c#·.net·.netcore
CS软件开发框架1 小时前
C/S软件授权注册系统-轻量级WebApi服务器介绍
运维·服务器·visualstudio·c#·.net·.netcore
Marzlam1 小时前
lambda 表达式 闭包写法
c#
yngsqq2 小时前
CAD表格转excel
c#·excel
极地星光3 小时前
使用 Wireshark 和 Lua 脚本解析通讯报文
wireshark·lua
小码编匠4 小时前
解决 WPF 多线程难题:技巧与案例分析
后端·c#·.net
sukalot6 小时前
windows C#-命名实参和可选实参(上)
开发语言·c#
小小怪下士yeah6 小时前
探秘 JSON:数据交互的轻盈使者
okhttp·json·交互