github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/json/marshal.go (about) 1 package json 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "strings" 8 ) 9 10 // NoData is a custom default error message when JSON marshaller returns nil 11 const NoData = "no data returned" 12 13 // Marshal is a wrapper around Go's JSON marshaller to prettify output 14 // depending on whether the target is a terminal or not. This is so that the 15 // output is human readable when output for a human but a single line machine 16 // readable formatting for better support with iteration / concatenation when 17 // output to system functions. 18 func Marshal(v interface{}, isTTY bool) (b []byte, err error) { 19 b, err = marshal(v, isTTY) 20 if err != nil && strings.Contains(err.Error(), "unsupported type: map[interface {}]interface {}") { 21 b, err = marshal(deinterface(v), isTTY) 22 } 23 24 if err != nil { 25 return 26 } 27 28 if string(b) == "null" { 29 b = make([]byte, 0) 30 return b, errors.New(NoData) 31 } 32 33 return 34 } 35 36 // marshal is a JSON marshaller which auto indents if output is a TTY 37 func marshal(v interface{}, isTTY bool) (b []byte, err error) { 38 //b, err = gojay.Marshal(v) 39 //if err == nil { 40 // return 41 //} 42 43 if isTTY { 44 b, err = json.MarshalIndent(v, "", " ") 45 return 46 } 47 48 b, err = json.Marshal(v) 49 return 50 } 51 52 // deinterface is used to fudge around the lack of support for 53 // `map[interface{}]interface{}` in Go's JSON marshaller. 54 func deinterface(v interface{}) interface{} { 55 switch t := v.(type) { 56 case map[interface{}]interface{}: 57 newV := make(map[string]interface{}) 58 for key := range t { 59 newV[fmt.Sprint(key)] = deinterface(t[key]) 60 } 61 //debug.Log(fmt.Sprintf("Deinterface: %T\n", t)) 62 return newV 63 64 case []interface{}: 65 newV := make([]interface{}, 0) 66 for i := range t { 67 newV = append(newV, deinterface(t[i])) 68 } 69 return newV 70 71 default: 72 //fmt.Printf("%T\n", t) 73 return v 74 } 75 }