Dapper能否将数据库中存储为文本的JSON反序列化为实体类数组属性?
当然可以实现!Dapper默认确实只会把数据库里的JSON字符串当成普通字符串处理,但我们有几种简单的方案来让它自动(或者手动)完成JSON到int[]的反序列化,下面给你详细说明:
方案1:全局注册自定义类型处理器(推荐)
这是最通用的做法,我们可以给int[]类型写一个专属的类型处理器,告诉Dapper如何在数据库字符串和数组之间转换。
首先创建处理器类:
using System.Data; using System.Text.Json; using Dapper; public class IntArrayTypeHandler : SqlMapper.TypeHandler<int[]> { // 把数组序列化为JSON字符串,用于写入数据库(如果有写入需求的话) public override void SetValue(IDbDataParameter parameter, int[] value) { parameter.Value = value == null ? null : JsonSerializer.Serialize(value); } // 把数据库返回的JSON字符串反序列化为int数组 public override int[] Parse(object value) { if (value is string json && !string.IsNullOrWhiteSpace(json)) { return JsonSerializer.Deserialize<int[]>(json) ?? Array.Empty<int>(); } return Array.Empty<int>(); } }
然后在你的应用启动时(比如Program.cs里)注册这个处理器:
SqlMapper.AddTypeHandler(new IntArrayTypeHandler());
之后再执行你原来的查询代码,Dapper就会自动把MyArrayAsJson字段的JSON字符串转成int[],赋值给MyType的MyArray属性了,完全不需要修改原查询逻辑。
方案2:临时手动映射(适合局部场景)
如果不想全局修改Dapper的行为,或者只在少数地方需要这个转换,也可以先查询到匿名对象,再手动完成反序列化:
var sql = "SELECT id, MyArrayAsJson"; var rawResults = await connection.QueryAsync(sql); var x = rawResults.Select(result => new MyType { Id = result.id, MyArray = JsonSerializer.Deserialize<int[]>(result.MyArrayAsJson.ToString()) ?? Array.Empty<int>() }).ToList();
这种方式灵活度高,不需要全局配置,适合临时或局部的转换需求。
方案3:利用Dapper的查询回调处理
你也可以在QueryAsync方法里传入一个映射回调,在Dapper完成基础映射后,手动修正MyArray的类型:
var sql = "SELECT id, MyArrayAsJson as MyArray"; var x = await connection.QueryAsync<MyType>(sql, typeInstance => { // Dapper会先把MyArray映射成字符串,这里我们手动转成数组 if (typeInstance.MyArray is string json) { typeInstance.MyArray = JsonSerializer.Deserialize<int[]>(json) ?? Array.Empty<int>(); } return typeInstance; }, splitOn: "" // 单表查询不需要拆分字段,留空即可 );
注意事项
上面的示例用的是.NET 6+内置的System.Text.Json,如果你项目里用的是Newtonsoft.Json(Json.NET),只需要把JsonSerializer相关的代码换成JsonConvert即可,比如:
// 反序列化 JsonConvert.DeserializeObject<int[]>(json) // 序列化 JsonConvert.SerializeObject(value)
内容的提问来源于stack exchange,提问作者Joe Phillips
相关产品推荐
相关产品推荐

