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

使用Npgsql执行SELECT查询时JSON数组列被转为字符串的问题

解决Npgsql查询中JSON数组列被序列化为字符串的问题

问题原因

你当前代码中reader.GetValue(i)会把PostgreSQL的json/jsonb类型列直接返回为字符串,Newtonsoft.Json序列化时会保留字符串的引号,导致JSON数组变成带引号的字符串格式。

解决方案1:读取时手动解析JSON列

在读取每列数据时,判断字段类型是否为json或jsonb,将其解析为Newtonsoft.Json的JArray类型,这样序列化时会自动转换为原生JSON数组格式。

修改后的代码:

using Newtonsoft.Json.Linq; // 需引入该命名空间

var result = new List<Dictionary<string, object>>();

await using (var cmd = new NpgsqlCommand("SELECT * FROM global", conn))
await using (var reader = await cmd.ExecuteReaderAsync())
{
    while (await reader.ReadAsync())
    {
        var row = new Dictionary<string, object>();
        for (int i = 0; i < reader.FieldCount; i++)
        {
            var fieldName = reader.GetName(i);
            var dataType = reader.GetDataTypeName(i);
            
            if (reader.IsDBNull(i))
            {
                row[fieldName] = null;
                continue;
            }
            
            // 判断是否为JSON类型列
            if (dataType == "json" || dataType == "jsonb")
            {
                var jsonStr = reader.GetString(i);
                // 解析为JArray,空字符串处理为空数组
                row[fieldName] = string.IsNullOrWhiteSpace(jsonStr) ? JArray.Parse("[]") : JArray.Parse(jsonStr);
            }
            else
            {
                row[fieldName] = reader.GetValue(i);
            }
        }
        result.Add(row);
    }
}

var jsonResult = JsonConvert.SerializeObject(result, Newtonsoft.Json.Formatting.Indented);
Console.WriteLine(jsonResult);

解决方案2:使用强类型实体类

定义与数据库表结构匹配的实体类,利用Npgsql的类型映射自动将JSON列转换为JArray或List<string>,序列化时自然保持数组格式。

步骤1:定义实体类

using Newtonsoft.Json.Linq;

public class GlobalRecord
{
    public int Id { get; set; }
    public bool Banned { get; set; }
    // 若确定strikes是字符串数组,也可替换为List<string>
    public JArray Strikes { get; set; }
}

步骤2:修改查询代码

var result = new List<GlobalRecord>();

await using (var cmd = new NpgsqlCommand("SELECT * FROM global", conn))
await using (var reader = await cmd.ExecuteReaderAsync())
{
    while (await reader.ReadAsync())
    {
        result.Add(new GlobalRecord
        {
            Id = reader.GetInt32(reader.GetOrdinal("id")),
            Banned = reader.GetBoolean(reader.GetOrdinal("banned")),
            // 直接读取为JArray类型
            Strikes = reader.GetFieldValue<JArray>(reader.GetOrdinal("strikes"))
        });
    }
}

var jsonResult = JsonConvert.SerializeObject(result, Newtonsoft.Json.Formatting.Indented);
Console.WriteLine(jsonResult);

补充说明

如果你的项目使用System.Text.Json而非Newtonsoft.Json,可以将JArray替换为JsonElement或JsonDocument,序列化逻辑保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 04:01:28