Documentation ¶
Index ¶
- func FillStruct(obj interface{}, mapped Mapped) error
- func FillStructByTags(obj interface{}, mapped Mapped, tagname string) error
- func FillStructDeflate(obj interface{}, mapped Mapped, tagname string) error
- func SQLScan(row SQLScanner, obj interface{}, tag string, x ...string) error
- func SetFieldFromTag(obj interface{}, tagName, tagValue string, value interface{}, ...) (bool, error)
- type MapDecoder
- type MapEncoder
- type Mapped
- type SQLScanner
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FillStruct ¶
FillStruct acts just like “json.Unmarshal“ but works with “Mapped“ instead of bytes of char that made from “json“.
Example ¶
mapped := MapFields(&sourceobj) sinked := sink{} err := FillStruct(&sinked, mapped) if err != nil { panic(err) } fmt.Println(sinked)
Output: {source the origin}
func FillStructByTags ¶
FillStructByTags fills the field that has tagname and tagvalue instead of Mapped key name.
Example ¶
maptags := MapTags(&sourceobj, "json") for k, v := range maptags { if vt, ok := v.(time.Time); ok { fmt.Printf("maptags[%s]: %s\n", k, vt.Format(time.RFC3339)) } else { fmt.Printf("maptags[%s]: %v\n", k, v) } } diffsink := differentSink{} err := FillStructByTags(&diffsink, maptags, "json") if err != nil { panic(err) } fmt.Println(diffsink.DiffLabel) fmt.Println(diffsink.NiceInfo) fmt.Println(diffsink.Version) fmt.Println(diffsink.Toki) fmt.Println(*diffsink.Addr)
Output: maptags[label]: source maptags[info]: the origin maptags[version]: 1 maptags[tomare]: 2000-01-01T00:00:00Z maptags[address]: hello異世界 source the origin 0001-01-01 00:00:00 +0000 UTC hello異世界
func FillStructDeflate ¶
FillStructDeflate fills the nested object from flat map. This works by filling outer struct first and then checking its subsequent object fields.
Example (FromJson) ¶
type ( nest2 struct { N2FieldFloat float64 `json:"nested2_flt"` N2FieldStr string `json:"nested2_str"` } nest1 struct { N1FieldFloat float64 `json:"nested1_flt"` N1FieldStr string `json:"nested1_str"` Nest2 *nest2 `json:"nested2"` } outerobj struct { FieldFloat float64 `json:"field_flt"` FieldStr string `json:"field_str"` Nest1 nest1 `json:"nested1"` } ) rawb := ` { "field_str": "555", "field_flt": 5, "nested1_flt": 515, "nested1_str": "515", "nested2_flt": 525, "nested2_str": "525" }` var m map[string]interface{} fmt.Println(json.Unmarshal([]byte(rawb), &m)) var tgt outerobj fmt.Println("error result fill struct deflate:", FillStructDeflate(&tgt, m, "json")) fmt.Printf("%#v\n", tgt.FieldFloat) fmt.Printf("%#v\n", tgt.FieldStr) fmt.Printf("%#v\n", tgt.Nest1.N1FieldFloat) fmt.Printf("%#v\n", tgt.Nest1.N1FieldStr) fmt.Printf("%#v\n", tgt.Nest1.Nest2.N2FieldFloat) fmt.Printf("%#v\n", tgt.Nest1.Nest2.N2FieldStr)
Output: <nil> error result fill struct deflate: <nil> 5 "555" 515 "515" 525 "525"
func SQLScan ¶
func SQLScan(row SQLScanner, obj interface{}, tag string, x ...string) error
SQLScan is the function that will map scanning object based on provided field name or field tagged string. The tags can receive the empty string "" and then it will map the field name by default.
Example (AllFields) ¶
currtime := time.Now() dr := createDummyRow(currtime) result := dummyValues{} if err := SQLScan(dr, &result, ""); err != nil { fmt.Println("Error happened!") return } fmt.Printf("NullString is Valid? %t\n", result.NullString.Valid) fmt.Printf("result.NullString is %s\n", result.NullString.String) fmt.Printf("NullTime is Valid? %t\n", result.NullTime.Valid) fmt.Printf("result.NullTime.Time.Equal(dr.Values.NullTime.Time)? %t\n", result.NullTime.Time.Equal(dr.Values.NullTime.Time)) fmt.Printf("result.Uint64 == %d\n", result.Uint64)
Output: NullString is Valid? true result.NullString is hello 異世界 NullTime is Valid? true result.NullTime.Time.Equal(dr.Values.NullTime.Time)? true result.Uint64 == 5
Example (SuppliedFields) ¶
currtime := time.Now() dr := createDummyRow(currtime) result := dummyValues{} if err := SQLScan(dr, &result, "", /* This is the tag, since we don't have so put it empty to match the field name */ /* Below arguments are variadic and we only take several fields from all available dummyValues */ "Int32", "Uint64", "Bool", "Bytes", "NullString", "NullTime"); err != nil { fmt.Println("Error happened!") return } fmt.Printf("NullString is Valid? %t\n", result.NullString.Valid) fmt.Printf("NullTime is Valid? %t\n", result.NullTime.Valid) fmt.Printf("result.NullTime.Time.Equal(dr.Values.NullTime.Time)? %t\n", result.NullTime.Time.Equal(dr.Values.NullTime.Time)) fmt.Printf("result.Uint64 == %d\n", result.Uint64)
Output: NullString is Valid? true NullTime is Valid? true result.NullTime.Time.Equal(dr.Values.NullTime.Time)? true result.Uint64 == 5
func SetFieldFromTag ¶
Types ¶
type MapDecoder ¶
type MapDecoder interface {
MapDecode(interface{}) error
}
Example ¶
var err error var smap map[string]interface{} type MapDecoderExample struct { Data sometype `json:"data"` } smap = map[string]interface{}{"data": "hello"} var s MapDecoderExample err = FillStructByTags(&s, smap, "json") if err != nil { fmt.Println(err) return } fmt.Println(s.Data.Value) type map2 struct { Data *sometype `json:"data"` } smap = map[string]interface{}{"data": "hello2"} var s2 map2 // s2 := map2{Data: &sometype{}} err = FillStructByTags(&s2, smap, "json") if err != nil { fmt.Println(err) return } fmt.Println(s2.Data.Value)
Output: hello hello2
type MapEncoder ¶
type MapEncoder interface {
MapEncode() (interface{}, error)
}
Example ¶
type MapEncoderExample struct { Data sometype `json:"data"` } type map2 struct { Data *sometype `json:"data"` } s := MapEncoderExample{Data: sometype{Value: "hello"}} smap := MapTags(&s, "json") str, ok := smap["data"].(string) if !ok { fmt.Println("Not ok!") return } fmt.Println(str) s2 := map2{Data: &sometype{Value: "hello2"}} smap = MapTags(&s2, "json") str, ok = smap["data"].(string) if !ok { fmt.Println("Not ok!") return } fmt.Println(str)
Output: hello hello2
type Mapped ¶
type Mapped map[string]interface{}
Mapped simply an alias
func MapFields ¶
func MapFields(x interface{}) Mapped
MapFields maps between struct to mapped interfaces{}. The argument must be (zero or minterface{} pointers to) struct or else it will be ignored. Now it's implemented as MapTags with empty tag "".
Only map the exported fields.
Example ¶
mapped := MapFields(sourceobj) printIfNotExists(mapped, "Label", "Info", "Version")
Output:
func MapTags ¶
MapTags maps the tag value of defined field tag name. This enable various field extraction that will be mapped to mapped interfaces{}.
Example (Basic) ¶
ptrSourceObj := &sourceobj maptags := MapTags(&ptrSourceObj, "json") printIfNotExists(maptags, "label", "info", "version")
Output:
Example (Nested) ¶
nestedSource := differentSourceSink{ Source: sourceobj, DiffSink: differentSink{ DiffLabel: "nested diff", NiceInfo: "nested info", Version: "next version", Toki: toki, Addr: &hello, }, } // this part illustrates that MapTags or any other Map function // accept arbitrary pointers to struct. ptrNestedSource := &nestedSource ptr2NestedSource := &ptrNestedSource ptr3NestedSource := &ptr2NestedSource nestedMap := MapTags(&ptr3NestedSource, "json") for k, v := range nestedMap { fmt.Println("top key:", k) for kk, vv := range v.(Mapped) { if vtime, ok := vv.(time.Time); ok { fmt.Println(" nested:", kk, vtime.Format(time.RFC3339)) } else { fmt.Println(" nested:", kk, vv) } } fmt.Println() }
Output: top key: source nested: label source nested: info the origin nested: version 1 nested: tomare 2000-01-01T00:00:00Z nested: address hello異世界 top key: differentSink nested: label nested diff nested: info nested info nested: unversion next version nested: doki 2000-01-01T00:00:00Z nested: address hello異世界
Example (TwoTags) ¶
general := generalFields{ Name: "duran", Rank: "private", Code: 1337, nickname: "drone", } mapjson := MapTags(&general, "json") printIfNotExists(mapjson, "name", "rank", "code") mapapi := MapTags(&general, "api") printIfNotExists(mapapi, "general_name", "general_rank", "general_code")
Output:
func MapTagsFlatten ¶
MapTagsFlatten is to flatten mapped object with specific tag. The limitation of this flattening that it can't have duplicate tag name and it will give incorrect result because the older value will be written with newer map field value.
Example ¶
type ( Last struct { Final string `json:"final"` Destination string } Lv3 struct { Lv3Str string `json:"lv3str"` *Last `json:"last"` Lv3Dummy string } Lv2 struct { Lv2Str string `json:"lv2str"` Lv3 `json:"lv3"` Lv2Dummy string } Lv1 struct { Lv2 Lv1Str string `json:"lv1str"` Lv1Dummy string } ) obj := Lv1{ Lv1Str: "level 1 string", Lv1Dummy: "baka", Lv2: Lv2{ Lv2Dummy: "bakabaka", Lv2Str: "level 2 string", Lv3: Lv3{ Lv3Dummy: "bakabakka", Lv3Str: "level 3 string", Last: &Last{ Final: "destination", Destination: "overloop", }, }, }, } for k, v := range MapTagsFlatten(&obj, "json") { fmt.Printf("key: %s, value: %v\n", k, v) }
Output: key: final, value: destination key: lv1str, value: level 1 string key: lv2str, value: level 2 string key: lv3str, value: level 3 string
func MapTagsWithDefault ¶
MapTagsWithDefault maps the tag with optional fallback tags. This to enable tag differences when there are only few difference with the default “json“ tag.
Example ¶
type higherCommon struct { General generalFields `json:"general"` Communality string `json:"common"` Available bool `json:"available" api:"is_available"` } rawjson := []byte(`{ "general": { name: "duran", rank: "private", code: 1337, }, "common": "rare", "available": true }`) hc := higherCommon{} _ = json.Unmarshal(rawjson, &hc) maptags := MapTagsWithDefault(&hc, "api", "json") printIfNotExists(maptags, "available")
Output: available : not exists
type SQLScanner ¶
type SQLScanner interface {
Scan(dest ...interface{}) error
}
SQLScanner is the interface that dictate any type that implement Scan method to be compatible with sql.Row Scan method.