Unity解析Construct 2嵌套JSON数组时List<List<List<string>>>加载异常求助
解决Construct 2生成的嵌套JSON解析问题
首先我得点明你遇到的核心问题:你加载的JSON是嵌套的双层结构,外层data字段里包裹的并不是直接的数组数据,而是一个转义后的完整JSON字符串。Unity自带的JsonUtility只会解析第一层JSON结构,所以外层的c2array和size能正常加载,但data里的内容只是一串文本,没法自动解析成你定义的嵌套列表。
问题拆解
看你提供的示例JSON,外层data的最内层其实是这样的字符串(已去除转义):
{"c2array":true,"size":[22,9,1],"data":[[["wall"],[0],[0],[10],[480],[0],[0],[0],[0]],...]}
这个字符串本身又是一个完整的Construct 2数组JSON,所以你得先解析外层结构取出这个字符串,再单独解析它才能拿到真正的地图数据。
另外你定义的List<List<List<string>>> data也有小隐患:内层数据里既有字符串(比如"wall")也有数字(比如0),虽然JsonUtility能把数字转成字符串,但后续使用数据时需要手动转类型,不如直接定义贴合数据结构的类更方便。
解决方案
步骤1:先解析外层,取出内层JSON字符串
先保留你原来的C2Map类,先解析外层JSON拿到内层的JSON文本:
void Start () { string jsonPath = Application.dataPath + "/Maps/MapFiles/Test/document.json"; // 先验证路径是否正确(可选) if (!File.Exists(jsonPath)) { Debug.LogError("找不到JSON文件:" + jsonPath); return; } jsonString = File.ReadAllText(jsonPath); // 解析外层结构 C2Map outerMap = JsonUtility.FromJson<C2Map>(jsonString); // 取出内层的JSON字符串(外层data的结构是[0][0][0],对应唯一的地图数据) string innerJson = outerMap.data[0][0][0]; // 解析内层的真实地图数据 C2Map innerMap = JsonUtility.FromJson<C2Map>(innerJson); // 测试输出内层地图尺寸 Debug.Log($"内层地图元素数量:{innerMap.size[0]},每个元素属性数:{innerMap.size[1]}"); }
步骤2:优化数据结构(推荐)
为了避免反复处理嵌套列表,你可以创建一个专门的类来映射每个地图元素的属性:
[System.Serializable] public class MapElement { public string type; // 元素类型:wall、plateform、spike等 public int x; // 元素X坐标 public int y; // 元素Y坐标 public int width; // 元素宽度 public int height; // 元素高度 public int rotation; // 旋转角度 public int loop; // 循环参数 public int speed; // 移动速度 public int direction; // 运动方向 } // 把内层的嵌套列表转换成MapElement列表 List<MapElement> ConvertToMapElements(C2Map innerMap) { List<MapElement> elements = new List<MapElement>(); foreach (var elementData in innerMap.data) { MapElement elem = new MapElement(); // 按顺序取出每个单元素数组的值 elem.type = elementData[0][0]; elem.x = int.Parse(elementData[1][0]); elem.y = int.Parse(elementData[2][0]); elem.width = int.Parse(elementData[3][0]); elem.height = int.Parse(elementData[4][0]); elem.rotation = int.Parse(elementData[5][0]); elem.loop = int.Parse(elementData[6][0]); elem.speed = int.Parse(elementData[7][0]); elem.direction = int.Parse(elementData[8][0]); elements.Add(elem); } return elements; }
然后在Start方法里调用这个转换方法:
List<MapElement> mapElements = ConvertToMapElements(innerMap); // 遍历输出测试 foreach (var elem in mapElements) { Debug.Log($"元素类型:{elem.type},位置:({elem.x}, {elem.y})"); }
可选优化:使用Newtonsoft.Json
如果你觉得手动转类型太麻烦,可以在Unity Package Manager中安装Newtonsoft.Json(官方支持的包),它对混合类型的JSON解析更灵活,能直接把内层数据解析成动态类型,代码会简洁很多:
using Newtonsoft.Json.Linq; // 解析内层JSON的示例 JObject innerObj = JObject.Parse(innerJson); JArray dataArray = (JArray)innerObj["data"]; foreach (var item in dataArray) { string type = item[0][0].ToString(); int x = (int)item[1][0]; // 其他属性同理 }
内容的提问来源于stack exchange,提问作者Michael Fontaine
相关产品推荐
相关产品推荐

