Я конвертирую JS API в Go. Я использую данные от третьей стороны, где иногда свойство является объектом с различным ключом, значением, а не массивом объектов (ключ, значение).
Итак, в моем интерфейсе, если это объект, он не будет отображаться, поэтому я конвертирую его в массив объектов.
В настоящее время в JS я делаю это:
if (!Array.isArray(data.attributes)) {
// convert into array of objects; only works for non separate key:key value:value
data.attributes = Object.entries(data.attributes).map(
([key, value]) => ({
type: key,
value: value,
})
);
}
data
— это свойство в ответе JSON, например:
{... data: { "attributes": [{...}{...}]}
Так что иногда атрибуты будут {... data: { "attributes": {name: "John", age: "20" }
:
Как бы я сделал что-то подобное в Go? Спасибо.
С объявленным типом вы можете реализовать интерфейс json.Unmarshaler
, чтобы настроить способ демаршалирования JSON.
В реализации вы можете проверить, представляют ли данные JSON объект или массив, просто взглянув на первый и последний байт, чтобы увидеть, являются ли они {
-и-}
или [
-и-]
. На основе этой проверки вы можете решить, как действовать дальше, вот пример:
type Attr struct {
Type string
Value interface{}
}
type AttrList []Attr
func (ls *AttrList) UnmarshalJSON(data []byte) error {
if len(data) == 0 { // nothing to do
return nil
}
switch last := len(data)-1; {
// is array?
case data[0] == '[' && data[last] == ']':
return json.Unmarshal(data, (*[]Attr)(ls))
// is object?
case data[0] == '{' && data[last] == '}':
var obj map[string]interface{}
if err := json.Unmarshal(data, &obj); err != nil {
return err
}
for key, value := range obj {
*ls = append(*ls, Attr{Type: key, Value: value})
}
return nil
}
return errors.New("unsupported JSON type for AttrList")
}