package tool import ( "encoding/json" "fmt" "github.com/jedib0t/go-pretty/v6/table" "github.com/loveuer/nf/nft/log" "io" "os" "reflect" "strings" ) func TablePrinter(data any, writers ...io.Writer) { var w io.Writer = os.Stdout if len(writers) > 0 && writers[0] != nil { w = writers[0] } t := table.NewWriter() structPrinter(t, "", data) _, _ = fmt.Fprintln(w, t.Render()) } func structPrinter(w table.Writer, prefix string, item any) { Start: rv := reflect.ValueOf(item) if rv.IsZero() { return } for rv.Type().Kind() == reflect.Pointer { rv = rv.Elem() } switch rv.Type().Kind() { case reflect.Invalid, reflect.Uintptr, reflect.Chan, reflect.Func, reflect.UnsafePointer: case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Interface, reflect.String: w.AppendRow(table.Row{strings.TrimPrefix(prefix, "."), rv.Interface()}) case reflect.Array, reflect.Slice: for i := 0; i < rv.Len(); i++ { p := strings.Join([]string{prefix, fmt.Sprintf("[%d]", i)}, ".") structPrinter(w, p, rv.Index(i).Interface()) } case reflect.Map: for _, k := range rv.MapKeys() { structPrinter(w, fmt.Sprintf("%s.{%v}", prefix, k), rv.MapIndex(k).Interface()) } case reflect.Pointer: goto Start case reflect.Struct: for i := 0; i < rv.NumField(); i++ { p := fmt.Sprintf("%s.%s", prefix, rv.Type().Field(i).Name) field := rv.Field(i) //log.Debug("TablePrinter: prefix: %s, field: %v", p, rv.Field(i)) if !field.CanInterface() { return } structPrinter(w, p, field.Interface()) } } } func TableMapPrinter(data []byte) { m := make(map[string]any) if err := json.Unmarshal(data, &m); err != nil { log.Warn(err.Error()) return } t := table.NewWriter() addRow(t, "", m) fmt.Println(t.Render()) } func addRow(w table.Writer, prefix string, m any) { rv := reflect.ValueOf(m) switch rv.Type().Kind() { case reflect.Map: for _, k := range rv.MapKeys() { key := k.String() if prefix != "" { key = strings.Join([]string{prefix, k.String()}, ".") } addRow(w, key, rv.MapIndex(k).Interface()) } case reflect.Slice, reflect.Array: for i := 0; i < rv.Len(); i++ { addRow(w, fmt.Sprintf("%s[%d]", prefix, i), rv.Index(i).Interface()) } default: w.AppendRow(table.Row{prefix, m}) } }