Serializacja listy do stringu [C#]

0

Zastanawiam się jak najbardziej optymalnie rozwiązać pewien problem:

Jest sobie lista obiektów typu A (List<A>), gdzie:

      string name
      string value
}```
(uwaga: ani *name *ani *value *nie jest unikatowe, może się powtarzać, i ważne aby zachować **kolejność **listy)

I teraz chciałbym z tej listy zrobić stringa (by przechować w bazie danych) i by potem można było go wydajnie przeczytać.

Rozwiązanie (?):
Zrobiłem to tak, że serializowałem do JSON'a. Tyle, że potem ten string znowu jest serializowany przed zapisem i dziwne to wychodzi.
Mogę zrobić tak, że po kolei dodawać do stringa "NAME: cos, VALUE: cos" i potem sobie czytać stringa po słowach kluczowych NAME i VALUE.
Pytanie czy można zrobić to lepiej/ łatwiej?
1

A nie lepiej zapisać te listę wprost w tabeli utworzonej dla listy?

0

Serializacja do JSON to chyba najprostsze rozwiązanie w takim przypadku. Nie rozumiem tylko o jakiej ponownej serializacji przed zapisem piszesz.

PS. Nie ma czegoś takiego "najbardziej optymalnie". Optymalny to najlepszy w danych warunkach, zwrot "najbardziej najlepszy" nie ma sensu.

0

@jacek.placek
@somekind

Nie mam wpływu na to co dzieje się potem. Później jest coś takiego, że jest sobie lista

var list = new List<KeyValuePair<string, string>() { 
    new KeyValuePair<string, int>("A", "A"),
    new KeyValuePair<string, int>("B", "B"),
    new KeyValuePair<string, int>("MÓJ_PARAMETR", "XXXXXXX"),
}
JsonConvert.SerializeObject(list);

Jedyne co ja mam zrobić to w miejsce "XXXXXX" wstawić wartość, którą chcę przechowa, by potem ją przeczytać.
I jako string muszę właśnie jakoś zapisać wcześniej wspomnianą listę:

List<A>
class A { 
    string name 
   string value 
}
0

I najpierw zrobiłem tak, że na swojej liście też wywołałem

JsonConvert.SerializeObject(Lista<A>);

I otrzymałem ten string które wpisałem w miejsce "XXXXX", ale to nie działa ok, bo potem kolejna serializacja, baza tego nie łyka dobrze.
Myślalem o czyms takim plus minus:

            string XXX = ""
            var lista = new List<A>(wszystkie_elementy)
            foreach(var element in lista) {
                XXX += "NAME:"
                XXX += element.name
                XXX += "VALUE:"
                XXX += element.value
            }
            // w XXX zapisane wszystkie elementy

I potem przy odczycie na podstawie "znaczników" NAME i VALUE wyciągnąc te wartości, tylko czy to jest optymalne :/

2

Ale co to znaczy, że "baza nie łyka dobrze"? Jeśli pole jest dwukrotnie zserializowane, to po prostu przy odczytywaniu trzeba je dwukrotnie zdeserializować.

A jeśli koniecznie chcesz sobie z tego zrobić jeden string, to Twoja metoda na pewno nie jest optymalna, bo każda konkatenacja powoduje alokację nowego obiektu stringa ze skopiowaną zawartością. Ty masz 4 konkatenacje dla każdego elementu listy.
Jeśli chcesz budować duże stringi z wielu małych, to powinieneś użyć klasy StringBuilder, np. tak:

var sb = new StringBuilder();
foreach (var element in lista)
{
    sb.Append($"NAME:{element.Name}VALUE:{element.Value}");
}
var result = sb.ToString();
0

Niestety dokładnie tak, baza dobrze tego nie łyka. W dużym skrócie podwójna serializacja dodaje dużo znaków escapowania, przez co część informacji się urywa. I o ile potem pierwsze deserializacja jest ok, to bywa, że na drugiej się wywala, bo ubyło parę escape znaków.

I dzięki za wskazówkę ze StringBuilderem. Czy jeszcze jakaś wskazówka jak to optymalnie potem przeczytać?
(ogólnie dodam, że jest programistą Androida - Java, Kotlin, no ale muszę niestety ruszyć trochę backendu w C#, a tutaj malutka wiedza)

0

Aaah, dobra. Ty pytałeś co to znaczy, że baza dobrze tego nie łyka. Chodzi wlasnie o znaki escapowania. Przy zapisie baza nie zapisuje wszystkich, przez co tak jak wczesniej wspomnialem pierwsze deserializacja ok, druga juz może się wykrzaczyć

0

Dziwna ta baza. Tzn. pewnie nie baza tylko zapis do niej macie źle zaimplementowany, prawdopodobnie właśnie brakuje jakiegoś enkodowania. Ale mniejsza z tym.
Odczyt można zrobić np. tak:

var result = new List<A>();
var split = input.Split(new string[] { "NAME:", "VALUE:" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < split.Length; i = i + 2)
{
    result.Add(new A { Name = split[i], Value = split[i + 1] });
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1