我有一个Person
班:
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Line1 { get; set; }
public string Line2 { get; set; }
}
最终,我想将一个Person
实例打印为JSON,但我希望它是一个很大的键值对字符串,例如:
"Name:John,Surname:Doe,Line1:Infinite Loop,Line2:California"
请注意,在上面的示例中,我摆脱了实际的类名(即,它打印出Line1
而不是Address.Line1
)-我只关心所有名称/值对。
因此最终结果将是Person
s的数组:
"persons":[
"Name:John,Surname:Doe,Line1:Infinite Loop 1,Line2:California",
"Name:Jane,Surname:Doe,Line1:Infinite Loop 2,Line2:California"
]
作为起点,我尝试使用反射:
void Main()
{
var persons = new List<Person>();
persons.Add(new Person
{
Name = "John",
Surname = "Doe",
Address = new Address
{
Line1 = "Infinite Loop",
Line2 = "California"
}
});
foreach(var person in persons)
{
var properties = new List<string>();
foreach(var property in person.GetType().GetProperties())
{
properties.Add($"{property.Name}:{property.GetValue(person, null)}");
}
Console.WriteLine(string.Join(",", properties));
}
}
但是我在LINQPad中得到以下输出:
Name:John,Surname:Doe,Address:UserQuery+Address
我假设Address
未被正确迭代,因为它是Person
中的嵌套对象。即使这样,这也不是最干净/最有效的方法。
答案 0 :(得分:2)
您可以使用自定义JsonConverter
来做到这一点,就像这样:
class PersonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Person);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var pairs = JObject.FromObject(value)
.Descendants()
.OfType<JProperty>()
.Where(p => p.Value is JValue)
.Select(p => p.Name + ":" + p.Value);
writer.WriteValue(string.Join(",", pairs));
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后通过将转换器传递到JsonConvert.SerializeObject
来使用它,如下所示:
string json = JsonConvert.SerializeObject(obj, Formatting.Indented, new PersonConverter());
这是一个有效的演示:https://dotnetfiddle.net/L4YDsm
答案 1 :(得分:1)
向您的课程添加ToString
覆盖并以JSON形式返回字符串的集合。
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public Address Address { get; set; }
public override string ToString()
{
return $"Name:{Name},Surname:{Surname},Line1:{Address?.Line1},Line2:{Address?.Line2}";
}
}
答案 2 :(得分:1)
您必须以某种方式实现反射,使其可以更深入地进入对象的结构,以便执行所需的操作。这是对您提供的代码的简单递归和通用适应。
public static string GetRecursivePropertyValues(object obj)
{
var properties = new List<string>();
foreach (var property in obj.GetType().GetProperties())
{
object currentPropertyValue = property.GetValue(obj);
if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string))
properties.Add($"{property.Name}:{currentPropertyValue}");
else
{
var subProperties = GetRecursivePropertyValues(currentPropertyValue);
properties.Add(subProperties);
}
}
return string.Join(";", properties);
}
此实现首先验证是否用基本类型或string
(在C#中不视为基本类型)定义每个属性,并在这种情况下正常打印它们。否则,如果类型很复杂(例如,将其声明为Address
实例),它将以递归方式检索复杂对象的属性,并将其添加到结果字符串中。
您可以这样称呼它:
string propertiesStr = GetRecursivePropertyValues(person);
编辑:代码现在仅根据OP的要求展平对象(先前的代码示例使用了一些粗糙的JSON格式)。
答案 3 :(得分:1)
使用Newtonsoft.json
https://www.newtonsoft.com/json/help/html/SerializingJSON.htm
检查上面的链接...它将告诉您如何将对象序列化为json,需要注意的重要一点是,您需要将所有项添加到列表中,然后将列表序列化为json以达到预期的效果
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
有例子:
string output = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "ExpiryDate": "2008-12-28T00:00:00",
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}