Skip to content
Snippets Groups Projects
Commit 00b0546b authored by Jan Semmelink's avatar Jan Semmelink
Browse files

Use Scan() method before json.Unmarshal for param values

parent 1873153a
Branches
Tags
1 merge request!11Use Scan() method before json.Unmarshal for param values
package struct_utils
import (
"database/sql"
"encoding/csv"
"encoding/json"
"reflect"
......@@ -284,19 +285,34 @@ func unmarshalValue(v interface{}, t reflect.Type) (reflect.Value, error) {
newValuePtr := reflect.New(t)
if reflect.ValueOf(v).Type().AssignableTo(t) {
newValuePtr.Elem().Set(reflect.ValueOf(v)) //can assign as is
} else {
return newValuePtr.Elem(), nil
}
//needs conversion
s, ok := v.(string)
if !ok {
jsonValue, _ := json.Marshal(v)
s = string(jsonValue)
}
//is string value, unmarshal as quoted or unquoted JSON value
if err := json.Unmarshal([]byte("\""+s+"\""), newValuePtr.Interface()); err != nil {
if err := json.Unmarshal([]byte(s), newValuePtr.Interface()); err != nil {
return newValuePtr.Elem(), errors.Wrapf(err, "invalid \"%s\"", s)
//now we have string value
if valueScanner, ok := newValuePtr.Interface().(sql.Scanner); ok {
//if has scanner - prefer that over json unmarshal
//because we do not know if json expects quoted/unquoted for this type
//and if we try quoted, it fail, then try unquoted, we have two different
//errors one one of them will be kind of meaning nothing, but which?
//scanner should always take the value as typed, so let's try that first
if err := valueScanner.Scan(s); err == nil {
return newValuePtr.Elem(), nil
}
}
//try JSON unmarshal as is else with quotes
if err := json.Unmarshal([]byte(s), newValuePtr.Interface()); err == nil {
return newValuePtr.Elem(), nil
}
if err := json.Unmarshal([]byte("\""+s+"\""), newValuePtr.Interface()); err != nil {
return newValuePtr.Elem(), errors.Wrapf(err, "invalid \"%s\"", s)
}
return newValuePtr.Elem(), nil
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment