Ваше решение конвертирует значения только на "верхнем" уровне.Если значение также является картой (вложенная карта), ваше решение не преобразует их.
Кроме того, вы только «копируете» значения с помощью клавиш string
, остальное будет исключено из карты результатов.
Вот функция, которая рекурсивно конвертирует вложенные карты:
func convert(m map[interface{}]interface{}) map[string]interface{} {
res := map[string]interface{}{}
for k, v := range m {
switch v2 := v.(type) {
case map[interface{}]interface{}:
res[fmt.Sprint(k)] = convert(v2)
default:
res[fmt.Sprint(k)] = v
}
}
return res
}
Тестирование:
m := map[interface{}]interface{}{
1: "one",
"two": 2,
"three": map[interface{}]interface{}{
"3.1": 3.1,
},
}
m2 := convert(m)
data, err := json.Marshal(m2)
if err != nil {
panic(err)
}
fmt.Println(string(data))
Вывод (попробуйте на Go Playground ):
{"1":"one","three":{"3.1":3.1},"two":2}
Несколько замечаний:
Чтобы скрыть interface{}
ключи, я использовал fmt.Sprint()
, который будет обрабатывать всетипы.switch
может иметь выделенный регистр string
для ключей, которые уже имеют значения string
, чтобы избежать вызова fmt.Sprint()
.Это исключительно из соображений производительности, результат будет таким же.
Вышеприведенная функция convert()
не разбивает на части.Так, например, если карта содержит значение, представляющее собой срез ([]interface{}
), который также может содержать карты, они не будут преобразованы.Для полного решения см. Библиотеку ниже.
Существует библиотека github.com/icza/dyno
, которая имеет оптимизированную встроенную поддержку для этого (раскрытие: IЯ автор).Использование dyno
выглядит следующим образом:
var m map[interface{}]interface{} = ...
m2 := dyno.ConvertMapI2MapS(m)
dyno.ConvertMapI2MapS()
также выполняет преобразование карт в []interface{}
срезов.
Также смотрите возможные дубликаты: Конвертируйте yaml в json без структуры