diff --git a/vlib/encoding/csv/reader_test.v b/vlib/encoding/csv/reader_test.v index f2350b9e6d..279ec7c0d2 100644 --- a/vlib/encoding/csv/reader_test.v +++ b/vlib/encoding/csv/reader_test.v @@ -279,3 +279,30 @@ fn test_field_double_quotes() { } assert row_count == 3 } + +struct Test { + id int + bonus string + amount int +} + +fn test_decode_to_struct() { + text := 'id,bonus,amount\r\n1,bomb,1\r\n2,rocket,1\r\n3,lightning,2\r\n' + arr := csv.decode(text) + for i, val in arr { + if i == 0 { + assert val.id == 1 + assert val.bonus == 'bomb' + assert val.amount == 1 + } else if i == 1 { + assert val.id == 2 + assert val.bonus == 'rocket' + assert val.amount == 1 + } else if i == 2 { + assert val.id == 3 + assert val.bonus == 'lightning' + assert val.amount == 2 + } + } + assert arr.len == 3 +} diff --git a/vlib/encoding/csv/to_struct_arr.v b/vlib/encoding/csv/to_struct_arr.v new file mode 100644 index 0000000000..3b260bcc04 --- /dev/null +++ b/vlib/encoding/csv/to_struct_arr.v @@ -0,0 +1,67 @@ +module csv + +import strconv + +// decode csv to struct +pub fn decode(data string) []T { + mut result := []T{} + if data == '' { + return result + } + + mut parser := new_reader(data) + mut columns_names := []string{} + mut i := 0 + for { + items := parser.read() or { break } + if i == 0 { + for val in items { + columns_names << val + } + } else { + mut t_val := T{} + $for field in T.fields { + col := get_column(field.name, columns_names) + if col > -1 && col < items.len { + $if field.typ is string { + t_val.$(field.name) = items[col] + } $else $if field.typ is int { + t_val.$(field.name) = items[col].int() + } $else $if field.typ is f32 { + t_val.$(field.name) = f32(strconv.atof64(items[col]) or { f32(0.0) }) + } $else $if field.typ is f64 { + t_val.$(field.name) = strconv.atof64(items[col]) or { f64(0.0) } + } $else $if field.typ is bool { + t_val.$(field.name) = string_to_bool(items[col]) + } + } + } + result << t_val + } + i++ + } + + return result +} + +fn string_to_bool(val string) bool { + l_val := val.to_lower().trim_space() + i_val := val.int() + if l_val == 'true' { + return true + } + if i_val == 1 { + return true + } + + return false +} + +fn get_column(name string, columns []string) int { + for i, val in columns { + if val == name { + return i + } + } + return -1 +}