Commits
Diff
diff --git a/output/main.go b/output/main.go
index 030707e..d91b72a 100644
--- a/output/main.go
+++ b/output/main.go
@@ -146,2 +146 @@ func JSON(v interface{}) string {
- b, e := json.Marshal(v)
- fmt.Println(e)
+ b, _ := json.Marshal(v)
package output
import (
"bytes"
"encoding/json"
"encoding/xml"
"fmt"
"reflect"
"strings"
"text/template"
)
// TextEncoder converts a struct to plain text based on struct tags, handling nested structs with indentation.
func Text(v interface{}) string {
var result strings.Builder
val := reflect.ValueOf(v)
typ := val.Type()
// Handle pointer types
if val.Kind() == reflect.Ptr {
val = val.Elem()
typ = val.Type()
}
processValue(val, typ, 0, &result)
return result.String()
}
func processValue(val reflect.Value, typ reflect.Type, indentLevel int, result *strings.Builder) {
indent := strings.Repeat("\t", indentLevel)
switch val.Kind() {
case reflect.Struct:
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
fieldType := typ.Field(i)
// Get the 'text' tag, fallback to 'xml' tag if not present
tag := fieldType.Tag.Get("text")
if tag == "" {
tag = fieldType.Tag.Get("xml")
}
// Skip if tag is "-"
if tag == "-" {
continue
}
// Use field name if no tag
fieldName := fieldType.Name
if tag == "" {
tag = fieldName
}
currentTag := tag
// Handle slices
if field.Kind() == reflect.Slice {
for j := 0; j < field.Len(); j++ {
item := field.Index(j)
itemType := item.Type()
if item.Kind() == reflect.Struct || (item.Kind() == reflect.Ptr && item.Elem().Kind() == reflect.Struct) {
// Nested struct or pointer to struct in slice
if strings.Contains(tag, "omitempty") && isEmptyValue(item) {
continue
} else {
currentTagWithoutOmit := strings.ReplaceAll(currentTag, ",omitempty", "")
result.WriteString(fmt.Sprintf("%s%s:\n", indent, currentTagWithoutOmit))
if item.Kind() == reflect.Ptr {
processValue(item.Elem(), itemType.Elem(), indentLevel+1, result)
} else {
processValue(item, itemType, indentLevel+1, result)
}
}
} else {
lines := strings.TrimSpace(fmt.Sprintf("%v", item.Interface()))
if strings.Contains(tag, "omitempty") && lines == "" {
continue
} else {
currentTagWithoutOmit := strings.ReplaceAll(currentTag, ",omitempty", "")
result.WriteString(fmt.Sprintf("%s%s: %v\n", indent, currentTagWithoutOmit, lines))
}
}
}
} else if field.Kind() == reflect.Struct || (field.Kind() == reflect.Ptr && field.Elem().Kind() == reflect.Struct) {
// Nested struct or pointer to struct
if strings.Contains(tag, "omitempty") && isEmptyValue(field) {
continue
} else {
currentTagWithoutOmit := strings.ReplaceAll(currentTag, ",omitempty", "")
result.WriteString(fmt.Sprintf("%s%s:\n", indent, currentTagWithoutOmit))
fieldTypeToPass := fieldType.Type
fieldValToPass := field
if field.Kind() == reflect.Ptr {
fieldTypeToPass = fieldType.Type.Elem()
fieldValToPass = field.Elem()
}
processValue(fieldValToPass, fieldTypeToPass, indentLevel+1, result)
}
} else {
// Basic type
lines := strings.TrimSpace(fmt.Sprintf("%v", field.Interface()))
if strings.Contains(tag, "omitempty") && lines == "" {
continue
} else {
currentTagWithoutOmit := strings.ReplaceAll(currentTag, ",omitempty", "")
result.WriteString(fmt.Sprintf("%s%s: %v\n", indent, currentTagWithoutOmit, lines))
}
}
}
default:
result.WriteString(fmt.Sprintf("%v", val.Interface()))
}
}
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
if !isEmptyValue(v.Field(i)) {
return false
}
}
return true
}
return false
}
func JSON(v interface{}) string {
b, e := json.Marshal(v)
fmt.Println(e)
return string(b)
}
func XML(v interface{}) string {
b, _ := xml.Marshal(v)
return string(b)
}
func FormatPath(path string, data interface{}) string {
var output bytes.Buffer
templ := template.Must(template.New("fp").Parse(path))
templ.Execute(&output, data)
return output.String()
}