反序列化JSON时如何将Phone中的Manufacturer ID转为实体对象?
问题:反序列化JSON时关联外部对象
我定义了两个C#类:
public class Phone { public int PhoneId { get; set; } public string Name { get; set; } public Manufacturer PhoneManufacturer { get; set; } } public class Manufacturer { public int ManId { get; set; } public string Name { get; set; } }
同时有两个独立的JSON文件:
phones.json:
[ { "phoneId" : 45, "name": "S20", "phoneManufacturer":16 } ]
manufacturers.json:
[ { "manId" : 16, "name": "Samsung" } ]
我目前用以下代码反序列化Phone对象:
string jsonString = File.ReadAllText("phones.json"); return JsonSerializer.Deserialize<List<Phone>>(jsonString, new JsonSerializerOptions { PropertyNameCaseInsensitive = true})!;
默认反序列化会报错,因为phones.json里的phoneManufacturer是ID(数值16),但Phone类中对应的属性是Manufacturer对象类型,无法直接转换。我希望反序列化List<Phone>时,PhoneManufacturer属性能自动填充为manufacturers.json中对应的实际Manufacturer对象。
解决方案
方法一:中间类过渡(简单直观)
先定义与JSON结构完全匹配的中间类,完成反序列化后再映射到目标类:
- 定义中间类
public class PhoneDto { public int PhoneId { get; set; } public string Name { get; set; } public int PhoneManufacturer { get; set; } }
- 加载并缓存厂商数据
// 读取厂商JSON并转为字典,用于快速按ID查找 var manufacturerJson = File.ReadAllText("manufacturers.json"); var manufacturers = JsonSerializer.Deserialize<List<Manufacturer>>(manufacturerJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true})!; var manufacturerDict = manufacturers.ToDictionary(m => m.ManId);
- 反序列化并映射为目标对象
var phoneJson = File.ReadAllText("phones.json"); var phoneDtos = JsonSerializer.Deserialize<List<PhoneDto>>(phoneJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true})!; // 转换为Phone对象并关联对应的厂商 var phones = phoneDtos.Select(dto => new Phone { PhoneId = dto.PhoneId, Name = dto.Name, PhoneManufacturer = manufacturerDict[dto.PhoneManufacturer] }).ToList(); return phones;
方法二:自定义JsonConverter(更灵活)
通过自定义转换器,在反序列化过程中直接完成ID到对象的关联:
- 实现自定义转换器
public class ManufacturerConverter : JsonConverter<Manufacturer> { private readonly Dictionary<int, Manufacturer> _manufacturerDict; // 构造函数传入厂商字典 public ManufacturerConverter(Dictionary<int, Manufacturer> manufacturerDict) { _manufacturerDict = manufacturerDict; } public override Manufacturer Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 读取JSON中的ID数值,匹配对应的厂商对象 if (reader.TokenType == JsonTokenType.Number) { var manId = reader.GetInt32(); return _manufacturerDict.TryGetValue(manId, out var manufacturer) ? manufacturer : null; } throw new JsonException("无法解析厂商ID"); } public override void Write(Utf8JsonWriter writer, Manufacturer value, JsonSerializerOptions options) { // 如果需要将Phone序列化为JSON,这里可以写入厂商ID writer.WriteNumberValue(value.ManId); } }
- 使用转换器完成反序列化
// 加载厂商数据并生成字典 var manufacturerJson = File.ReadAllText("manufacturers.json"); var manufacturers = JsonSerializer.Deserialize<List<Manufacturer>>(manufacturerJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true})!; var manufacturerDict = manufacturers.ToDictionary(m => m.ManId); // 配置序列化选项,添加自定义转换器 var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, Converters = { new ManufacturerConverter(manufacturerDict) } }; // 直接反序列化到List<Phone> var phoneJson = File.ReadAllText("phones.json"); var phones = JsonSerializer.Deserialize<List<Phone>>(phoneJson, options)!; return phones;
内容的提问来源于stack exchange,提问作者ml123
相关产品推荐
相关产品推荐

