如何在 C# 中平展数据模型的 JSON 输出?

  • 本文关键字:数据模型 JSON 输出 c#
  • 更新时间 :
  • 英文 :


如果我有这样一个模型:

public class Person
{
public string Name { get; set; }
public DateTime DOB { get; set; }
public Dictionary<string, string> Address { get; set; }
}

字典中可以有像

这样的数据
"Number", "18"
"Line1", "Knotta Street"
"Line2", "Thrumpton-on-Thames"
"Postcode", "SW1 2AA"

有没有办法让这个模型的实例变平,创建一个新的,临时的匿名对象,看起来像这样:

Name : Jim
DOB : 21/01/1990
Number : 18
Line1 : Knotta Street
Line2 : Thrumpton-on-Thames
Postcode : SW1 2AA

最终目标是我可以以完全扁平的1:1格式输出到JSON

您只需要创建一个扁平的字典。您可以通过手动添加静态属性的键和值,然后在Address字典中动态添加现有的键值对来实现这一点。

就我个人而言,我建议创建一种方法,使数据变得平坦,并以JSON字符串的形式返回:

public class Person {
public string Name { get; set; }
public DateTime DOB { get; set; }
public Dictionary<string, string> Address { get; set; }
public string GetFlattenedJson() {
var result = new Dictionary<string, object> {
{ "Name", Name },
{ "DOB", DOB }
};
foreach (var datum in Address)
result.Add(datum.Key, datum.Value);
return JsonConvert.SerializeObject(result);
}
}

然后,当您需要扁平化的数据时,您只需使用该方法访问它:

var flatJson = myPerson.GetFlattenedJson();

澄清编辑:动态对象不是匿名对象,我用动态来演示是因为它是可用的最接近的解决方案——真正的匿名对象不能在运行时基于字典填充属性(除非引入了动态代码生成),只有动态对象支持这一点。


您需要使用dynamic来生成具有动态属性的匿名对象,通常在以下场景中使用ExpandoObject:

var person = new Person
{
Name = "Jim",
DOB = DateTime.UtcNow,
Address = new Dictionary<string, string>
{
{ "Number", "18" },
{ "Line1", "Knotta Street" },
{ "Line2", "Thrumpton-on-Thames" },
{ "Postcode", "SW1 2AA" },
}
};
dynamic flatterned = new ExpandoObject();
flatterned.Name = person.Name;
flatterned.DOB = person.DOB;
foreach (var kv in person.Address)
{
(flatterned as IDictionary<string, object>).Add(kv.Key, kv.Value);
}
Console.WriteLine(JsonConvert.SerializeObject(flatterned));

请注意,正如其他人所评论的那样,没有必要创建一个对象,然后序列化为JSON,但这是您所要求的,所以我认为它可以帮助您展示。

您可以使用ExpandoObjects轻松实现您正在寻找的内容。我写了一个扩展方法下面将与您的任何对象工作。然而,它只会使Dictionary<string,>目前为止。稍后会尝试更新。

public static class ExtentionClasses
{
public static dynamic Flatten<T>(this T item)
{
// Get all the properties not of type dictionary
var regularProps = item.GetType().GetProperties().Where(x => !typeof(Dictionary<string, string>).IsAssignableFrom(x.PropertyType));
var dictionaryProps = item.GetType().GetProperties().Where(x => typeof(Dictionary<string, string>).IsAssignableFrom(x.PropertyType));
var outputDict = new Dictionary<object, object>();
// Create a dynamic object
dynamic expando = new ExpandoObject();
// Add the regular properties
foreach (var prop in regularProps)
{
AddProperty(expando, prop.Name, prop.GetValue(item));
}
// Add the dictionary properties
foreach (var prop in dictionaryProps)
{
// convert to dict
var val = prop.GetValue(item);
var dict = (Dictionary<string, string>)val;
foreach(var keyValue in dict)
{
AddProperty(expando, keyValue.Key, keyValue.Value);
}
}
return expando;
}
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
} 

使用例子:

var person = new Person()
{
Name = "Jhon",
DOB = DateTime.Today,
Address = new Dictionary<string, string>()
{
{"Number", "18"},
{"Line1", "Knotta Street"},
{"Line2", "Thrumpton-on-Thames"},
{"Postcode", "SW1 2AA"}
}
};
var x = person.Flatten();
Console.WriteLine(x.Name);
Console.WriteLine(x.Postcode);

和结果:

Jhon
SW1 2AA

这样,您仍然可以在使用JsonConvert.SerializeObject(x)打印Json结果之前引用所有您想要的对象

最新更新