Предисловие: Я оптимизировал и улучшил решение ниже и выпустил его в виде библиотеки здесь: github.com/icza/dyno
. Нижеследующая функция convert()
доступна как dyno.ConvertMapI2MapS()
.
Проблема заключается в том, что если вы используете самый общий тип interface{}
для распаковать в тип по умолчанию, используемый github.com/go-yaml/yaml
пакета распаковать пар ключ-значение будет map[interface{}]interface{}
.
Первая идея будет использовать map[string]interface{}
:
var body map[string]interface{}
Но эта попытка терпит неудачу, если глубина YAML конфигурации больше, чем один, так как это body
карта будет содержать дополнительные карты, тип которых будет снова map[interface{}]interface{}
,
Проблема в том, что глубина неизвестна, и могут быть другие значения, чем карты, поэтому использование map[string]map[string]interface{}
не очень хорошо.
Жизнеспособной подход должен позволить yaml
распаковать в значение типа interface{}
, и пройти через результат рекурсивно и преобразовать каждый сталкивался map[interface{}]interface{}
к значению map[string]interface{}
. Обе карты и срезы должны обрабатываться.
Вот пример этого конвертера функции:
func convert(i interface{}) interface{} {
switch x := i.(type) {
case map[interface{}]interface{}:
m2 := map[string]interface{}{}
for k, v := range x {
m2[k.(string)] = convert(v)
}
return m2
case []interface{}:
for i, v := range x {
x[i] = convert(v)
}
}
return i
}
И использовать его:
func main() {
fmt.Printf("Input: %s\n", s)
var body interface{}
if err := yaml.Unmarshal([]byte(s), &body); err != nil {
panic(err)
}
body = convert(body)
if b, err := json.Marshal(body); err != nil {
panic(err)
} else {
fmt.Printf("Output: %s\n", b)
}
}
const s = `Services:
- Orders:
- ID: $save ID1
SupplierOrderCode: $SupplierOrderCode
- ID: $save ID2
SupplierOrderCode: 111111
`
Выход:
Input: Services:
- Orders:
- ID: $save ID1
SupplierOrderCode: $SupplierOrderCode
- ID: $save ID2
SupplierOrderCode: 111111
Output: {"Services":[{"Orders":[
{"ID":"$save ID1","SupplierOrderCode":"$SupplierOrderCode"},
{"ID":"$save ID2","SupplierOrderCode":111111}]}]}
Одно замечание: при переходе от YAML в формате JSON через карты Go вы потеряете порядок элементов, поскольку элементы (пары ключ-значение) на карте Go не упорядочены. Это может быть или не быть проблемой.
создать тело var следующим образом: 'body: = make (map [string] interface {})' –