You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:31:38