You need to enable JavaScript to run this app. Unity JsonUtility/LitJson解析JSON遇KeyNotFoundException及嵌套取值问题
优惠活动
大模型
产品
解决方案
定价
更多

Unity JsonUtility/LitJson解析JSON遇KeyNotFoundException及嵌套取值问题

问题根因与解决方案

一、报错代码的核心问题

你遇到的KeyNotFoundException,本质是对JSON的两个基础特性不熟悉导致的:

  • JSON键名是严格大小写敏感的
    LitJson内部把JSON对象映射为严格区分大小写的字典结构,必须和JSON原文的键名字符完全匹配才能访问到值。你提供的JSON原文中,data节点下的键是otherInfo(Info的首字母I为大写),但代码里写的是otherinfo(info全小写),两个字符串不完全相等,自然找不到对应键值。
    你第一个示例能正常运行,是因为代码里访问的stats、kills键名和JSON原文完全大小写一致,和解析逻辑本身没有关系。
  • JSON容器的访问规则差异
    JSON只有两种核心容器结构,访问逻辑完全不同:
    • 大括号{}包裹的对象结构:通过字符串键名访问成员
    • 中括号[]包裹的数组结构:通过从0开始的整数索引访问成员,不存在字符串键

二、LitJson 场景下的可扩展实现

基础修正:单键值正确读取

修正键名大小写匹配问题后,即可正常读取otherInfo字段:

JsonData jsonData = JsonMapper.ToObject(jsonString);
JsonData dataObj = jsonData["data"];
// 严格匹配JSON原文的键名大小写
int otherInfo = int.Parse(dataObj["otherInfo"].ToString());
Debug.Log(otherInfo);

小技巧:LitJson的对象类型JsonData提供了ContainsKey方法,取值前可以先判断目标键是否存在,避免键名不匹配时直接抛出异常导致程序崩溃。

// 安全判断键存在再取值的写法
if (dataObj.ContainsKey("otherInfo"))
{
    int otherInfo = int.Parse(dataObj["otherInfo"].ToString());
}

可扩展读取任意数量的玩家数据

对于scoreboard这种数组结构,LitJson会自动将其识别为带整数索引、有Count属性的集合,不管数组内有多少个玩家条目,都可以通过遍历的方式读取,不需要写死固定数量的取值逻辑:

JsonData scoreboardArray = dataObj["scoreboard"];
// 遍历所有玩家条目,覆盖任意数量的玩家
for (int i = 0; i < scoreboardArray.Count; i++)
{
    JsonData currentPlayer = scoreboardArray[i];
    // 读取玩家基础字段
    string playerName = currentPlayer["player"].ToString();
    int playerScore = int.Parse(currentPlayer["score"].ToString());
    // 读取嵌套的pdata数据
    JsonData pdata = currentPlayer["pdata"];
    int pdataValueA = int.Parse(pdata["a"].ToString());
    int pdataValueB = int.Parse(pdata["b"].ToString());
    // 在此处可自定义逻辑存储读取到的玩家数据
    Debug.Log($"玩家{playerName} 分数{playerScore} pdata值:a={pdataValueA}, b={pdataValueB}");
}

三、可迁移到JsonUtility的适配方案

如果后续需要从LitJson切换到Unity原生的JsonUtility,只需要按照JSON结构定义对应的可序列化类即可,核心要求同样是字段名和JSON键名严格大小写匹配:

  1. 按照JSON层级定义对应数据结构:
[System.Serializable]
public class PData
{
    public int a;
    public int b;
}

[System.Serializable]
public class PlayerEntry
{
    public string player;
    public int score;
    public PData pdata;
}

[System.Serializable]
public class DataNode
{
    public int otherInfo;
    public List<PlayerEntry> scoreboard;
    public int otherInfo2;
}

[System.Serializable]
public class RootStructure
{
    public DataNode data;
}
  1. 反序列化与读取逻辑:
RootStructure root = JsonUtility.FromJson<RootStructure>(jsonString);
// 直接读取otherInfo字段
int info = root.data.otherInfo;
// 遍历任意数量的玩家条目,无需调整代码适配条目数量变化
foreach (var player in root.data.scoreboard)
{
    string name = player.player;
    int score = player.score;
    int pA = player.pdata.a;
    int pB = player.pdata.b;
}

内容的提问来源于stack exchange,提问作者coldchickens

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.06 19:36:03