Как представить значение + единицы в YAML?

Я разрабатываю новый формат конфигурации/данных, который будет в YAML. Многие из входов представляют собой значения int/float, с соответствующими единицами (например, литр, кварт, пинта, секунда, минута,...).

Я искал и читал, но все равно не могу понять: как лучше всего связать значение и unit с элементом конфигурации в YAML

Пример: Скажем, у меня есть список из нескольких напитков и (среди прочего), я хочу ввести их объем. Я могу думать о нескольких путях, но (по крайней мере, по-моему) ни один из них не идеален:

  • Требовать, чтобы все значения тома были введены в те же единицы.

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

  • Представьте значение с последовательностью томов и единиц. Пример:

    volume: [ 0.5, Gallons ]
    

    (Отображение будет работать также, хотя и более подробное). Последовательность может быть ОК, но я не уверен, что мне это нравится.

  • Используйте два значения "объем", один для значения, другой для единиц. Пример:

    volume_value: 0.5
    volume_units: Gallons
    

    Я думаю, что это не стартер. Вербальная, очень свободная ассоциация, подверженная ошибкам.

  • Используйте вместо этого строку и проанализируйте ее в приложении. Пример:

    volume: 0.5 Gallons
    

    Проще всего войти, и очень легко написать надежный парсер. Кажется, возможно, это немного взломать, хотя...

  • Теги приложения:

    volume: !gallons 0.5
    

    Не уверен в этом, так как я новичок в YAML и еще не очень хорошо разбираюсь в тегах. Синтаксис немного более хрупкий, возможно.


Итак, вопрос в следующем: в спецификации YAML или в наилучшей практике/соглашении defacto, существует ли конкретный способ представления значений + единиц? Является ли это одним из пяти перечисленных мной или чего-то еще, Я надеюсь, что есть "правильный ответ", чтобы оставаться в пределах рекомендаций по сайту.

Ответ 1

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

Если это так, расширьте безопасный загрузчик, предоставляемый вашей библиотекой, особенно если у вас нет полного контроля над созданием файла конфигурации. Если вы этого не сделаете и загрузите с помощью интерпретируемого языка (perl, python, ruby), вы рискуете создать специальную конфигурацию Crafter, на которой будет запущен любой код на компьютере.

Если теги не так, как вы хотите, есть еще одна альтернатива, которую вы не предложили, это вложенные сопоставления:

volume:
  Gallons: 0.5

или как однострочный:

volume: {Gallons: 0.5} 

или если вы предпочитаете:

volume: {0.5: Gallons}

Вышеизложенное потребует интерпретации после загрузки, как и ваши варианты 2, 3 и 4.


Поскольку комментарий @denian об использовании строк вместо floats имеет смысл, вы могли бы, если хотите, чтобы вы делали вычисления с использованием использования фракций !decimalfraction "0.5". В Python (PyYAML, ruamel.yaml) вы можете настроить загрузчик YAML, поэтому вам не нужно предоставлять кавычки вокруг 0.5, но это приведет к поплавкам all в файле, который будет загружен как строки (которые затем могут быть интерпретированы без ошибок округления с помощью создания экземпляра decimalfraction).

Ответ 2

Я не уверен в лучших практиках, но я бы использовал что-то вроде:

Coca Cola: {unit: 0.5}

Несколько более подробный вариант:

Pepsi: {value: 0.5, unit: gallons}

Другой вариант - использовать последовательности (раздел 2.4 спецификации YAML1.2)

-
   name: Coca Cola
   unit: gallons
   value: 0.5
-
   name: Pepsi
   unit: gallons
   value: 0.75

Проверьте спецификацию YAML, у нее действительно хорошие примеры. http://www.yaml.org/spec/1.2/spec.html

Ответ 3

Я получил это представление

volume : 0.5
volume_units : gallons

Потому что для меня более естественно использовать его вместе с предметами, которые не имеют никаких единиц. Например.

experiment_setup : 
  volume : 0.5 
  volume_units : gal
  vessel: cylinder
  color: red
  concentration: 10
  concentration_units : mol

Чем я могу называть конкретные элементы последовательно их естественными именами:

experiment_setup.volume
experiment_setup.color

а не непоследовательно, как

experiment_setup.volume.value
experiment_setup.color

или

experiment_setup.volume_value
experiment_setup.color