SQLite中Json序列化问题:Player字典值为空
问题分析与解决方案
问题现象
使用EF Core的HasConversion将Dictionary<string, Player>序列化为BLOB存储到数据库后,发现存储的Player对象全部为空(示例:{"667440114":{},"181308099":{},"1326342467":{}})。此前因反序列化构造函数错误添加了无参构造函数,但引发了当前序列化空对象的问题。
核心原因
System.Text.Json默认仅序列化公共属性,而你的Player类成员都是公共字段;同时无参构造函数的存在,让序列化器无法正确识别需要写入的字段内容,最终导致空对象被存储。
解决方法
1. 规范修改:将公共字段改为公共属性(推荐)
这是符合.NET编码惯例的最优方案,能让序列化器自动识别并处理成员:
public class Player { public string UserID { get; set; } public string UserName { get; set; } public string UserToken { get; set; } public byte InGameOrder { get; set; } public string Team { get; set; } public List<Cards> Hand { get; set; } public Player(string id, string name, string token, int inGameOrder) { UserID = id; UserName = name; UserToken = token; InGameOrder = (byte)inGameOrder; Team = new string[] { "red", "black" }[inGameOrder % 2]; Hand = new List<Cards>(8); } // 保留无参构造函数供EF Core反序列化使用 public Player() { } }
2. 保留字段:配置序列化选项包含公共字段
如果不想修改字段为属性,可以在JsonSerializerOptions中开启字段序列化:
// 定义序列化配置 var options = new JsonSerializerOptions { IncludeFields = true, // 可添加其他配置,如忽略循环引用、缩进格式化等 }; // 应用到EF Core的类型转换中 modelBuilder.Entity<Game>() .Property(g => g.Players) .HasColumnName("Players") .HasColumnType("BLOB") .HasConversion( v => JsonSerializer.Serialize(v, options), s => JsonSerializer.Deserialize<Dictionary<string, Player>>(s, options)!, ValueComparer.CreateDefault(typeof(Dictionary<string, Player>), true));
3. 移除无参构造:标记反序列化专用构造函数
如果想去掉无参构造函数,可通过[JsonConstructor]标记用于反序列化的构造函数,确保参数与字段/属性名称匹配(若大小写不一致,可开启PropertyNameCaseInsensitive):
public class Player { public string UserID; public string UserName; public string UserToken; public byte InGameOrder; public string Team; public List<Cards> Hand; // 标记该构造函数为反序列化专用 [JsonConstructor] public Player(string userID, string userName, string userToken, byte inGameOrder, string team, List<Cards> hand) { UserID = userID; UserName = userName; UserToken = userToken; InGameOrder = inGameOrder; Team = team; Hand = hand ?? new List<Cards>(8); } // 保留业务逻辑构造函数 public Player(string id, string name, string token, int inGameOrder) { UserID = id; UserName = name; UserToken = token; InGameOrder = (byte)inGameOrder; Team = new string[] { "red", "black" }[inGameOrder % 2]; Hand = new List<Cards>(8); } }
同时更新序列化配置:
var options = new JsonSerializerOptions { IncludeFields = true, PropertyNameCaseInsensitive = true // 允许参数与字段大小写不匹配 };
额外修正点
你的添加玩家代码中存在参数顺序错误:
// 原错误代码 gameFound.Players.Add(userToken, new Player(userID, userToken, userName, prevPlayerInGameOrder + 1));
构造函数第二个参数应为userName,第三个是userToken,修正后:
gameFound.Players.Add(userToken, new Player(userID, userName, userToken, prevPlayerInGameOrder + 1));
内容的提问来源于stack exchange,提问作者Erray1
相关产品推荐
相关产品推荐

