/** * Given a type and any value, return a runtime value coerced to match the type. */ func coerceValue(typ typs.QLType, value interface{}) interface{} { if typ, ok := typ.(*typs.QLNonNull); ok { nullableType := typ.OfType return coerceValue(nullableType, value) } v := reflect.ValueOf(value) if value == nil || v.IsNil() { return nil } switch typ := typ.(type) { case *typs.QLList: itemType := typ.OfType if v.Kind() == reflect.Slice || v.Kind() == reflect.Array { result := make([]interface{}, v.Len())[:0] for i, n := 0, v.Len(); i < n; i++ { fieldValue := v.Field(i) result = append(result, coerceValue(itemType, fieldValue)) } return result } return []interface{}{coerceValue(itemType, value)} case *typs.QLInputObject: fields := typ.GetFields() obj := make(map[string]interface{}) for fieldName, field := range fields { runtimeField := v.FieldByName(fieldName) if !runtimeField.IsValid() { continue } fieldValue := coerceValue(field.Type, runtimeField.Interface()) if fieldValue == nil { fieldValue = field.DefaultValue } if fieldValue != nil { obj[fieldName] = fieldValue } } return obj case *typs.QLScalar: return typ.ParseValue(value) case *typs.QLEnum: return typ.ParseValue(value) default: panic("Must be input type") } }