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

PostgreSQL JSONB查询结果绑定C#模型报错的解决问询

问题分析

错误的核心原因是:PostgreSQL返回的content列是字符串类型的JSON数组,而你的ToModelList方法直接将DataTable序列化为JSON后,content字段会被保留为带引号的字符串值(例如 "[{\"created_by\": \"user1\", ...}]"),但C#模型中NegotiatedContents是List<NegotiatedContent>类型,Json.NET无法直接将字符串转换为集合对象,因此抛出类型转换错误。

解决方案

以下提供两种可行的修复方式,可根据你的代码习惯选择:

方式一:修改ToModelList扩展方法,手动处理JSON字段反序列化

直接在转换模型的过程中,对需要解析JSON的字段单独处理,确保字符串转成对应的集合:

using System.Reflection;
using Newtonsoft.Json;

public static List<T> ToModelList<T>(this DataTable dt) where T : new()
{
    if (dt?.Rows.Count == 0)
        return new List<T>();

    var modelList = new List<T>();
    var modelType = typeof(T);
    // 获取模型的公共属性
    var properties = modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (DataRow row in dt.Rows)
    {
        var model = new T();
        foreach (var prop in properties)
        {
            // 根据JsonProperty特性匹配DataTable列名
            var jsonAttr = prop.GetCustomAttribute<JsonPropertyAttribute>();
            string columnName = jsonAttr?.PropertyName ?? prop.Name;

            if (!dt.Columns.Contains(columnName))
                continue;

            var cellValue = row[columnName];
            if (cellValue == DBNull.Value)
                continue;

            // 判断当前属性是否为List<T>类型
            if (prop.PropertyType.IsGenericType && 
                prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
            {
                // 将字符串形式的JSON反序列化为对应集合
                string jsonStr = cellValue.ToString();
                var deserializedList = JsonConvert.DeserializeObject(jsonStr, prop.PropertyType);
                prop.SetValue(model, deserializedList);
            }
            else
            {
                // 普通类型直接转换赋值
                var convertedValue = Convert.ChangeType(cellValue, prop.PropertyType);
                prop.SetValue(model, convertedValue);
            }
        }
        modelList.Add(model);
    }

    return modelList;
}

方式二:使用自定义JsonConverter处理字段转换

通过自定义Json转换器,告诉Json.NET如何将字符串形式的JSON数组转换为List<NegotiatedContent>:

1. 定义自定义转换器

using Newtonsoft.Json;
using System.Collections.Generic;

public class JsonStringToListConverter<T> : JsonConverter<List<T>>
{
    public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 如果读取到的是字符串,先反序列化为JSON再转成集合
        if (reader.TokenType == JsonToken.String)
        {
            string jsonStr = reader.Value.ToString();
            return JsonConvert.DeserializeObject<List<T>>(jsonStr);
        }
        // 正常JSON数组直接反序列化
        return serializer.Deserialize<List<T>>(reader);
    }

    public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

2. 在模型中应用转换器

修改MainClauseHistoryDto,给NegotiatedContents属性添加转换器特性:

public class MainClauseHistoryDto
{
     [JsonProperty("transaction_id")]
     public int TransactionId { get; set; }
     [JsonProperty("content")]
     [JsonConverter(typeof(JsonStringToListConverter<NegotiatedContent>))]
     public List<NegotiatedContent> NegotiatedContents { get; set; }
 }

 public class NegotiatedContent
 {
     [JsonProperty("created_by")]
     public string CreatedBy { get; set; }
     [JsonProperty("created_date")]
     public DateTime CreatedDate { get; set; }
     [JsonProperty("title")]
     public string Title{ get; set; }
 }

3. 保留原ToModelList方法即可

此时原有的ToModelList方法无需修改,Json.NET会通过自定义转换器自动处理字符串到集合的转换。

验证说明

两种方式都能解决字符串JSON数组到C#集合的转换问题,方式一更通用(无需修改模型),方式二更灵活(可针对特定字段定制转换逻辑),根据你的实际场景选择即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 05:12:35