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  }