LINUX.ORG.RU

Какой выдумать или создать формат для конфигов?

 , , ,


1

3

Хочу для своего упражнения использовать yaml. Вроде голанг его умеет читать и писать. Что говорит на эту тему духовенство? Уместен ли такой формат или же лучше взять что-то другое?

json не хочу по той причине, что в него нельзя вставлять комментарии, xml слишком многословен.

==========================================

Решение: взят обычный json, который читает - пишет структуру. Для комментария в структуре предусмотрено специальное поле Comment. Это не так удобно, зато гомоиконно.

Если в конфиге задано поле, отсутствующее в структуре, например, если название поля написано с опечаткой, то будет ошибка чтения конфига. Это важно, поскольку толерантность многих программ к опечаткам в конфигах приводит к тому, что можно часами сидеть и искать ответ на вопрос «ну почему же это дерьмо не работает»?

Код такой:

package main

import (
	"strings"; "fmt"; "os"
	"encoding/json"
	"io/ioutil"
	// "github.com/flynn/json5"
)

type SecretConfigDataStruct struct {
	Comment       string
	RecieverEMail string
	SMTPServer    string
	SMTPUser      string
	SMTPPassword  string
	SenderEMail   string }

var SecretConfigData SecretConfigDataStruct

func (sds *SecretConfigDataStruct) SaveToFile(filename string) (err error) {
	var text []byte
	text, err = json.MarshalIndent(sds,""," ")
	if err != nil { return	}	
	err = ioutil.WriteFile(filename, text, 0600)
	return }

const ConfigFileName = "secret-data.config.json"

// for development
func saveSecretConfigDataExample() {
	sds := SecretConfigDataStruct{
		Comment:       "Example config file. Copy this one to the secret-data.config.json and edit",
		SenderEMail:   "den@example.net",
		RecieverEMail: "world@example.net",
		SMTPServer:    "smtp.example.net",
		SMTPUser:      "Кирилл",
		SMTPPassword:  "bla-bla-bla"}
	err := sds.SaveToFile(ConfigFileName + ".example")
	if err != nil {	panic(err)	}}

func loadSecretConfigData() (err error) {
	sds := &SecretConfigData
	fn := ConfigFileName
	if _, err = os.Stat(fn); os.IsNotExist(err) {
		fmt.Printf("No config file %s found. Create one by copying from %s.example\n",
			fn, fn)
		return	}
	var bytes []byte
	bytes, err = ioutil.ReadFile(fn)
	if err != nil {
		fmt.Printf("Unable to read config %s\n", fn)
		return	}
		dec := json.NewDecoder(strings.NewReader(string(bytes)))
		dec.DisallowUnknownFields() 
		err = dec.Decode(sds)
	if err != nil {
		fmt.Printf("Error reading config file %s: %#v\n", fn, err)
		return	}
	fmt.Printf("playWithSecretConfigData returned %#v\n", sds)
	return }

★★★★★

Ответ на: комментарий от RazrFalcon

Как решить TOML vs yaml? Вот нашёл старую тему:

В чем суть TOML?

Не сказать, чтобы обсуждение породило у меня большой энтузиазм в направлении TOML. Идея значимых отступов мне нравится, хотя многострочные строки в сочетании с отступами - это сомнительная идея. Придётся и на yaml подробнее посмотреть под критическим углом. Насчёт dhall - я сильно усомнюсь что Хаскель подходит для «нетехнических людей», которые там упомянуты.

den73 ★★★★★ ()
Ответ на: комментарий от RazrFalcon

Спасибо, я уже понял, что yaml сложный, и в этом его недостаток. Хотя я ещё посмотрю на историю. Вроде они при переходе с 1.1 на 1.2 упростили, а теперь уже 2.0.

Нашёл вот такую затею: https://habr.com/ru/post/248147/ В общем, чую, что придётся мне сделать свой язык конфигов, поэтому добавлю-ка я сюда тег «Яр».

den73 ★★★★★ ()
Ответ на: комментарий от den73

Но вообще это плохой конец дня. Я завязну в этом языке для конфигов. Похоже, что нужно сделать волевое усилие и применить json :( Но только это должен быть спец-json, позволяющий комментарии. А так, по идее, можно ещё сделать языком конфига ограниченное подмножество самого голанга, и/или то, что печатается по %#v. Есть ли такое где-нибудь, кто в курсе?

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от anonymous

json5 - классная штука, но у меня ругается на «неподдерживаемый протокол» на сайте. Нашёл на гитхабе. Похоже на приемлемое.

{
  // comments
  unquoted: 'and you can quote me on that',
  singleQuotes: 'I can use "double quotes" here',
  lineBreaks: "Look, Mom! \
No \\n's!",
  hexadecimal: 0xdecaf,
  leadingDecimalPoint: .8675309, andTrailing: 8675309.,
  positiveSign: +1,
  trailingComma: 'in objects', andIn: ['arrays',],
  "backwardsCompatible": "with JSON",
}
Т.е. у меня в хорошей степени проработанности гораздо более интересная штука (похожая на вышеупомянутый Tree), но сейчас задача не в том.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от Harald

Ну ты знаешь, после лиспа на ini-файлы - это, наверное, то же ощущение, что было у белоэмигрантов, успевших на последний пароход. Пока что всё не настолько плохо.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от Harald

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

Я читал что-то на тему того, что они там ехали чуть ли не стоя, и какать им приходилось чуть ли ни у всех на глазах. Ехали они довольно долго. Когда доехали, первым желанием каждого было больше никогда не видеть этих людей, соседей по пароходу.

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

den73 ★★★★★ ()

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

Томл фигня. Он пытается соответсвовать ини файлам, которые, по факту, тупо key-value списки. Зачастую, для конфигов требуются сложные объекты и массивы. В томле они реализованы криво, через избыточное дублирование префиксов ключей. + у стороннего человека будет снос башки, т.к. вроде обычный ини файл, но при этом какие-то странные заголовки в группах и другие непонятные моменты.

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

Json тоже не особо подходит. Проблема с комментариями (в стандарте специально их не сделали, но на практике борятся между собой js комментарии // и питонячьи #, но по факту ни те, ни другие не валидны без специальной обработки. + те же проблемы с многострочными строками.

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

Deleted ()

Главное, чтобы был тьюринг-полный и контекстно-зависимый. А вдруг я захочу в тетрис поиграть, а конфиг не позволяет.

anonymous ()
Ответ на: комментарий от annulen

UCL для моей задачи явно переусложнён, причём некоторые вещи выглядят ошибками проектирования, например, превращение повторяющихся ключей в массивы. Также идея о допустимости запятой в конце перечисления для меня выглядит вопиющей неграмотностью, несмотря на её популярность в последнее время.

den73 ★★★★★ ()
Ответ на: комментарий от den73

Зато программировать не просто и не удобно, а у меня всего лишь упражнение.

Да ладно, очень просто. Для C есть bison, для всех остальных языков комбинаторные парсеры.

kirk_johnson ★☆ ()
Последнее исправление: kirk_johnson (всего исправлений: 1)

Если конфиг сложный, то лучше если это будет какой-то язык программирования. В идеале --- тот, на котором написана программа. В go ведь нет eval? Тогда lua или guile.

Jini ★★ ()
Ответ на: комментарий от den73

ОФФТОП

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

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

yetanother ()

Если конфиг предусматривает редактирование - человеком, то только читаемый формат.
Иначе - можешь брать любой, хоть чисто бинарный и шифрованный.

Atlant ★★★★★ ()
Последнее исправление: Atlant (всего исправлений: 1)
Ответ на: комментарий от Novell-ch

As an alternative, lists of objects can be created with repeated blocks, using this structure

service {
    key = "value"
}

service {
    key = "value"
}

Вот это мне не нравится совсем. Типичная опечатка превращается в валидную структуру данных.

den73 ★★★★★ ()