C#中如何将包含字典属性的数据模型的JSON输出扁平化?
可行实现方案
以下提供三种常用实现方式,均可直接输出你需要的完全扁平化JSON结构:
方案1:使用Newtonsoft.Json(Json.NET)自定义转换器
这是最常用的实现方式,无需额外生成中间对象,序列化时直接展开结构:
using Newtonsoft.Json; public class PersonFlattenConverter : JsonConverter<Person> { public override void WriteJson(JsonWriter writer, Person value, JsonSerializer serializer) { writer.WriteStartObject(); // 写入Person类原生属性 writer.WritePropertyName(nameof(Person.Name)); writer.WriteValue(value.Name); writer.WritePropertyName(nameof(Person.DOB)); // 日期格式可根据需求调整,不需要固定格式可直接传value.DOB writer.WriteValue(value.DOB.ToString("dd/MM/yyyy")); // 展开Address字典的所有键值对 foreach (var kvp in value.Address) { writer.WritePropertyName(kvp.Key); writer.WriteValue(kvp.Value); } writer.WriteEndObject(); } public override Person ReadJson(JsonReader reader, Type objectType, Person existingValue, bool hasExistingValue, JsonSerializer serializer) { throw new NotImplementedException("当前转换器仅支持序列化操作"); } }
使用示例:
// 构造测试数据 var person = new Person { Name = "Jim", DOB = new DateTime(1990,1,21), Address = new Dictionary<string, string> { {"Number", "18"}, {"Line1", "Knotta Street"}, {"Line2", "Thrumpton-on-Thames"}, {"Postcode", "SW1 2AA"} } }; // 序列化时指定自定义转换器 string json = JsonConvert.SerializeObject(person, Formatting.Indented, new PersonFlattenConverter());
方案2:使用.NET官方System.Text.Json自定义转换器
适合不想引入第三方库的场景,实现逻辑和Json.NET类似:
using System.Text.Json; using System.Text.Json.Serialization; public class PersonFlattenConverter : JsonConverter<Person> { public override void Write(Utf8JsonWriter writer, Person value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WriteString(nameof(Person.Name), value.Name); // 日期格式可按需调整 writer.WriteString(nameof(Person.DOB), value.DOB.ToString("dd/MM/yyyy")); foreach (var kvp in value.Address) { writer.WriteString(kvp.Key, kvp.Value); } writer.WriteEndObject(); } public override Person Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { throw new NotImplementedException("当前转换器仅支持序列化操作"); } }
使用示例:
var options = new JsonSerializerOptions { WriteIndented = true }; options.Converters.Add(new PersonFlattenConverter()); string json = JsonSerializer.Serialize(person, options);
方案3:动态构建扁平化匿名对象
如果确实需要先得到中间的扁平化对象再序列化,可以用ExpandoObject动态构建:
using System.Dynamic; public static dynamic FlattenPerson(Person person) { IDictionary<string, object> flatObj = new ExpandoObject(); flatObj[nameof(Person.Name)] = person.Name; flatObj[nameof(Person.DOB)] = person.DOB.ToString("dd/MM/yyyy"); foreach (var kvp in person.Address) { flatObj[kvp.Key] = kvp.Value; } return flatObj; }
使用示例:
dynamic flatPerson = FlattenPerson(person); // 可以直接序列化该对象得到目标JSON string json = JsonConvert.SerializeObject(flatPerson, Formatting.Indented);
注意事项
如果Address字典的键可能和Person类原生属性(Name、DOB)重名,建议提前添加校验逻辑,避免属性覆盖。
内容的提问来源于stack exchange,提问作者jamheadart
相关产品推荐
相关产品推荐

