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

反序列化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结构完全匹配的中间类,完成反序列化后再映射到目标类:

  1. 定义中间类
public class PhoneDto
{
    public int PhoneId { get; set; }
    public string Name { get; set; }
    public int PhoneManufacturer { get; set; }
}
  1. 加载并缓存厂商数据
// 读取厂商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);
  1. 反序列化并映射为目标对象
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到对象的关联:

  1. 实现自定义转换器
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);
    }
}
  1. 使用转换器完成反序列化
// 加载厂商数据并生成字典
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:05:14