github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/types/csv-bad/marshal.go (about)

     1  package csvbad
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"sort"
     9  	"strings"
    10  
    11  	"github.com/lmorg/murex/lang"
    12  	"github.com/lmorg/murex/utils"
    13  )
    14  
    15  func marshal(p *lang.Process, iface interface{}) (b []byte, err error) {
    16  	w, err := NewParser(nil, p.Config)
    17  	if err != nil {
    18  		return
    19  	}
    20  
    21  	switch v := iface.(type) {
    22  	case []string:
    23  		for i := range v {
    24  			s := strings.TrimSpace(v[i])
    25  			b = append(b, w.ArrayToCsv([]string{s})...)
    26  			b = append(b, utils.NewLineByte...)
    27  		}
    28  		return
    29  
    30  	case [][]string:
    31  		for i := range v {
    32  			//s := strings.TrimSpace(v[i])
    33  			b = append(b, w.ArrayToCsv(v[i])...)
    34  			b = append(b, utils.NewLineByte...)
    35  		}
    36  		return
    37  
    38  	case []interface{}:
    39  		for i := range v {
    40  			j, err := json.Marshal(v[i])
    41  			s := string(j)
    42  			if err != nil {
    43  				s = strings.TrimSpace(fmt.Sprintln(v[i]))
    44  			}
    45  			b = append(b, w.ArrayToCsv([]string{s})...)
    46  			b = append(b, utils.NewLineByte...)
    47  		}
    48  		return
    49  
    50  	case map[string]string:
    51  		var headings []string
    52  		for key := range v {
    53  			headings = append(headings, key)
    54  		}
    55  		sort.Strings(headings)
    56  		b = w.ArrayToCsv(headings)
    57  		b = append(b, utils.NewLineByte...)
    58  
    59  		records := make([]string, len(headings))
    60  		for i := range headings {
    61  			records[i] = v[headings[i]]
    62  		}
    63  		b = append(b, w.ArrayToCsv(records)...)
    64  
    65  		return
    66  
    67  	case map[string]interface{}:
    68  		var headings []string
    69  		for key := range v {
    70  			headings = append(headings, key)
    71  		}
    72  		sort.Strings(headings)
    73  		b = w.ArrayToCsv(headings)
    74  		b = append(b, utils.NewLineByte...)
    75  
    76  		records := make([]string, len(headings))
    77  		for i := range headings {
    78  			j, err := json.Marshal(v[headings[i]])
    79  			s := string(j)
    80  			if err != nil {
    81  				s = strings.TrimSpace(fmt.Sprint(v[headings[i]]))
    82  			}
    83  			records[i] = s
    84  		}
    85  		b = append(b, w.ArrayToCsv(records)...)
    86  
    87  		return
    88  
    89  	case map[interface{}]string:
    90  		var headings []string
    91  		for key := range v {
    92  			headings = append(headings, fmt.Sprint(key))
    93  		}
    94  		sort.Strings(headings)
    95  		b = w.ArrayToCsv(headings)
    96  		b = append(b, utils.NewLineByte...)
    97  
    98  		records := make([]string, len(headings))
    99  		for i := range headings {
   100  			records[i] = v[headings[i]]
   101  		}
   102  		b = append(b, w.ArrayToCsv(records)...)
   103  
   104  		return
   105  
   106  	case map[interface{}]interface{}:
   107  		var headings []string
   108  
   109  		for key := range v {
   110  			headings = append(headings, fmt.Sprint(key))
   111  		}
   112  		sort.Strings(headings)
   113  		b = w.ArrayToCsv(headings)
   114  		b = append(b, utils.NewLineByte...)
   115  
   116  		records := make([]string, len(headings))
   117  		for i := range headings {
   118  			j, err := json.Marshal(v[headings[i]])
   119  			s := string(j)
   120  			if err != nil {
   121  				s = strings.TrimSpace(fmt.Sprint(v[headings[i]]))
   122  			}
   123  			records[i] = s
   124  		}
   125  		b = append(b, w.ArrayToCsv(records)...)
   126  		return
   127  
   128  	case []map[string]string:
   129  		var headings []string
   130  
   131  		for slice := range v {
   132  			if len(headings) == 0 {
   133  				for key := range v[slice] {
   134  					headings = append(headings, key)
   135  				}
   136  				sort.Strings(headings)
   137  				b = w.ArrayToCsv(headings)
   138  			}
   139  
   140  			//order := make(map[string]int)
   141  			//for i := range headings {
   142  			//	order[headings[i]] = i
   143  			//}
   144  
   145  			records := make([]string, len(headings))
   146  			for i := range headings {
   147  				records[i] = v[slice][headings[i]]
   148  			}
   149  			b = append(b, utils.NewLineByte...)
   150  			b = append(b, w.ArrayToCsv(records)...)
   151  		}
   152  		os.Stderr.WriteString("Warning: untested!\n")
   153  		return b, nil
   154  
   155  	case []map[string]interface{}:
   156  		var headings []string
   157  
   158  		for slice := range v {
   159  			if len(headings) == 0 {
   160  				for key := range v[slice] {
   161  					headings = append(headings, key)
   162  				}
   163  				sort.Strings(headings)
   164  				b = w.ArrayToCsv(headings)
   165  			}
   166  
   167  			records := make([]string, len(headings))
   168  			for i := range headings {
   169  				j, err := json.Marshal(v[slice][headings[i]])
   170  				s := string(j)
   171  				if err != nil {
   172  					s = strings.TrimSpace(fmt.Sprint(v[slice][headings[i]]))
   173  				}
   174  				records[i] = s
   175  			}
   176  			b = append(b, utils.NewLineByte...)
   177  			b = append(b, w.ArrayToCsv(records)...)
   178  		}
   179  		os.Stderr.WriteString("Warning: untested!\n")
   180  		return b, nil
   181  
   182  	case []map[interface{}]string:
   183  		var headings []string
   184  
   185  		for slice := range v {
   186  			if len(headings) == 0 {
   187  				for key := range v[slice] {
   188  					headings = append(headings, fmt.Sprint(key))
   189  				}
   190  				sort.Strings(headings)
   191  				b = w.ArrayToCsv(headings)
   192  			}
   193  
   194  			records := make([]string, len(headings))
   195  			for i := range headings {
   196  				j, err := json.Marshal(v[slice][headings[i]])
   197  				s := string(j)
   198  				if err != nil {
   199  					s = strings.TrimSpace(fmt.Sprint(v[slice][headings[i]]))
   200  				}
   201  				records[i] = s
   202  			}
   203  			b = append(b, utils.NewLineByte...)
   204  			b = append(b, w.ArrayToCsv(records)...)
   205  		}
   206  		os.Stderr.WriteString("Warning: untested!\n")
   207  		return b, nil
   208  
   209  	case []map[interface{}]interface{}:
   210  		var headings []string
   211  
   212  		for slice := range v {
   213  			if len(headings) == 0 {
   214  				for key := range v[slice] {
   215  					headings = append(headings, fmt.Sprint(key))
   216  				}
   217  				sort.Strings(headings)
   218  				b = w.ArrayToCsv(headings)
   219  			}
   220  
   221  			records := make([]string, len(headings))
   222  			for i := range headings {
   223  				j, err := json.Marshal(v[slice][headings[i]])
   224  				s := string(j)
   225  				if err != nil {
   226  					s = strings.TrimSpace(fmt.Sprint(v[slice][headings[i]]))
   227  				}
   228  				records[i] = s
   229  				records[i] = fmt.Sprint(v[slice][headings[i]])
   230  			}
   231  			b = append(b, utils.NewLineByte...)
   232  			b = append(b, w.ArrayToCsv(records)...)
   233  		}
   234  		os.Stderr.WriteString("Warning: untested!\n")
   235  		return b, nil
   236  
   237  	default:
   238  		err = errors.New("I don't know how to marshal that data into a `csv`. Data possibly too complex?")
   239  		return
   240  	}
   241  }
   242  
   243  func unmarshal(p *lang.Process) (interface{}, error) {
   244  	csvReader, err := NewParser(p.Stdin, p.Config)
   245  	if err != nil {
   246  		return nil, err
   247  	}
   248  
   249  	table := make([]map[string]string, 0)
   250  	csvReader.ReadLine(func(recs []string, heads []string) {
   251  		record := make(map[string]string)
   252  		for i := range recs {
   253  			record[heads[i]] = recs[i]
   254  		}
   255  		table = append(table, record)
   256  	})
   257  
   258  	return table, nil
   259  }