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

C#读取JSON文件后无法使用foreach循环操作数据的问题

图书馆管理系统JSON反序列化类型转换问题解决

问题说明

开发的图书馆管理系统支持用户注册、图书添加、借阅及归还功能。首次运行自动创建database.json时功能正常,但再次运行读取已存在的文件后,无法通过foreach循环处理数据。执行foreach (User user in (List<User>)database["users"])时,报错:无法将类型为'Newtonsoft.Json.Linq.JArray'的对象转换为类型'System.Collections.Generic.List'。

相关代码片段:

namespace LibraryManagementSystem
{
    public class Library
    {
        public Dictionary<string, object> database;

        public Library()
        {
            database = new Dictionary<string, object>
            {   
                { "books", new List<Book>() },
                { "users", new List<User> { new User { Login = "admin", Password = "admin" } } },
                { "registry", new List<Registry>() }
            };
            Setup();
        }

        private void Setup()
        {
            string cwd = Directory.GetCurrentDirectory();
            string databasePath = Path.Combine(cwd, "database.json");
            if (File.Exists(databasePath))
            {
                string json = File.ReadAllText(databasePath);
                database = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
                Console.WriteLine("Library successfully loaded!");
                Console.WriteLine(JsonConvert.SerializeObject(database));
            }
            else if (!File.Exists(databasePath))
            {
                Console.WriteLine("I can't find database.json file from last session...");
                Console.WriteLine("No problem :) I will create new one!");
                string json = JsonConvert.SerializeObject(database);
                File.WriteAllText(databasePath, json);
                Console.WriteLine(JsonConvert.SerializeObject(database));
            }

            Console.WriteLine("Psst! I have hint for you :) there is list of avaliable users, please don't waste it!");
            Console.WriteLine(JsonConvert.SerializeObject(database["users"]));
        }
    }
}

生成的database.json内容:

{
    "books":[],
    "users":[{"Login":"admin","Password":"admin"}],
    "registry":[]
}

错误原因

使用JsonConvert.DeserializeObject<Dictionary<string, object>>()反序列化JSON时,JSON数组会被默认解析为JArray类型(Newtonsoft.Json的动态数组类型),而非预先定义的List<User>等强类型集合,直接强制转换会触发类型不匹配异常。

解决方案

方法1:反序列化为强类型模型(推荐)

创建与JSON结构匹配的强类型模型类,替代Dictionary<string, object>,反序列化时直接映射为强类型集合,避免类型转换问题。

步骤1:定义Database模型类

public class Database
{
    public List<Book> books { get; set; }
    public List<User> users { get; set; }
    public List<Registry> registry { get; set; }
}

步骤2:修改Library类代码

namespace LibraryManagementSystem
{
    public class Library
    {
        public Database database;

        public Library()
        {
            database = new Database
            {   
                books = new List<Book>(),
                users = new List<User> { new User { Login = "admin", Password = "admin" } },
                registry = new List<Registry>()
            };
            Setup();
        }

        private void Setup()
        {
            string cwd = Directory.GetCurrentDirectory();
            string databasePath = Path.Combine(cwd, "database.json");
            if (File.Exists(databasePath))
            {
                string json = File.ReadAllText(databasePath);
                // 反序列化为强类型Database对象
                database = JsonConvert.DeserializeObject<Database>(json);
                Console.WriteLine("Library successfully loaded!");
                Console.WriteLine(JsonConvert.SerializeObject(database));
            }
            else
            {
                Console.WriteLine("I can't find database.json file from last session...");
                Console.WriteLine("No problem :) I will create new one!");
                string json = JsonConvert.SerializeObject(database);
                File.WriteAllText(databasePath, json);
                Console.WriteLine(JsonConvert.SerializeObject(database));
            }

            Console.WriteLine("Psst! I have hint for you :) there is list of avaliable users, please don't waste it!");
            Console.WriteLine(JsonConvert.SerializeObject(database.users));
        }
    }
}

修改后,直接使用foreach (User user in database.users)即可正常遍历用户集合。

方法2:手动将JArray转换为强类型集合

若需保留Dictionary<string, object>,可在读取JSON后手动将JArray转换为对应强类型集合,或在遍历前进行转换。

方式A:读取时转换

private void Setup()
{
    string cwd = Directory.GetCurrentDirectory();
    string databasePath = Path.Combine(cwd, "database.json");
    if (File.Exists(databasePath))
    {
        string json = File.ReadAllText(databasePath);
        var jObject = JObject.Parse(json);
        database = new Dictionary<string, object>
        {
            { "books", jObject["books"].ToObject<List<Book>>() },
            { "users", jObject["users"].ToObject<List<User>>() },
            { "registry", jObject["registry"].ToObject<List<Registry>>() }
        };
        Console.WriteLine("Library successfully loaded!");
        Console.WriteLine(JsonConvert.SerializeObject(database));
    }
    // 其余代码不变
}

方式B:遍历时转换

// 在需要遍历users的位置添加转换逻辑
var users = ((JArray)database["users"]).ToObject<List<User>>();
foreach (User user in users)
{
    // 执行用户相关处理逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:34:54