1
1
mirror of https://github.com/wader/fq.git synced 2024-12-18 10:52:44 +03:00
fq/internal/mapstruct/mapstruct.go
Mattias Wadman cae288e6be format,intepr: Refactor json, yaml, etc into formats also move out related functions
json, yaml, toml, xml, html, csv are now normal formats and most of them also particiate
in probing (not html and csv).

Also fixes a bunch of bugs in to/fromxml, to/fromjq etc.
2022-07-23 21:48:45 +02:00

79 lines
1.5 KiB
Go

// Package mapstruct maps struct <-> JSON using came case <-> snake case
// also set default values based on struct tags
package mapstruct
// TODO: implement own version as we don't need much?
import (
"regexp"
"strings"
"github.com/creasty/defaults"
"github.com/mitchellh/mapstructure"
)
var camelToSnakeRe = regexp.MustCompile(`[[:lower:]][[:upper:]]`)
// "AaaBbb" -> "aaa_bbb"
func CamelToSnake(s string) string {
return strings.ToLower(camelToSnakeRe.ReplaceAllStringFunc(s, func(s string) string {
return s[0:1] + "_" + s[1:2]
}))
}
func ToStruct(m any, v any) error {
_ = defaults.Set(v)
ms, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
MatchName: func(mapKey, fieldName string) bool {
return CamelToSnake(fieldName) == mapKey
},
TagName: "mapstruct",
Result: v,
})
if err != nil {
return err
}
if err := ms.Decode(m); err != nil {
return err
}
return nil
}
func CamelCase(v any) any {
switch vv := v.(type) {
case map[string]any:
n := map[string]any{}
for k, v := range vv {
n[CamelToSnake(k)] = CamelCase(v)
}
return n
case []any:
n := make([]any, len(vv))
for i, v := range vv {
n[i] = CamelCase(v)
}
return n
}
return v
}
func ToMap(v any) (map[string]any, error) {
m := map[string]any{}
ms, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &m,
})
if err != nil {
return nil, err
}
if err := ms.Decode(v); err != nil {
return nil, err
}
m, ok := CamelCase(m).(map[string]any)
if !ok {
panic("not map")
}
return m, nil
}