package customer import ( "encoding/json" "fmt" "strings" ) type companySelectionObject struct { ID string `json:"id"` } // decodeCompanySelection parses company IDs sent as strings, legacy company_ids, // or company summary objects returned by GET customer. func decodeCompanySelection(raw json.RawMessage) ([]string, error) { if len(raw) == 0 { return nil, fmt.Errorf("empty company selection") } if string(raw) == "null" { return []string{}, nil } var ids []string if err := json.Unmarshal(raw, &ids); err == nil { return ids, nil } var objects []companySelectionObject if err := json.Unmarshal(raw, &objects); err == nil { result := make([]string, 0, len(objects)) for _, object := range objects { if id := strings.TrimSpace(object.ID); id != "" { result = append(result, id) } } return result, nil } return nil, fmt.Errorf("companies must be an array of IDs or objects with id") } func mergeCompanySelectionFields(raw map[string]json.RawMessage) (json.RawMessage, bool, error) { if value, ok := raw["companies"]; ok { return value, true, nil } if value, ok := raw["company_ids"]; ok { return value, true, nil } return nil, false, nil } func unmarshalFormWithoutCompanyFields(data []byte, raw map[string]json.RawMessage, target any) error { delete(raw, "companies") delete(raw, "company_ids") trimmed, err := json.Marshal(raw) if err != nil { return err } return json.Unmarshal(trimmed, target) } // UnmarshalJSON accepts companies, legacy company_ids, and company summary objects. func (f *CreateCustomerForm) UnmarshalJSON(data []byte) error { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return err } selectionRaw, present, err := mergeCompanySelectionFields(raw) if err != nil { return err } type alias CreateCustomerForm if err := unmarshalFormWithoutCompanyFields(data, raw, (*alias)(f)); err != nil { return err } if !present { return nil } companies, err := decodeCompanySelection(selectionRaw) if err != nil { return err } f.Companies = companies return nil } // UnmarshalJSON accepts companies, legacy company_ids, and company summary objects. func (f *UpdateCustomerForm) UnmarshalJSON(data []byte) error { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return err } selectionRaw, present, err := mergeCompanySelectionFields(raw) if err != nil { return err } type alias UpdateCustomerForm if err := unmarshalFormWithoutCompanyFields(data, raw, (*alias)(f)); err != nil { return err } if !present { return nil } companies, err := decodeCompanySelection(selectionRaw) if err != nil { return err } f.Companies = &companies return nil } // UnmarshalJSON accepts companies, legacy company_ids, and company summary objects. func (f *AssignCompaniesForm) UnmarshalJSON(data []byte) error { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return err } selectionRaw, present, err := mergeCompanySelectionFields(raw) if err != nil { return err } type alias AssignCompaniesForm if err := unmarshalFormWithoutCompanyFields(data, raw, (*alias)(f)); err != nil { return err } if !present { return nil } companies, err := decodeCompanySelection(selectionRaw) if err != nil { return err } f.Companies = companies return nil }