Skip to content

Commit 310e83a

Browse files
committed
feat: add convertion function for proper handling of byte arrays to base64 strings
1 parent 7935d9e commit 310e83a

File tree

2 files changed

+172
-0
lines changed

2 files changed

+172
-0
lines changed

core/utils/utils.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package utils
22

3+
import (
4+
"encoding/base64"
5+
"encoding/json"
6+
)
7+
38
// Ptr Returns the pointer to any type T
49
func Ptr[T any](v T) *T {
510
return &v
@@ -13,3 +18,50 @@ func Contains[T comparable](slice []T, element T) bool {
1318
}
1419
return false
1520
}
21+
22+
// ConvertForYAML converts a struct to a map with byte arrays converted to base64 strings
23+
// for proper YAML marshaling. This handles the case where []byte fields need to be
24+
// displayed as base64 strings in YAML output instead of byte arrays.
25+
func ConvertForYAML(obj interface{}) (map[string]interface{}, error) {
26+
if obj == nil {
27+
return nil, nil
28+
}
29+
30+
// Marshal to JSON first to get the correct structure
31+
jsonData, err := json.Marshal(obj)
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
var result map[string]interface{}
37+
if err := json.Unmarshal(jsonData, &result); err != nil {
38+
return nil, err
39+
}
40+
41+
// Convert byte arrays to base64 strings
42+
convertByteArraysToBase64(result)
43+
44+
return result, nil
45+
}
46+
47+
// convertByteArraysToBase64 recursively converts []byte values to base64 strings
48+
func convertByteArraysToBase64(data interface{}) {
49+
switch v := data.(type) {
50+
case map[string]interface{}:
51+
for key, value := range v {
52+
if byteArray, ok := value.([]byte); ok {
53+
v[key] = base64.StdEncoding.EncodeToString(byteArray)
54+
} else {
55+
convertByteArraysToBase64(value)
56+
}
57+
}
58+
case []interface{}:
59+
for i, value := range v {
60+
if byteArray, ok := value.([]byte); ok {
61+
v[i] = base64.StdEncoding.EncodeToString(byteArray)
62+
} else {
63+
convertByteArraysToBase64(value)
64+
}
65+
}
66+
}
67+
}

core/utils/utils_test.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package utils
22

33
import (
4+
"encoding/base64"
45
"testing"
56
)
67

@@ -37,3 +38,122 @@ func TestContainsInt(t *testing.T) {
3738
t.Fatalf("Should not be contained")
3839
}
3940
}
41+
42+
// Test struct for YAML conversion testing
43+
type TestServer struct {
44+
Name string `json:"name"`
45+
UserData *[]byte `json:"userData,omitempty"`
46+
Data []byte `json:"data,omitempty"`
47+
}
48+
49+
func TestConvertForYAML(t *testing.T) {
50+
// Test with nil input
51+
result, err := ConvertForYAML(nil)
52+
if err != nil {
53+
t.Fatalf("Expected no error for nil input, got: %v", err)
54+
}
55+
if result != nil {
56+
t.Fatalf("Expected nil result for nil input, got: %v", result)
57+
}
58+
59+
// Test with server containing byte arrays
60+
userData := []byte("hello world")
61+
data := []byte("test data")
62+
63+
server := TestServer{
64+
Name: "test-server",
65+
UserData: &userData,
66+
Data: data,
67+
}
68+
69+
result1, err := ConvertForYAML(server)
70+
if err != nil {
71+
t.Fatalf("Expected no error, got: %v", err)
72+
}
73+
74+
// Check that UserData is converted to base64
75+
if userDataStr, ok := result1["userData"].(string); !ok {
76+
t.Fatalf("Expected userData to be a string, got: %T", result1["userData"])
77+
} else {
78+
expected := base64.StdEncoding.EncodeToString(userData)
79+
if userDataStr != expected {
80+
t.Fatalf("Expected userData to be %s, got: %s", expected, userDataStr)
81+
}
82+
}
83+
84+
// Check that Data is converted to base64
85+
if dataStr, ok := result1["data"].(string); !ok {
86+
t.Fatalf("Expected data to be a string, got: %T", result1["data"])
87+
} else {
88+
expected := base64.StdEncoding.EncodeToString(data)
89+
if dataStr != expected {
90+
t.Fatalf("Expected data to be %s, got: %s", expected, dataStr)
91+
}
92+
}
93+
94+
// Check that other fields remain unchanged
95+
if result1["name"] != "test-server" {
96+
t.Fatalf("Expected name to be 'test-server', got: %v", result1["name"])
97+
}
98+
}
99+
100+
func TestConvertForYAMLWithNilPointer(t *testing.T) {
101+
// Test with nil pointer to byte array
102+
server := TestServer{
103+
Name: "test-server",
104+
UserData: nil, // nil pointer
105+
Data: []byte("test"),
106+
}
107+
108+
result2, err := ConvertForYAML(server)
109+
if err != nil {
110+
t.Fatalf("Expected no error, got: %v", err)
111+
}
112+
113+
// Check that nil pointer is handled correctly
114+
if result2["userData"] != nil {
115+
t.Fatalf("Expected userData to be nil, got: %v", result2["userData"])
116+
}
117+
118+
// Check that non-nil byte array is still converted
119+
if dataStr, ok := result2["data"].(string); !ok {
120+
t.Fatalf("Expected data to be a string, got: %T", result2["data"])
121+
} else {
122+
expected := base64.StdEncoding.EncodeToString([]byte("test"))
123+
if dataStr != expected {
124+
t.Fatalf("Expected data to be %s, got: %s", expected, dataStr)
125+
}
126+
}
127+
}
128+
129+
func TestConvertForYAMLWithEmptyByteArray(t *testing.T) {
130+
// Test with empty byte array
131+
emptyData := []byte{}
132+
133+
server := TestServer{
134+
Name: "test-server",
135+
Data: emptyData,
136+
}
137+
138+
result3, err := ConvertForYAML(server)
139+
if err != nil {
140+
t.Fatalf("Expected no error, got: %v", err)
141+
}
142+
143+
// Check that empty byte array is converted to empty base64 string
144+
// Note: empty byte arrays might be omitted from JSON, so we check if it exists
145+
if dataStr, exists := result3["data"]; !exists {
146+
// Empty byte array was omitted from JSON, which is expected behavior
147+
t.Logf("Empty byte array was omitted from JSON output, which is expected")
148+
} else if dataStr, ok := dataStr.(string); !ok {
149+
t.Fatalf("Expected data to be a string, got: %T", result3["data"])
150+
} else {
151+
expected := base64.StdEncoding.EncodeToString(emptyData)
152+
if dataStr != expected {
153+
t.Fatalf("Expected data to be %s, got: %s", expected, dataStr)
154+
}
155+
if dataStr != "" {
156+
t.Fatalf("Expected empty byte array to be converted to empty string, got: %s", dataStr)
157+
}
158+
}
159+
}

0 commit comments

Comments
 (0)