Unity C#读取含多层子键的JSON字典问题求助
在Unity中读取多层字典结构JSON并实现玩家位置同步
问题背景
尝试用C#脚本在Unity中读取JSON数据,目标是基于位置数据同步移动玩家。需要在Update()前按字典键对嵌套字典分组,此前普通数组结构的JSON可正常读取,但多层字典结构的JSON处理时出现CS0029(隐式转换错误)和CS1061(List无Keys属性)错误。
可正常读取的JSON格式
{"__comment__": "This file contains event and positional information. Data generated on 2024-07-14 17:51:10. Version: 1.0.0.","event_data": [{"player_name": "player1","league_id": "xxxx","team": 2,"x": 26.68,"y": 9.179,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1},{"player_name": "player2","league_id": "xxxx","team": 2,"x": 19.109,"y": 9.189,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1}]}
无法正确处理的多层字典JSON格式
{"__comment__": "This file contains event and positional information grouped by match time seconds. Data generated on 2024-07-14 17:51:10. Version: 1.0.0.","event_data": {"1": {"1": [{"player_name": "player1","league_id": "xxxx","team": 2,"x": 26.68,"y": 9.179,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1},{"player_name": "player2","league_id": "xxxx","team": 2,"x": 19.109,"y": 9.189,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1},{"player_name": "player3","league_id": "xxx","team": 2,"x": 23.204,"y": 8.801,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1}]},"34": {"873": [{"player_name": "player4","league_id": "xxxx","team": 1,"x": 39.344,"y": 19.727,"z": 1.6,"match_time_seconds_column": 873,"event_key": 34}]}}}
原代码问题
原代码混用JsonUtility和Newtonsoft.Json,且后续遍历逻辑错误(试图访问List的Keys属性),导致类型转换和属性不存在的错误。
正确实现方案
1. 定义匹配JSON结构的实体类
确保EventPositionalData类字段与JSON中玩家数据的键完全对应,同时RootObject的event_data类型匹配多层字典结构:
using Newtonsoft.Json; using System.Collections.Generic; using UnityEngine; public class DataReader3 : MonoBehaviour { // 玩家位置数据实体类 [System.Serializable] public class EventPositionalData { public string player_name; public string league_id; // 若JSON中为数字类型,改为int public int team; public float x; public float y; public float z; public int match_time_seconds_column; public int event_key; } // 根对象类,匹配多层字典结构的JSON public class RootObject { public string __comment__; public Dictionary<string, Dictionary<string, List<EventPositionalData>>> event_data; } public TextAsset jsonFile; // 在Inspector中拖入JSON文件 private RootObject parsedData; // 预分组存储,方便Update快速获取 private Dictionary<string, List<EventPositionalData>> groupedData = new Dictionary<string, List<EventPositionalData>>(); void Start() { // 仅用Newtonsoft.Json反序列化多层字典结构 parsedData = JsonConvert.DeserializeObject<RootObject>(jsonFile.text); // 在Update前完成预分组 PreGroupData(); } // 预分组逻辑:按event_key+match_time_seconds_column整理数据 void PreGroupData() { // 遍历外层event_key字典 foreach (var eventKeyValuePair in parsedData.event_data) { string eventKey = eventKeyValuePair.Key; var timeDict = eventKeyValuePair.Value; // 遍历内层match_time字典 foreach (var timeKeyValuePair in timeDict) { string matchTime = timeKeyValuePair.Key; List<EventPositionalData> playerList = timeKeyValuePair.Value; // 用eventKey+matchTime作为唯一键存储玩家列表 groupedData[$"{eventKey}_{matchTime}"] = playerList; } } } void Update() { // 示例:根据当前游戏状态获取对应玩家列表并同步位置 string targetKey = "1_1"; // 假设当前需要同步eventKey=1、matchTime=1的玩家 if (groupedData.TryGetValue(targetKey, out var players)) { foreach (var playerData in players) { // 根据player_name找到对应玩家对象,设置位置 // GameObject playerObj = GameObject.Find(playerData.player_name); // if (playerObj != null) // { // playerObj.transform.position = new Vector3(playerData.x, playerData.y, playerData.z); // } } } } }
2. 关键修正点
- 统一序列化工具:多层字典结构不适合Unity内置的
JsonUtility,全程使用Newtonsoft.Json(需通过Unity Package Manager搜索导入Newtonsoft Json包)。 - 字段严格匹配:C#类的字段名必须与JSON中的键完全一致,若需改名可使用
[JsonProperty("json_key_name")]特性指定。 - 正确遍历嵌套字典:外层遍历
event_key字典,内层遍历match_time字典,最终获取玩家列表,避免错误访问List的Keys属性。
3. 常见错误规避
- 禁止混用
JsonUtility和Newtonsoft.Json:前者对复杂嵌套结构支持有限,后者更适合处理多层字典JSON。 - 类型匹配检查:确保JSON中的数据类型与C#字段类型一致(如浮点数对应
float,整数对应int,字符串对应string)。
内容的提问来源于stack exchange,提问作者Vintertid
相关产品推荐
相关产品推荐

