I'd like to add a method into the nested exported struct that is used in exported struct.
I have a []*ldap.Entry
type returned by the ldap.Search().Entries
ldap.Entry
type consists of Attributes []*EntryAttribute
. My goal is to add an extra method into the ldap.EntryAttribute
, e.g. MarshalJSON
I can add an extra code directly into the ldap
package and it will work as I expect. But it is a dirty way:
// EntryAttribute holds a single attribute
type newEntryAttribute struct {
// Name is the name of the attribute
Name string
// Values contain the string values of the attribute
Values []string
// ByteValues contain the raw values of the attribute
ByteValues [][]byte
}
// Print outputs a human-readable description
func (e EntryAttribute) MarshalJSON() ([]byte, error) {
b := newEntryAttribute(e)
b.ByteValues = nil
return json.Marshal(b)
}
How can I do that in a more elegant way?
The closest you can come is to create the method on your own type, which embeds the EntryAttribute type. Something like this:
package mine
import "github.com/go-ldap/ldap""
type EntryAttribute {
ldap.EntryAttribute
}
func (e EntryAttribute) MarshalJSON() ([]byte, error) {
// ...
}
But then, you must use your type, not the original type, everywhere in your program.
So far I have found the solution below. It is not elegant, but it doesn't require the package modification.
type myEntry struct {
*ldap.Entry
Attributes []*myEntryAttribute
}
type myEntryAttribute struct {
*ldap.EntryAttribute
}
func (a *myEntryAttribute) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Name string
Values []string
}{Name: a.Name, Values: a.Values})
}
func ldapEntry2myEntry(t interface{}) interface{} {
switch e := t.(type) {
case []*ldap.Entry:
var res []interface{}
for _, v := range e {
res = append(res, ldapEntry2myEntry(v))
}
return res
case *ldap.Entry:
var att []*myEntryAttribute
for _, a := range e.Attributes {
att = append(att, &myEntryAttribute{a})
}
return &myEntry{e, att}
}
return nil
}
... ... ...
data, err := json.Marshal(ldapEntry2myEntry(sr.Entries))
if err != nil {
log.Fatal("error")
}
fmt.Printf("%s
", data)
// or only one element
data, err := json.Marshal(ldapEntry2myEntry(sr.Entries[0]))
if err != nil {
log.Fatal("error")
}
fmt.Printf("%s
", data)