@@ -15,16 +15,15 @@ import (
1515 "github.com/oapi-codegen/oapi-codegen-exp/codegen/internal/runtime/types"
1616)
1717
18- // StyleLabelParam serializes a value using label style (RFC 6570) without exploding .
19- // Label style prefixes values with a dot.
20- // Primitives: .value
21- // Arrays: .a,b,c
22- // Objects: .key1, value1, key2, value2
23- func StyleLabelParam (paramName string , paramLocation ParamLocation , value any ) (string , error ) {
18+ // StyleLabelParam serializes a value using label style (RFC 6570).
19+ // Label style prefixes values with a dot. Path parameters only.
20+ //
21+ // Non-explode: Primitives: .value Arrays: .a,b,c Objects: .key1,value1,key2,value2
22+ // Explode: Primitives: .value Arrays: .a.b.c Objects: .key1= value1. key2= value2
23+ func StyleLabelParam (paramName string , value any , opts ParameterOptions ) (string , error ) {
2424 t := reflect .TypeOf (value )
2525 v := reflect .ValueOf (value )
2626
27- // Dereference pointers
2827 if t .Kind () == reflect .Ptr {
2928 if v .IsNil () {
3029 return "" , fmt .Errorf ("value is a nil pointer" )
@@ -33,15 +32,14 @@ func StyleLabelParam(paramName string, paramLocation ParamLocation, value any) (
3332 t = v .Type ()
3433 }
3534
36- // Check for TextMarshaler (but not time.Time or Date)
3735 if tu , ok := value .(encoding.TextMarshaler ); ok {
3836 innerT := reflect .Indirect (reflect .ValueOf (value )).Type ()
3937 if ! innerT .ConvertibleTo (reflect .TypeOf (time.Time {})) && ! innerT .ConvertibleTo (reflect .TypeOf (types.Date {})) {
4038 b , err := tu .MarshalText ()
4139 if err != nil {
4240 return "" , fmt .Errorf ("error marshaling '%s' as text: %w" , value , err )
4341 }
44- return "." + escapeParameterString (string (b ), paramLocation ), nil
42+ return "." + escapeParameterString (string (b ), opts . ParamLocation ), nil
4543 }
4644 }
4745
@@ -52,44 +50,41 @@ func StyleLabelParam(paramName string, paramLocation ParamLocation, value any) (
5250 for i := 0 ; i < n ; i ++ {
5351 sliceVal [i ] = v .Index (i ).Interface ()
5452 }
55- return styleLabelSlice (paramName , paramLocation , sliceVal )
53+ return styleLabelSlice (paramName , opts , sliceVal )
5654 case reflect .Struct :
57- return styleLabelStruct (paramName , paramLocation , value )
55+ return styleLabelStruct (paramName , opts , value )
5856 case reflect .Map :
59- return styleLabelMap (paramName , paramLocation , value )
57+ return styleLabelMap (paramName , opts , value )
6058 default :
61- return styleLabelPrimitive (paramLocation , value )
62- }
63- }
64-
65- func styleLabelPrimitive (paramLocation ParamLocation , value any ) (string , error ) {
66- strVal , err := primitiveToString (value )
67- if err != nil {
68- return "" , err
59+ strVal , err := primitiveToString (value )
60+ if err != nil {
61+ return "" , err
62+ }
63+ return "." + escapeParameterString (strVal , opts .ParamLocation ), nil
6964 }
70- return "." + escapeParameterString (strVal , paramLocation ), nil
7165}
7266
73- func styleLabelSlice (paramName string , paramLocation ParamLocation , values []any ) (string , error ) {
74- // Label without explode: .a,b,c
67+ func styleLabelSlice (paramName string , opts ParameterOptions , values []any ) (string , error ) {
7568 parts := make ([]string , len (values ))
7669 for i , v := range values {
7770 part , err := primitiveToString (v )
7871 if err != nil {
7972 return "" , fmt .Errorf ("error formatting '%s': %w" , paramName , err )
8073 }
81- parts [i ] = escapeParameterString (part , paramLocation )
74+ parts [i ] = escapeParameterString (part , opts . ParamLocation )
8275 }
83- return "." + strings .Join (parts , "," ), nil
76+ sep := ","
77+ if opts .Explode {
78+ sep = "."
79+ }
80+ return "." + strings .Join (parts , sep ), nil
8481}
8582
86- func styleLabelStruct (paramName string , paramLocation ParamLocation , value any ) (string , error ) {
87- // Check for known types first
83+ func styleLabelStruct (paramName string , opts ParameterOptions , value any ) (string , error ) {
8884 if timeVal , ok := marshalKnownTypes (value ); ok {
89- return "." + escapeParameterString (timeVal , paramLocation ), nil
85+ return "." + escapeParameterString (timeVal , opts . ParamLocation ), nil
9086 }
9187
92- // Check for json.Marshaler
9388 if m , ok := value .(json.Marshaler ); ok {
9489 buf , err := m .MarshalJSON ()
9590 if err != nil {
@@ -101,25 +96,32 @@ func styleLabelStruct(paramName string, paramLocation ParamLocation, value any)
10196 if err = e .Decode (& i2 ); err != nil {
10297 return "" , fmt .Errorf ("failed to unmarshal JSON: %w" , err )
10398 }
104- return StyleLabelParam (paramName , paramLocation , i2 )
99+ return StyleLabelParam (paramName , i2 , opts )
105100 }
106101
107- // Build field dictionary
108102 fieldDict , err := structToFieldDict (value )
109103 if err != nil {
110104 return "" , err
111105 }
112106
113- // Label style without explode: .key1,value1,key2,value2
107+ if opts .Explode {
108+ var parts []string
109+ for _ , k := range sortedKeys (fieldDict ) {
110+ v := escapeParameterString (fieldDict [k ], opts .ParamLocation )
111+ parts = append (parts , k + "=" + v )
112+ }
113+ return "." + strings .Join (parts , "." ), nil
114+ }
115+
114116 var parts []string
115117 for _ , k := range sortedKeys (fieldDict ) {
116- v := escapeParameterString (fieldDict [k ], paramLocation )
118+ v := escapeParameterString (fieldDict [k ], opts . ParamLocation )
117119 parts = append (parts , k , v )
118120 }
119121 return "." + strings .Join (parts , "," ), nil
120122}
121123
122- func styleLabelMap (paramName string , paramLocation ParamLocation , value any ) (string , error ) {
124+ func styleLabelMap (paramName string , opts ParameterOptions , value any ) (string , error ) {
123125 dict , ok := value .(map [string ]any )
124126 if ! ok {
125127 return "" , errors .New ("map not of type map[string]any" )
@@ -134,10 +136,18 @@ func styleLabelMap(paramName string, paramLocation ParamLocation, value any) (st
134136 fieldDict [fieldName ] = str
135137 }
136138
137- // Label style without explode: .key1,value1,key2,value2
139+ if opts .Explode {
140+ var parts []string
141+ for _ , k := range sortedKeys (fieldDict ) {
142+ v := escapeParameterString (fieldDict [k ], opts .ParamLocation )
143+ parts = append (parts , k + "=" + v )
144+ }
145+ return "." + strings .Join (parts , "." ), nil
146+ }
147+
138148 var parts []string
139149 for _ , k := range sortedKeys (fieldDict ) {
140- v := escapeParameterString (fieldDict [k ], paramLocation )
150+ v := escapeParameterString (fieldDict [k ], opts . ParamLocation )
141151 parts = append (parts , k , v )
142152 }
143153 return "." + strings .Join (parts , "," ), nil
0 commit comments