C#:如何将JSON字符串引用映射为对象属性实现序列化反序列化
实现JSON位置名称到Location实例的映射转换
核心思路
先加载locations.json中的所有位置数据,构建位置名称→Location实例的映射字典,再通过自定义JSON转换器,在反序列化objects.json时自动将CurrentLocation字段的字符串名称替换为对应的Location实例;序列化时则反向将Location转为名称字符串。
步骤1:加载位置映射字典
先读取并解析locations.json,构建用于查找的字典:
// 读取locations.json文件内容 var locationsJson = File.ReadAllText("locations.json"); // 反序列化为Location列表 var locations = JsonSerializer.Deserialize<List<Location>>(locationsJson); // 构建名称到Location实例的映射字典 var locationMap = locations.ToDictionary(loc => loc.Name, loc => loc);
步骤2:编写自定义JSON转换器
创建继承自JsonConverter<T>的转换器,处理字符串与Location实例的互转:
public class LocationReferenceConverter : JsonConverter<Location> { private readonly Dictionary<string, Location> _locationMap; // 通过构造函数传入预先构建的位置映射字典 public LocationReferenceConverter(Dictionary<string, Location> locationMap) { _locationMap = locationMap ?? throw new ArgumentNullException(nameof(locationMap)); } // 反序列化:将JSON中的位置名称转为Location实例 public override Location Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var locationName = reader.GetString(); // 找不到对应位置时返回默认实例,也可根据需求抛出异常 if (locationName == null || !_locationMap.TryGetValue(locationName, out var location)) { return new Location(); // 替代方案:throw new JsonException($"未找到名为「{locationName}」的位置"); } return location; } // 序列化:将Location实例转为名称字符串 public override void Write(Utf8JsonWriter writer, Location value, JsonSerializerOptions options) { writer.WriteStringValue(value.Name); } }
步骤3:使用转换器处理objects.json
配置序列化选项并添加转换器,完成反序列化/序列化操作:
// 配置JSON序列化选项 var jsonOptions = new JsonSerializerOptions(); // 添加自定义转换器,传入位置映射字典 jsonOptions.Converters.Add(new LocationReferenceConverter(locationMap)); // 反序列化objects.json为ObjectOfInterest列表 var objectsJson = File.ReadAllText("objects.json"); var objectsList = JsonSerializer.Deserialize<List<ObjectOfInterest>>(objectsJson, jsonOptions); // 序列化时自动将Location转为名称字符串 var serializedJson = JsonSerializer.Serialize(objectsList, jsonOptions);
注意事项
- 若
ObjectOfInterest类中的CurrentLocation类型是LocationNode而非Location,需将转换器的泛型类型改为LocationNode,并补充LocationNode与Location的兼容逻辑(例如LocationNode继承Location,或包含Location属性)。 - 需保证
locations.json的加载操作在objects.json反序列化之前完成,确保映射字典已准备就绪。
内容的提问来源于stack exchange,提问作者SashaZd
相关产品推荐
相关产品推荐

