Распечатать объект с вложенными свойствами в виде строки пар ключ-значение, разделенных запятыми - PullRequest
0 голосов
/ 12 октября 2018

У меня есть 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.Тем не менее, это не выглядит как самый чистый / эффективный подход.

Ответы [ 4 ]

0 голосов
/ 12 октября 2018

Вы можете сделать это, используя пользовательский 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

0 голосов
/ 12 октября 2018

Вы должны реализовать отражение таким образом, чтобы оно могло углубиться в структуру вашего объекта, чтобы делать то, что вы хотите.Вот простая рекурсивная и универсальная адаптация к предоставленному вами коду.

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).

0 голосов
/ 12 октября 2018

Использование 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"
//  ]
//}
0 голосов
/ 12 октября 2018

Добавьте переопределение 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}";
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...