在C#类中将JSON对象字符串转换为int的更佳方案
优化System.Text.JSON反序列化时字符串转int的实现方案
问题背景
现有如下JSON数据:
[ { "change_date": "20211118 2134", "inspection_id": "74207177", "insp_unit_id": "185883333" } ]
对应的C#类定义为:
public class Root { public string change_date { get; set; } public string inspection_id { get; set; } public string insp_unit_id { get; set; } }
需求是将inspection_id、insp_unit_id这类字符串格式的ID以int类型返回,当前做法是在类中添加转换方法:
public int inspection_id_int() { return Convert.ToInt32(inspection_id); }
以下是基于System.Text.JSON的更优实现方案:
方案一:自定义JSON转换器+修改属性类型
直接将目标属性改为int类型,通过自定义转换器处理字符串与int的双向转换,这是最符合类型设计的方案。
步骤1:实现自定义转换器
using System.Text.Json; using System.Text.Json.Serialization; public class StringToIntConverter : JsonConverter<int> { // 反序列化:字符串转int public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { if (int.TryParse(reader.GetString(), out int result)) return result; throw new JsonException($"无法将字符串 {reader.GetString()} 转换为int类型"); } // 兼容JSON中直接是数字的情况 return reader.GetInt32(); } // 序列化:int转字符串(如果需要保留原JSON格式) public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } }
步骤2:修改Root类并标记转换器
public class Root { public string change_date { get; set; } [JsonConverter(typeof(StringToIntConverter))] public int inspection_id { get; set; } [JsonConverter(typeof(StringToIntConverter))] public int insp_unit_id { get; set; } }
步骤3:反序列化使用
var json = "[{\"change_date\":\"20211118 2134\",\"inspection_id\":\"74207177\",\"insp_unit_id\":\"185883333\"}]"; var rootList = JsonSerializer.Deserialize<List<Root>>(json); // 直接使用int类型属性 int id = rootList[0].inspection_id;
方案二:后台字段映射(保留字符串与int双类型)
如果需要同时保留原始字符串属性和int类型的访问入口,可以通过后台字段实现序列化与业务逻辑的分离。
修改Root类
using System.Text.Json.Serialization; public class Root { public string change_date { get; set; } // 后台字段映射JSON的inspection_id [JsonPropertyName("inspection_id")] private string _inspectionIdStr; // 对外暴露int类型属性 public int inspection_id => int.Parse(_inspectionIdStr); [JsonPropertyName("insp_unit_id")] private string _inspUnitIdStr; public int insp_unit_id => int.Parse(_inspUnitIdStr); }
反序列化配置
需要启用后台字段的序列化支持:
var options = new JsonSerializerOptions { IncludeFields = true, PropertyNameCaseInsensitive = true // 可选,兼容JSON键的大小写差异 }; var rootList = JsonSerializer.Deserialize<List<Root>>(json, options);
方案三:只读计算属性(极简读取场景)
如果仅需要读取时获取int类型值,不需要修改或序列化回JSON,直接使用只读计算属性替代原有方法,更符合C#属性规范。
修改Root类
public class Root { public string change_date { get; set; } public string inspection_id { get; set; } public string insp_unit_id { get; set; } // 只读计算属性,自动转换为int public int InspectionId => int.Parse(inspection_id); public int InspUnitId => int.Parse(insp_unit_id); }
使用方式
var rootList = JsonSerializer.Deserialize<List<Root>>(json); int id = rootList[0].InspectionId;
方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 自定义转换器 | 类型设计合理,双向转换支持完善,对外暴露正确类型 | 需要编写转换器代码 | 长期维护的项目,需要严格类型约束 |
| 后台字段映射 | 同时保留原始字符串和int类型 | 配置稍复杂,需要启用字段序列化 | 需兼容原有字符串属性的场景 |
| 只读计算属性 | 实现最简单,无额外配置 | 仅支持读取,无法反向序列化 | 临时需求、仅读取数据的场景 |
内容的提问来源于stack exchange,提问作者Dayton Brown
相关产品推荐
相关产品推荐

