diff --git a/types/devcontainer_config.go b/types/devcontainer_config.go index ad4f32d47..ff0eb9dc9 100644 --- a/types/devcontainer_config.go +++ b/types/devcontainer_config.go @@ -188,6 +188,10 @@ func (f *FeatureValue) UnmarshalJSON(data []byte) error { return nil } +func (f *FeatureValue) MarshalJSON() ([]byte, error) { + return json.Marshal(f.Options) +} + func (f *Features) UnmarshalJSON(data []byte) error { if *f == nil { *f = make(Features) @@ -248,15 +252,27 @@ type Mount struct { } func (m *Mount) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, m); err == nil { + type Alias Mount + aux := &struct { + *Alias + }{ + Alias: (*Alias)(m), + } + if err := json.Unmarshal(data, &aux); err == nil { return nil } - dst, err := stringToObject(string(data)) - if err != nil { - return err + + var str string + if err := json.Unmarshal(data, &str); err == nil { + dst, err := stringToObject(str) + if err != nil { + return err + } + *m = *dst + return nil } - *m = *dst - return nil + + return fmt.Errorf("failed to unmarshal JSON: %s", string(data)) } func ParseMountsFromRawSlice(values []any) ([]*Mount, error) { @@ -318,8 +334,6 @@ func stringToObject(mountStr string) (*Mount, error) { } case "target", "dst", "destination": newMount.Target = val - default: - return nil, fmt.Errorf("unexpected key '%s' in '%s'", key, field) } } return &newMount, nil diff --git a/types/devcontainer_feature_config.go b/types/devcontainer_feature_config.go index bb109ed64..026a277e7 100644 --- a/types/devcontainer_feature_config.go +++ b/types/devcontainer_feature_config.go @@ -58,11 +58,18 @@ func (o *OptionDefinition) ValidateValue(optionValue any, optionKey string, feat switch o.Type { case enum.FeatureOptionValueTypeBoolean: boolValue, ok := optionValue.(bool) - if !ok { - return "", fmt.Errorf("error during resolving feature %s, option Id %s "+ - "expects boolean, got %s ", featureSource, optionKey, optionValue) + if ok { + return strconv.FormatBool(boolValue), nil } - return strconv.FormatBool(boolValue), nil + stringValue, ok := optionValue.(string) + if ok { + parsedBoolValue, err := strconv.ParseBool(stringValue) + if err == nil { + return strconv.FormatBool(parsedBoolValue), nil + } + } + return "", fmt.Errorf("error during resolving feature %s, option Id %s "+ + "expects boolean, got %s ", featureSource, optionKey, optionValue) case enum.FeatureOptionValueTypeString: stringValue, ok := optionValue.(string) if !ok {