#3924 - generate UnmarshalText conversion for struct:field:type on HTTP path and query params#3926
Conversation
…field:type on HTTP path and query params. When struct:field:type meta is used on a string-based attribute mapped to an HTTP path or query parameter, the generated encode_decode.go assigned the raw string value directly to the typed field, causing a compile error. This fix detects when struct:field:type overrides a string attribute and the custom type implements encoding.TextUnmarshaler, and generates a call to UnmarshalText instead of the current direct string assignment. This should work for both path params (read via mux.Vars) and query params (read via url.Values.Get). A new isStringMetaType helper function has been added to service_Data.go, which sets IsTextUnmarshaler on AttributeData when the condition is met. The request_elements.go.tpl and query_type_conversion.go.tpl templates use this flag to bypass the string short-circuit path and emit the correct conversion code. The mustValidate logic is also updated so that err is declared in the generated var block when a TextUnmarshaler conversion is present.
|
Thanks for jumping on this, this looks like the right direction and the generated required path/query cases are much better. I think there are two edge cases worth tightening before merging:
It’d also be good to add a golden case that matches the original issue more closely: |
…rams - Fix nil pointer panic for optional query params with struct:field:type: unmarshal into a local value and assign &v only on success, rather than calling UnmarshalText directly on the nil pointer variable - Skip format validation for attributes with struct:field:type meta to avoid passing a non-string typed value to goa.ValidateFormat, which expects a plain string regardless of context - Add golden test cases for Format(FormatUUID) + struct:field:type on a required path param, and for an optional query param to cover the pointer variable path
|
Thanks for the feedback! I've updated the PR as follows: Nil pointer for optional query params The template now unmarshals into a local stack value and only assigns Format validation skip - I did take your suggestion to revert the changes to Golden test cases I've added two new cases - |
…attributes hasValidations() was returning true for attributes with struct:field:type meta whose only validation was Format (e.g. UUIDField()), causing a ValidateX call to be emitted in the parent type's validate function even though no ValidateX function would be generated - since the format check is skipped at code gen time. Fixed by treating format-only struct:field_type attributes as having no validations in hasValidations(), consistent with the skip already applied in validationCode().
|
I encountered one additional edge case while testing in a real project - types where UUIDField() (or any The parent type's validate function would emit a Fixed by adding the same |
|
Nice, thanks for chasing those extra cases down. The optional query path looks much better now, and the added golden cases cover the shape I was worried about. One small thought on the latest Could we instead have Something along those lines would make the nested |
|
That's a great point re. |
|
This looks good to me now, the One last small thing: since the regression you found was specifically the nested body Also, super minor: the extra |
…on test. validationCode() already calls generatedRequiredValidation() internally, making the explicit fallback check in hasValidations() redundant. Added a focused regression test for the nested body ValidateX mismatch.
|
Done - two small changes made: Redundant Check - I've removed the Regression test - Added a focused DSL case with a nested body type whose only validations are |
|
Perfect, thank you! |
Fix for #3924: generate UnmarshalText conversion for struct:field:type on HTTP path and query params.
When struct:field:type meta is used on a string-based attribute mapped to an HTTP path or query parameter, the generated encode_decode.go assigned the raw string value directly to the typed field, causing a compile error.
This fix detects when struct:field:type overrides a string attribute and the custom type implements encoding.TextUnmarshaler, and generates a call to UnmarshalText instead of the current direct string assignment. This should work for both path params (read via mux.Vars) and query params (read via url.Values.Get).
A new isStringMetaType helper function has been added to service_Data.go, which sets IsTextUnmarshaler on AttributeData when the condition is met. The request_elements.go.tpl and query_type_conversion.go.tpl templates use this flag to bypass the string short-circuit path and emit the correct conversion code. The mustValidate logic is also updated so that err is declared in the generated var block when a TextUnmarshaler conversion is present.
Format validation is also skipped for attributes with a struct:field:type meta that implement encoding.TextUnmarshaler, as the UnmarshalText call already validates the format implicitly during deserialization.