Как HashSet сериализовать в json?

150
03 июня 2019, 02:50

Начну с кода:

Записываю все значения в файл таким способом ( всё что есть )

Класс BaseAccount:

public class BaseAccount
{
   [JsonProperty("Browser")]
   public string BrowserName { get; set; }
   [JsonProperty("Link")]
   public string Url { get; set; }
   [JsonProperty("Login")]
   public string User { get; set; }
   [JsonProperty("Password")]
   public string Pass { get; set; }
}

Класс GetPass:

private static HashSet<BaseAccount> _Logs = new HashSet<BaseAccount>();
public static void Inizialize()
{
   // большой кусок кода
    using (SQLiteDataReader reader = ComText.ExecuteReader())
    {
        while (reader.Read())
        {
            _Logs.Add(new BaseAccount
             {
               BrowserName = Name,
               Url = reader,
               User = reader,
               Pass = Pass
             });
        }
    }
   // Записываю в файл:
   foreach (BaseAccount ss in _Logs)
   {
       File.AppendAllText("pass.json", JsonConvert.SerializeObject(ss, Formatting.Indented));
   }
}

Но на выходе получаю не корректный формат json

{
  "Browser": "Opera",
  "Link": "https://account.mail.ru/login/",
  "Login": "MyRecovery",
  "Password": "Test"
}{
  "Browser": "Opera",
  "Link": "https://passport.yandex.ru/restoration/changepassword",
  "Login": "MyRecovery",
  "Password": "Test"
}{
  "Browser": "Opera",
  "Link": "https://e.mail.ru/messages/inbox/",
  "Login": "MyRecovery",
  "Password": "Test"
}

Вопрос: Как получить формат данного типа ?

{
  "browsers": {
    "chrome": [
      {
        "site": "http:\/\/google.ru",
        "login": "test",
        "password": "test"
      },
      {
        "site": "http:\/\/vk.ru",
        "login": "test",
        "password": "test"
      }
    ],
    "citrio": [
      {
        "site": "http:\/\/google.ru",
        "login": "test",
        "password": "test"
      }
    ],
    "opera": [
      {
        "site": "http:\/\/mail.ru",
        "login": "test",
        "password": "test"
      }
    ]
  }
}

[Update]

Добавил класс Wrapper:

public class Wrapper
{
  public HashSet<BaseAccount> Browsers { get; set; }
} 

Теперь в классе GetPass:

// За место HashSet был добавлен Dictionary
private static Dictionary<string, BaseAccount> _Logs = new Dictionary<string, BaseAccount>();
public static void Inizialize()
{
  using (var Connect = new SQLiteConnection(...)
  {
     Connect.Open();
     using (var ComText = new SQLiteCommand(CommandText, Connect))
     {
       using (var reader = ComText.ExecuteReader())
       {
          while (reader.Read())
          {
              // Но теперь данный метод добавления данных не работает 
              // Ошибка в _Logs.Add           
             _Logs.Add(new BaseAccount
             {
                BrowserName = Name,
                Url = reader,
                User = reader,
                Pass = Pass
             });
          }
       }  
     }
  }
}

Ошибка следующего вида:

Answer 1

Это потому что вы решили в цикле сами обходить элементы и каждый сериализовать отдельно. А вы должны сделать сериализацию только один раз - всего объекта. Не переживайте, json конвертер достаточно умный, чтобы самому обойти все ваши дочерние узлы.

var serialized = JsonConvert.SerializeObject(_Logs, Newtonsoft.Json.Formatting.Indented);

На выходе:

[
  {
    "Browser": "123",
    "Link": "http://ya.ru",
    "Login": "login1",
    "Password": "secret1"
  },
  {
    "Browser": "123",
    "Link": "http://ya.ru",
    "Login": "login2",
    "Password": "secret2"
  }
]

Пример полностью:

void Main()
{
    _Logs.Add(new BaseAccount{
        BrowserName = "123",
        Url = @"http://ya.ru",
        User = "login1",
        Pass = "secret1",
    });
    _Logs.Add(new BaseAccount
    {
        BrowserName = "123",
        Url = @"http://ya.ru",
        User = "login2",
        Pass = "secret2",
    });
    _Logs.Dump();
    var serialized = JsonConvert.SerializeObject(_Logs, Newtonsoft.Json.Formatting.Indented);
    serialized.Dump();
}
// Define other methods and classes here
private static HashSet<BaseAccount> _Logs = new HashSet<BaseAccount>();
public class BaseAccount
{
    [JsonProperty("Browser")]
    public string BrowserName { get; set; }
    [JsonProperty("Link")]
    public string Url { get; set; }
    [JsonProperty("Login")]
    public string User { get; set; }
    [JsonProperty("Password")]
    public string Pass { get; set; }
}

Это основное в чём была ваша ошибка. Также если нужно - можете дополнительный класс сделать:

public class Wrapper
{
    public HashSet<BaseAccount> Browsers { get; set; }
}

Сериализуя его

var b = new Wrapper { Browsers = _Logs };
var serialized2 = JsonConvert.SerializeObject(b, Newtonsoft.Json.Formatting.Indented);
serialized2.Dump();

получите на выходе:

{
  "Browsers": [
    {
      "Browser": "123",
      "Link": "http://ya.ru",
      "Login": "login1",
      "Password": "secret1"
    },
    {
      "Browser": "123",
      "Link": "http://ya.ru",
      "Login": "login2",
      "Password": "secret2"
    }
  ]
}
READ ALSO
Перезапуск службы

Перезапуск службы

В общем у меня есть свои собственные службы, например: Service1, Service2, Service3

163
Разбить строку оставив разделители

Разбить строку оставив разделители

Как из строки с предложением сделать массив слов, содержащий слова и пробелы в C#? Например, из строки "I walk with" должен получиться массив, содержащий...

147
Изменение шрифта отдельных слов в TreeView

Изменение шрифта отдельных слов в TreeView

Пишу программу, в которой необходимо в TreeView (в узлах всех уровней) выделять отдельные слова, указанные в словаре, жирным шрифтомПоискав решение...

138