@@ -153,9 +153,13 @@ func addOrMergeFields(info *fieldInfo, key string, child *fieldInfo, fullName st
153153}
154154
155155func buildAnonymousFieldInfo (info * fieldInfo , lowerCaseName string , ft reflect.Type , fullName string ) error {
156+ return buildAnonymousFieldInfoWithVisited (info , lowerCaseName , ft , fullName , make (map [reflect.Type ]bool ))
157+ }
158+
159+ func buildAnonymousFieldInfoWithVisited (info * fieldInfo , lowerCaseName string , ft reflect.Type , fullName string , visited map [reflect.Type ]bool ) error {
156160 switch ft .Kind () {
157161 case reflect .Struct :
158- fields , err := buildFieldsInfo (ft , fullName )
162+ fields , err := buildFieldsInfoWithVisited (ft , fullName , visited )
159163 if err != nil {
160164 return err
161165 }
@@ -166,7 +170,7 @@ func buildAnonymousFieldInfo(info *fieldInfo, lowerCaseName string, ft reflect.T
166170 }
167171 }
168172 case reflect .Map :
169- elemField , err := buildFieldsInfo (mapping .Deref (ft .Elem ()), fullName )
173+ elemField , err := buildFieldsInfoWithVisited (mapping .Deref (ft .Elem ()), fullName , visited )
170174 if err != nil {
171175 return err
172176 }
@@ -193,13 +197,25 @@ func buildAnonymousFieldInfo(info *fieldInfo, lowerCaseName string, ft reflect.T
193197}
194198
195199func buildFieldsInfo (tp reflect.Type , fullName string ) (* fieldInfo , error ) {
200+ return buildFieldsInfoWithVisited (tp , fullName , make (map [reflect.Type ]bool ))
201+ }
202+
203+ func buildFieldsInfoWithVisited (tp reflect.Type , fullName string , visited map [reflect.Type ]bool ) (* fieldInfo , error ) {
196204 tp = mapping .Deref (tp )
197205
206+ if visited [tp ] {
207+ return & fieldInfo {
208+ children : make (map [string ]* fieldInfo ),
209+ }, nil
210+ }
211+
198212 switch tp .Kind () {
199213 case reflect .Struct :
200- return buildStructFieldsInfo (tp , fullName )
214+ visited [tp ] = true
215+ defer delete (visited , tp )
216+ return buildStructFieldsInfoWithVisited (tp , fullName , visited )
201217 case reflect .Array , reflect .Slice , reflect .Map :
202- return buildFieldsInfo (mapping .Deref (tp .Elem ()), fullName )
218+ return buildFieldsInfoWithVisited (mapping .Deref (tp .Elem ()), fullName , visited )
203219 case reflect .Chan , reflect .Func :
204220 return nil , fmt .Errorf ("unsupported type: %s, fullName: %s" , tp .Kind (), fullName )
205221 default :
@@ -210,22 +226,26 @@ func buildFieldsInfo(tp reflect.Type, fullName string) (*fieldInfo, error) {
210226}
211227
212228func buildNamedFieldInfo (info * fieldInfo , lowerCaseName string , ft reflect.Type , fullName string ) error {
229+ return buildNamedFieldInfoWithVisited (info , lowerCaseName , ft , fullName , make (map [reflect.Type ]bool ))
230+ }
231+
232+ func buildNamedFieldInfoWithVisited (info * fieldInfo , lowerCaseName string , ft reflect.Type , fullName string , visited map [reflect.Type ]bool ) error {
213233 var finfo * fieldInfo
214234 var err error
215235
216236 switch ft .Kind () {
217237 case reflect .Struct :
218- finfo , err = buildFieldsInfo (ft , fullName )
238+ finfo , err = buildFieldsInfoWithVisited (ft , fullName , visited )
219239 if err != nil {
220240 return err
221241 }
222242 case reflect .Array , reflect .Slice :
223- finfo , err = buildFieldsInfo (ft .Elem (), fullName )
243+ finfo , err = buildFieldsInfoWithVisited (ft .Elem (), fullName , visited )
224244 if err != nil {
225245 return err
226246 }
227247 case reflect .Map :
228- elemInfo , err := buildFieldsInfo (mapping .Deref (ft .Elem ()), fullName )
248+ elemInfo , err := buildFieldsInfoWithVisited (mapping .Deref (ft .Elem ()), fullName , visited )
229249 if err != nil {
230250 return err
231251 }
@@ -235,7 +255,7 @@ func buildNamedFieldInfo(info *fieldInfo, lowerCaseName string, ft reflect.Type,
235255 mapField : elemInfo ,
236256 }
237257 default :
238- finfo , err = buildFieldsInfo (ft , fullName )
258+ finfo , err = buildFieldsInfoWithVisited (ft , fullName , visited )
239259 if err != nil {
240260 return err
241261 }
@@ -245,6 +265,10 @@ func buildNamedFieldInfo(info *fieldInfo, lowerCaseName string, ft reflect.Type,
245265}
246266
247267func buildStructFieldsInfo (tp reflect.Type , fullName string ) (* fieldInfo , error ) {
268+ return buildStructFieldsInfoWithVisited (tp , fullName , make (map [reflect.Type ]bool ))
269+ }
270+
271+ func buildStructFieldsInfoWithVisited (tp reflect.Type , fullName string , visited map [reflect.Type ]bool ) (* fieldInfo , error ) {
248272 info := & fieldInfo {
249273 children : make (map [string ]* fieldInfo ),
250274 }
@@ -260,12 +284,12 @@ func buildStructFieldsInfo(tp reflect.Type, fullName string) (*fieldInfo, error)
260284 ft := mapping .Deref (field .Type )
261285 // flatten anonymous fields
262286 if field .Anonymous {
263- if err := buildAnonymousFieldInfo (info , lowerCaseName , ft ,
264- getFullName (fullName , lowerCaseName )); err != nil {
287+ if err := buildAnonymousFieldInfoWithVisited (info , lowerCaseName , ft ,
288+ getFullName (fullName , lowerCaseName ), visited ); err != nil {
265289 return nil , err
266290 }
267- } else if err := buildNamedFieldInfo (info , lowerCaseName , ft ,
268- getFullName (fullName , lowerCaseName )); err != nil {
291+ } else if err := buildNamedFieldInfoWithVisited (info , lowerCaseName , ft ,
292+ getFullName (fullName , lowerCaseName ), visited ); err != nil {
269293 return nil , err
270294 }
271295 }
0 commit comments