如何解析SQL查询结果中的JSON字符串并映射至LinkedList?
看起来你已经搞定了普通字段的映射,现在就差解析那两个JSON格式的字段了。别担心,这事儿用C#里的JSON序列化库就能轻松解决,我给你一步步拆解:
1. 定义匹配JSON结构的实体类
首先,你得先创建一个和house、not_house字段返回的JSON结构完全对应的类。从你给出的JSON示例来看,我们可以定义这样的类:
public class HouseInfo { public string Email { get; set; } public bool Active { get; set; } public DateTime CreatedDate { get; set; } public List<string> Roles { get; set; } }
注意:如果JSON里的键名和C#属性名不匹配(比如JSON是小写的
[JsonProperty("email")]或者System.Text.Json的[JsonPropertyName("email")]。
2. 更新你的vinDetails模型
接下来,把原来vinDetails里的house和not_house字段类型从string改成我们刚定义的HouseInfo:
public class vinDetails { public string bundle { get; set; } public string fix { get; set; } public HouseInfo house { get; set; } public HouseInfo not_house { get; set; } }
如果你不想修改原有模型结构,也可以新增只读属性来存储解析后的对象(不过这种方式每次访问都会重新解析JSON,性能稍差),具体代码我放在最后补充。
3. 解析JSON并完成映射
现在就可以在读取数据的时候,把JSON字符串解析成HouseInfo对象了。这里分两种常用的库来演示:
方式一:使用Newtonsoft.Json(Json.NET)
这是.NET生态里非常流行的JSON库,需要先通过NuGet安装:Install-Package Newtonsoft.Json
然后修改你的数据读取代码:
// 假设你已经在循环读取DataReader的每一行 vinDetails e = new vinDetails(); { e.bundle = DataReaderExtension.GetStringOrNull(reader, "bundle"); e.fix = DataReaderExtension.GetStringOrNull(reader, "fix"); // 解析house字段的JSON字符串 var houseJson = DataReaderExtension.GetStringOrNull(reader, "House"); e.house = string.IsNullOrEmpty(houseJson) ? null : JsonConvert.DeserializeObject<HouseInfo>(houseJson); // 解析not_house字段的JSON字符串 var notHouseJson = DataReaderExtension.GetStringOrNull(reader, "not_House"); e.not_house = string.IsNullOrEmpty(notHouseJson) ? null : JsonConvert.DeserializeObject<HouseInfo>(notHouseJson); };
方式二:使用System.Text.Json(.NET Core/.NET 5+自带)
如果你用的是较新的.NET版本,不需要额外安装包,直接用自带的System.Text.Json:
using System.Text.Json; // ... vinDetails e = new vinDetails(); { e.bundle = DataReaderExtension.GetStringOrNull(reader, "bundle"); e.fix = DataReaderExtension.GetStringOrNull(reader, "fix"); var houseJson = DataReaderExtension.GetStringOrNull(reader, "House"); e.house = string.IsNullOrEmpty(houseJson) ? null : JsonSerializer.Deserialize<HouseInfo>(houseJson); var notHouseJson = DataReaderExtension.GetStringOrNull(reader, "not_House"); e.not_house = string.IsNullOrEmpty(notHouseJson) ? null : JsonSerializer.Deserialize<HouseInfo>(notHouseJson); };
4. 将结果添加到LinkedList
最后,把解析好的vinDetails对象添加到你的LinkedList里就行:
LinkedList<vinDetails> resultList = new LinkedList<vinDetails>(); // 循环读取DataReader的所有行 while (reader.Read()) { vinDetails e = new vinDetails(); // 上面的赋值和解析代码 resultList.AddLast(e); }
补充:不修改原有模型的方案
如果你不想改动vinDetails里的house和not_house字段类型,可以新增只读属性来存储解析后的对象:
public class vinDetails { public string bundle { get; set; } public string fix { get; set; } public string house { get; set; } public string not_house { get; set; } // 解析后的house信息,访问时自动解析 [JsonIgnore] // 如果要序列化这个类,避免重复输出 public HouseInfo ParsedHouse => string.IsNullOrEmpty(house) ? null : JsonConvert.DeserializeObject<HouseInfo>(house); [JsonIgnore] public HouseInfo ParsedNotHouse => string.IsNullOrEmpty(not_house) ? null : JsonConvert.DeserializeObject<HouseInfo>(not_house); }
不过这种方式每次访问ParsedHouse都会重新解析一次JSON,如果你要频繁访问的话,建议还是用第一种修改模型的方案。
内容的提问来源于stack exchange,提问作者fusolage

