Хранить несколько форматов сериализации в одном файле?АКА избегая сериализации наворотов для коллекций - PullRequest
0 голосов
/ 13 июня 2018

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

Скажем, у меня есть объект в памяти, которыйсодержит

  1. простых типов (например, имя, имя компьютера, дата создания, конфигурация и т. д.);и
  2. коллекция какого-либо вида (например, временные ряды статистических мер, например, скользящее среднее)

Для их сериализации имеет смысл

  1. для хранения простых типов в полнофункциональном формате сериализации, например, JSON, XML, YAML
  2. для хранения значений коллекции в файле CSV (для сохранения ненужного повторения тегов для каждой записи)

Но это значит, что у меня два файла.Лучше, если вся информация находится в одном файле, чтобы читатель мог однозначно понять, что (2) является результатом (1).Также легче поддерживать в файловой системе.

Я не хочу объединяться в BLOB, так как это потеряло бы удобочитаемость для человека.

Существует ли простая техника для объединения JSON в (1) и CSV для (2) в один файл?

Моим первым предположением было бы иметь (скажем) теги XML для разделения различных типов.например,

<SimpleTypes format="JSON">
   [JSON for simple types]
</SimpleTypes>
<Collection format="CSV" type="Dictionary" name="DailySalesTotal">
   [CSV for collection]
</Collection>
<Collection format="CSV" type="Dictionary" name="DailyFootfallInStore">
   [CSV for collection]
</Collection>

Затем просто откройте файл, проанализируйте XML на отдельные секции JSON и CSV и обработайте как обычно.

Это разумный подход?Есть риски?

Или есть где-нибудь библиотека для этого?Я использую C #, поэтому мне нужна библиотека .NET.

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

См. Это.

Создайте некоторую модель, используя XmlAttribute:

public class Foo
{
    [XmlAttribute]
    public string Bar { get; set; }
    [XmlAttribute]
    public List<int> List1 { get; set; }
    [XmlAttribute]
    public List<double> List2 { get; set; }
}

Сериализуйте ее:

var foo = new Foo
{
    Bar = "test",
    List1 = new List<int> { 1, 2, 3 },
    List2 = new List<double> { 0.1, 0.2, 0.3 }
};

var xs = new XmlSerializer(typeof(Foo));
var settings = new XmlWriterSettings { NewLineOnAttributes = true, Indent = true };
using (var xmlWriter = XmlWriter.Create(Console.Out, settings))
{
    xs.Serialize(xmlWriter, foo);
}

Console.WriteLine();

Результат компактен и вполне читабелен:

<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  Bar="test"
  List1="1 2 3"
  List2="0.1 0.2 0.3" />

Не изобретайте велосипед.

0 голосов
/ 21 июня 2018

Я нашел два компромиссных решения, которые хорошо работают.

  1. Сохраните файл для каждого формата сериализации с тем же именем файла и другим расширением, например <GUID>.csv <GUID>.xml <GUID.yaml> <GUID>.json
  2. Используйте подход YAML, как указано выше в flyx

Поэтому ответ flyx был принят в качестве ответа.Большое спасибо!

0 голосов
/ 13 июня 2018

Я оспариваю приведенные причины, по которым это имело бы смысл.

В основном, предлагаемое решение использования XML просто использует другой формат сериализации.Давайте посмотрим, сможем ли мы достичь заявленной цели:

, чтобы сохранить ненужное повторение тегов для каждой записи

с помощью YAML.Исходя из вашего примера, предположим, что у нас есть name и computer_name как «простые» данные, и список времен с некоторыми данными, прикрепленными как «данные сбора» .Тривиальный подход будет выглядеть примерно так:

name: My Name
computer_name: My Computer
collection:
- time: 1:30
  data: foo
- time: 2:20
  data: bar

Нет повторяющихся тегов.При десериализации в правильный тип YAML будет знать, что значение collection: будет списком точек данных без явных тегов.Однако у нас есть издержки, потому что мы каждый раз указываем имена полей time и data.Итак, давайте попробуем избавиться от них:

name: My Name
computer_name: My Computer
collection:
- [ 1:30, foo ]
- [ 2:20, bar ]

Большинство сред YAML предоставляют необходимые функции для десериализации этих последовательностей YAML в соответствующие классы данных.Мы все еще в пределах синтаксиса YAML.Теперь давайте посмотрим, сможем ли мы получить действительный CSV там:

name: My Name
computer_name: My Computer
collection: |
  1:30;foo
  2:20;bar

Используя скалярный литеральный блок YAML, мы теперь вводим данные сбора в виде скаляров, которые затем мы можем проанализировать с помощью синтаксического анализатора CSV.Мы даже можем дать указание нашей реализации YAML сделать это немедленно при обнаружении значения collection:.

Было бы более сложно сделать это с JSON в качестве основного формата сериализации, поскольку JSON не оснащен блочными скалярами,XML также будет работать, но сам по себе очень вздут.

Пока мы находимся в YAML, есть еще одно возможное решение: использовать маркер конца документа , чтобы сообщить синтаксическому анализатору YAML, чтоНа этом документ YAML заканчивается, и после него помещаются данные CSV.Подобные вещи делаются в Джекиле, чтобы отделить «YAML переднюю тему » от содержимого.Это будет выглядеть так:

name: My Name
computer_name: My Computer
...
1:30;foo
2:20;bar

... - маркер конца документа.Вместо этого Jekyll использует ---, что в соответствии со спецификацией положит там второй документ YAML, и я не знаю, почему они решили это сделать.... является более подходящим для спецификации способом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...