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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:50:31