C#如何将JSON子属性反序列化到父类属性中?
当然可以搞定!这种把JSON里嵌套的子属性映射到父类平级属性的需求,在.NET里用主流的JSON序列化库都能实现,我给你详细讲讲两种常用方案:
使用Newtonsoft.Json(Json.NET)实现映射
这是.NET生态里老牌且功能丰富的JSON库,处理这种映射非常简单,推荐优先用这个方案:
方法1:利用JsonProperty特性的路径映射
直接在你的Issue类属性上添加JsonProperty特性,指定对应的JSON嵌套路径即可:
public class Issue { public int? id { get; set; } [JsonProperty(PropertyName = "project.id")] public int project_id { get; set; } [JsonProperty(PropertyName = "project.name")] public string project_name { get; set; } }
反序列化的时候直接调用常规方法就行:
string json = "{ \"issue\" : { \"id\": 1, \"project\": { \"id\":1, \"name\":\"name of project\" } } }"; // 先提取issue节点的内容(也可以把Issue包装到对应类里,这里只处理核心对象) var issueJson = JObject.Parse(json)["issue"].ToString(); var issue = JsonConvert.DeserializeObject<Issue>(issueJson);
方法2:自定义Json转换器(适合复杂场景)
如果你的映射逻辑更复杂,还可以写一个自定义转换器来手动处理:
public class IssueConverter : JsonConverter<Issue> { public override Issue ReadJson(JsonReader reader, Type objectType, Issue existingValue, bool hasExistingValue, JsonSerializer serializer) { var jo = JObject.Load(reader); var issue = new Issue(); issue.id = (int?)jo["id"]; issue.project_id = (int)jo["project"]["id"]; issue.project_name = (string)jo["project"]["name"]; return issue; } public override void WriteJson(JsonWriter writer, Issue value, JsonSerializer serializer) { // 如果需要序列化回JSON,这里可以编写对应的逻辑 var jo = new JObject(); jo["id"] = value.id; jo["project"] = new JObject { ["id"] = value.project_id, ["name"] = value.project_name }; jo.WriteTo(writer); } }
使用转换器时,在序列化选项里添加即可:
var settings = new JsonSerializerSettings(); settings.Converters.Add(new IssueConverter()); var issue = JsonConvert.DeserializeObject<Issue>(issueJson, settings);
使用System.Text.Json实现映射
如果你用的是.NET Core 3.0+或者.NET 5+,默认的System.Text.Json也能实现,不过它原生不支持路径映射,需要用下面两种方式:
方法1:自定义Json转换器
写一个专属的转换器来手动解析嵌套属性:
public class IssueConverter : JsonConverter<Issue> { public override Issue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using JsonDocument doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; var issue = new Issue(); issue.id = root.GetProperty("id").GetInt32(); var projectElement = root.GetProperty("project"); issue.project_id = projectElement.GetProperty("id").GetInt32(); issue.project_name = projectElement.GetProperty("name").GetString(); return issue; } public override void Write(Utf8JsonWriter writer, Issue value, JsonSerializerOptions options) { // 序列化逻辑(按需实现) writer.WriteStartObject(); writer.WriteNumber("id", value.id ?? 0); writer.WriteStartObject("project"); writer.WriteNumber("id", value.project_id); writer.WriteString("name", value.project_name); writer.WriteEndObject(); writer.WriteEndObject(); } }
使用时添加转换器到选项:
var options = new JsonSerializerOptions(); options.Converters.Add(new IssueConverter()); var issue = JsonSerializer.Deserialize<Issue>(issueJson, options);
方法2:匿名类型投影(简单场景快捷方案)
如果只是简单的映射,也可以先反序列化成JsonElement,再手动赋值:
var jsonElement = JsonSerializer.Deserialize<JsonElement>(issueJson); var issue = new Issue { id = jsonElement.GetProperty("id").GetInt32(), project_id = jsonElement.GetProperty("project").GetProperty("id").GetInt32(), project_name = jsonElement.GetProperty("project").GetProperty("name").GetString() };
内容的提问来源于stack exchange,提问作者Adolfok3
相关产品推荐
相关产品推荐

