2016-11-09 3 views
3

У меня есть две json-маршаллируемые анонимные структуры.Как слить две структуры в Голанге?

a := struct { 
    Name string `json:"name"` 
}{"my name"} 

b := struct { 
    Description string `json:"description"` 
}{"my description"} 

Есть ли способ, чтобы объединить их в JSON, чтобы получить что-то вроде этого:

{ 
    "name":"my name", 
    "description":"my description" 
} 
+0

Что бы неправильно с 'fmt.Sprintf ("{\" Имя \ ":% ц, \" Описание \ ":% д}", a.Name, b.Description) '? Некоторые вещи ** ** требуют некоторого кодирования ... – Volker

ответ

5

Это немного запутанным, но я полагаю, вы могли бы сделать что-то вроде этого:

a := struct { 
     Name string `json:"name"` 
    }{"my name"} 

    b := struct { 
     Description string `json:"description"` 
    }{"my description"} 

    var m map[string]string 

    ja, _ := json.Marshal(a) 
    json.Unmarshal(ja, &m) 
    jb, _ := json.Marshal(b) 
    json.Unmarshal(jb, &m) 

    jm, _ := json.Marshal(m) 
    fmt.Println(string(jm)) 
+0

Это абсолютно то, что мне нужно! Спасибо! –

+0

Можете ли вы пометить ответ как принятый. Спасибо –

8

Вы можете embed both structs in another.

type name struct { 
    Name string `json:"name"` 
} 

type description struct { 
    Description string `json:"description"` 
} 

type combined struct { 
    name 
    description 
} 

Пакет JSON будет обрабатывать встроенные структуры типа подобных союзов, но это может стать неуклюжим довольно быстро.

+0

Нюанс в том, что структура анонимна. Я не знаю, что это имя. Поэтому я не могу использовать вложение. –

+1

@DmitryKapsamun: Разве вы не можете создать тип? Почему структура анонимна? –

3

Go - все о композиции над наследованием. К сожалению, вы используете анонимные структуры, но, учитывая, что вы явно пытаетесь JSon маршала их, вы лучше определений их типов:

type name struct { 
    Name string `json:"name"` 
} 
type desc struct { 
    Description string `json:"description"` 
} 

Вы можете инициализировать их точно так же, как вы» повторно в настоящее время делает, но вместо struct{<fields>}{init}, вы просто написать

a := name{"foo"} 
b := desc{"Description"} 

вы можете комбинировать их в любом случае вы хотите написать:

c := struct { 
    name 
    description 
}{a, b} 

Один выверт (что может сработать у Сначала вы должны привыкнуть к тому, когда вы создаете такие типы, как это вы инициализируете членов. Допустим, вы решили создать тип, который сочетает в себе два других структур:

type foo struct { 
    name 
    description 
} 

Вы не можете инициализировать его, как это:

o := foo{"Name value", "description value"} 

Go будет сетовать вы используете строку типа как тип name. Вы должны написать что-то вроде этого:

o := foo{ 
    name{"Name value"}, 
    description{Description: "Description val"},//optional with field names 
} 

рядный композит построен с использованием существующих объектов (ср c := struct{}{a, b}) делает это уже.
В зависимости от того, что вы пытаетесь сделать, это иногда проще написать что-то вроде этого:

func (s *MyCompositeType) CopyName(n name) { 
    s.Name = n.Name 
    //copy other fields 
} 

Это делает жизнь проще, когда вы вложенности составных типов несколько уровней вложенности.

+0

если вы маршали в json, как бы выглядела эта строка? – tutley

+0

@tutley: попробуйте на игровой площадке. Он будет/должен выглядеть так: '{" name ":" Name value "," description ":" Description val "}'. Другие типы не экспортируются, встроенные структуры –

+0

@tutley: подтверждено, проверьте вывод [здесь] (https://play.golang.org/p/9VV0394hKC) –

0

Вы можете объединить две структура, как это:

package main 

import (
    "fmt" 
    "encoding/json" 
) 


type b struct { 
    Name string `json:"name"` 
    Description string 
    Url string 
} 

type a struct { 
    *b 
    MimeType string `json:"mimeType"` 
} 

func main() { 
    bc := b{"test", "testdecription", "testurl"} 
    ac := a{nil, "jpg"} 

    ac.b = &bc 

    js, _ := json.Marshal(ac) 

    fmt.Println(string(js)) 
}