基于C# Newtonsoft JSON实现用户被动技能的JSON分类存储
问题
我正在开发一款基于《龙珠Z:爆裂大战》(Dokkan Battle)的Discord Bot小游戏,支持用户创建自定义被动技能,可通过指令查看对应属性。需要将这些被动技能数据按指定JSON格式存储(包含userPassiveStorage说明与members数组),但当前代码生成的JSON格式错误(仅单行存储)。现需实现向members数组添加新成员的功能,同时希望了解更易检索的存储方案。
当前代码:
public void StoreUserPassives(DokkanUserPassiveBuilder classObj) { using (StreamWriter sw = new StreamWriter("UserPassivesStorage.json")) { JsonSerializer serializer = new JsonSerializer(); List<DokkanUserPassiveBuilder> data = new List<DokkanUserPassiveBuilder>(); data.Add(classObj); string json = JsonConvert.SerializeObject(data.ToArray(), Formatting.Indented); serializer.Serialize(sw, json); } }
目标JSON格式:
{ "userPassiveStorage": "Storage for user created passives using /passivecreator", "members": [ { "passiveName": "", "leaderName": "", "unitHP": 0, "unitATK": 0, "unitDEF": 0, "leaderValue": 0, "passiveATK": 0, "passiveDEF": 0, "supportBuff": 0, "links": "" } ] }
解决方案
一、修复JSON格式并实现添加成员功能
首先得创建一个匹配目标JSON结构的实体类,不能直接序列化列表:
// 对应整体存储结构的实体类 public class UserPassiveStorage { [JsonProperty("userPassiveStorage")] public string Description { get; set; } = "Storage for user created passives using /passivecreator"; [JsonProperty("members")] public List<DokkanUserPassiveBuilder> Members { get; set; } = new List<DokkanUserPassiveBuilder>(); } // 确保DokkanUserPassiveBuilder的属性和目标JSON字段一一对应 public class DokkanUserPassiveBuilder { [JsonProperty("passiveName")] public string PassiveName { get; set; } = ""; [JsonProperty("leaderName")] public string LeaderName { get; set; } = ""; [JsonProperty("unitHP")] public int UnitHP { get; set; } [JsonProperty("unitATK")] public int UnitATK { get; set; } [JsonProperty("unitDEF")] public int UnitDEF { get; set; } [JsonProperty("leaderValue")] public int LeaderValue { get; set; } [JsonProperty("passiveATK")] public int PassiveATK { get; set; } [JsonProperty("passiveDEF")] public int PassiveDEF { get; set; } [JsonProperty("supportBuff")] public int SupportBuff { get; set; } [JsonProperty("links")] public string Links { get; set; } = ""; }
然后修改存储方法,实现读取现有数据→添加新成员→写入文件的完整逻辑:
public void StoreUserPassives(DokkanUserPassiveBuilder newPassive) { UserPassiveStorage storage = null; string filePath = "UserPassivesStorage.json"; // 读取已有文件(如果存在) if (File.Exists(filePath)) { string existingJson = File.ReadAllText(filePath); storage = JsonConvert.DeserializeObject<UserPassiveStorage>(existingJson); } else { // 文件不存在就初始化新的存储结构 storage = new UserPassiveStorage(); } // 把新被动技能加入members数组 storage.Members.Add(newPassive); // 序列化并写入格式化后的JSON string formattedJson = JsonConvert.SerializeObject(storage, Formatting.Indented); File.WriteAllText(filePath, formattedJson); }
关键修复说明
- 之前的代码错误地把序列化后的JSON字符串再次序列化,导致输出的是转义后的单行内容,现在直接序列化实体类并通过
Formatting.Indented生成格式化的JSON。 - 新增了读取现有数据的逻辑,避免每次覆盖整个文件,而是在原有数据基础上追加新成员。
二、更易检索的存储方案
如果需要频繁检索被动技能(比如按技能名称、创建者ID查找),纯JSON文件的效率会随数据量增加下降,推荐以下几种方案:
1. 本地SQLite数据库
SQLite是轻量级本地数据库,适合小型Bot应用:
- 可以为被动技能创建数据表,给常用检索字段(比如
passiveName、userId)设置索引,大幅提升检索速度。 - 支持SQL查询,方便做复杂的筛选、排序操作。
- 示例表结构:
CREATE TABLE UserPassives ( Id INTEGER PRIMARY KEY AUTOINCREMENT, PassiveName TEXT NOT NULL, LeaderName TEXT, UnitHP INTEGER, UnitATK INTEGER, UnitDEF INTEGER, LeaderValue INTEGER, PassiveATK INTEGER, PassiveDEF INTEGER, SupportBuff INTEGER, Links TEXT, UserId TEXT NOT NULL -- 记录创建者ID,方便按用户检索 ); CREATE INDEX idx_passive_name ON UserPassives(PassiveName); CREATE INDEX idx_user_id ON UserPassives(UserId);
2. LiteDB文档型存储
LiteDB是.NET平台的轻量级文档数据库,类似MongoDB但无需服务器:
- 可以把每个被动技能作为独立文档存储,支持按字段创建索引和查询。
- 操作比SQLite更灵活,不用写SQL语句。
3. 优化JSON文件存储(适合小数据量)
如果坚持用JSON文件,可以做以下优化:
- 按用户ID分文件存储,比如每个用户的被动技能单独存一个JSON文件。
- 在内存中维护一个字典索引,比如
Dictionary<string, List<DokkanUserPassiveBuilder>>,键为用户ID,值为该用户的技能列表,每次修改后同步到JSON文件,检索时直接通过键获取,不用遍历整个数组。
内容的提问来源于stack exchange,提问作者user11057786
相关产品推荐
相关产品推荐

