gnormal / gnorm

A database-first code generator for any language
https://gnorm.org
Other
488 stars 40 forks source link

Convert []interface{} to []string from plugins #66

Closed verygoodsoftwarenotvirus closed 6 years ago

verygoodsoftwarenotvirus commented 6 years ago

Encountered this need when using Gnorm in a personal project. Plugin output is marshaled as []interface{} by default, which means you can't send something from the Gnorm template data structure into a plugin and then pipe that data to a function like join, because join only accepts []strings.

I'm not completely married to the function name or docstring, so open to suggestions on how those could be improved. :)

natefinch commented 6 years ago

So, I think we can instead just automatically check for json lists that are all strings and convert them to slices of strings. the template code will convert an interface{} to the underlying type to make it work with the target function. See here: https://play.golang.org/p/V7huph8VEZ

So, we should change the plugin code to run through the json output and do this kind of a check, something like this:

func convert(v interface{}) interface{} {
    if m, ok := v.(map[string]interface{}); ok {
        for k, v := range m {
            m[k]=convert(v)
        }
    }
    list, ok := v.([]interface)
    if !ok {
        // not a list
        return v
    }
    var str []string
    for _, val := range list {
        s, ok := val.(string)
        if !ok {
            // something in the list not a string, return the original
            return v
        }
        str = append(str, s)
    }
    // if we got this far, they're all strings
    return str
}

We'd just need to call the above function here: https://github.com/gnormal/gnorm/blob/master/environ/funcs.go#L174

natefinch commented 6 years ago

Great, thanks! :)