@@ -119,14 +119,13 @@ func toCSV(data interface{}) (string, error) {
119119 // How much values does it add? Using CSV for a single object feels a bit odd
120120 // -> honestly none imo - tested current implementation on get_commit and this does more harm than good
121121 // as we lose insight on certain, deeply nested, fields
122- if v .Kind () == reflect .Struct || v . Kind () == reflect . Map {
122+ if v .Kind () == reflect .Struct {
123123 slice := reflect .MakeSlice (reflect .SliceOf (v .Type ()), 1 , 1 )
124124 slice .Index (0 ).Set (v )
125125 return sliceToCSV (slice )
126126 }
127127
128- // Return any primitive as is
129- return fmt .Sprintf ("%v" , data ), nil
128+ return "" , fmt .Errorf ("unsupported data type: %v" , v .Kind ())
130129}
131130
132131// unwrap dereferences pointers and interfaces until reaching a concrete value
@@ -154,7 +153,11 @@ func sliceToCSV(slice reflect.Value) (string, error) {
154153
155154 // Get all possible headers from first element
156155 firstElem := slice .Index (0 )
157- allHeaders := extractHeaders (firstElem )
156+ firstElem , isNil := unwrap (firstElem )
157+ if isNil {
158+ return "" , nil
159+ }
160+ allHeaders := extractStructHeaders (firstElem , "" )
158161 if len (allHeaders ) == 0 {
159162 return "" , fmt .Errorf ("no fields found in data" )
160163 }
@@ -220,22 +223,6 @@ func sliceToCSV(slice reflect.Value) (string, error) {
220223 return buf .String (), nil
221224}
222225
223- // extractHeaders gets all field names from an object, flattening nested structures
224- func extractHeaders (v reflect.Value ) []string {
225- v , isNil := unwrap (v )
226- if isNil {
227- return nil
228- }
229-
230- if v .Kind () == reflect .Struct {
231- return extractStructHeaders (v , "" )
232- }
233- if v .Kind () == reflect .Map {
234- return extractMapKeys (v )
235- }
236- return nil
237- }
238-
239226// getFieldName extracts field name from struct field, preferring json tag
240227func getFieldName (field reflect.StructField ) string {
241228 if jsonTag := field .Tag .Get ("json" ); jsonTag != "" && jsonTag != "-" {
@@ -272,13 +259,13 @@ func extractStructHeaders(v reflect.Value, prefix string) []string {
272259
273260 kind := fieldValue .Kind ()
274261
275- // Skip complex types (arrays, maps , interfaces), only allow primitives and timestamps
262+ // Skip complex types (arrays, slices , interfaces), only allow primitives and timestamps
276263 if kind == reflect .Struct {
277264 typeName := fieldValue .Type ().Name ()
278265 if typeName != "Timestamp" && typeName != "Time" {
279266 continue
280267 }
281- } else if kind == reflect .Slice || kind == reflect .Array || kind == reflect .Map || kind == reflect . Interface {
268+ } else if kind == reflect .Slice || kind == reflect .Array || kind == reflect .Interface {
282269 continue
283270 }
284271 }
@@ -329,8 +316,7 @@ func hasPrimitiveFields(v reflect.Value) bool {
329316 kind := field .Kind ()
330317
331318 // Check for any primitive types
332- if kind == reflect .String || kind == reflect .Int || kind == reflect .Int64 ||
333- kind == reflect .Bool || kind == reflect .Float32 || kind == reflect .Float64 {
319+ if kind == reflect .String || kind == reflect .Int || kind == reflect .Int64 || kind == reflect .Bool {
334320 return true
335321 }
336322
@@ -346,20 +332,7 @@ func hasPrimitiveFields(v reflect.Value) bool {
346332 return false
347333}
348334
349- // extractMapKeys gets keys from a map
350- func extractMapKeys (v reflect.Value ) []string {
351- var keys []string
352- iter := v .MapRange ()
353- for iter .Next () {
354- if key := iter .Key (); key .Kind () == reflect .String {
355- keys = append (keys , key .String ())
356- }
357- }
358-
359- return keys
360- }
361-
362- // extractValues gets field values from an object in the same order as headers
335+ // extractValues gets field values from a struct in the same order as headers
363336func extractValues (v reflect.Value , headers []string ) []string {
364337 v , isNil := unwrap (v )
365338 values := make ([]string , len (headers ))
@@ -386,12 +359,9 @@ func extractFieldValue(v reflect.Value, path string) string {
386359 return ""
387360 }
388361
389- switch v .Kind () {
390- case reflect .Struct :
362+ if v .Kind () == reflect .Struct {
391363 v = getStructField (v , part )
392- case reflect .Map :
393- v = v .MapIndex (reflect .ValueOf (part ))
394- default :
364+ } else {
395365 return ""
396366 }
397367 }
@@ -438,21 +408,11 @@ func formatValue(v reflect.Value) string {
438408 return strings .Join (strings .Fields (v .String ()), " " )
439409
440410 // Handle numeric and boolean types
441- case reflect .Int , reflect .Int8 , reflect . Int16 , reflect . Int32 , reflect . Int64 :
411+ case reflect .Int , reflect .Int64 :
442412 if n := v .Int (); n != 0 {
443413 return fmt .Sprintf ("%d" , n )
444414 }
445415
446- case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 :
447- if n := v .Uint (); n != 0 {
448- return fmt .Sprintf ("%d" , n )
449- }
450-
451- case reflect .Float32 , reflect .Float64 :
452- if n := v .Float (); n != 0 {
453- return fmt .Sprintf ("%g" , n )
454- }
455-
456416 case reflect .Bool :
457417 if v .Bool () {
458418 return "true"
0 commit comments