@@ -226,6 +226,163 @@ func AssertMapFieldError(t *testing.T, s map[string]*FieldError, field string, e
226226 EqualSkip (t , 2 , val .Tag , expectedTag )
227227}
228228
229+ func TestFlattenValidation (t * testing.T ) {
230+
231+ type Inner struct {
232+ Name string `validate:"required"`
233+ }
234+
235+ type TestMultiDimensionalStructsPtr struct {
236+ Errs [][]* Inner `validate:"gt=0,dive,dive,required"`
237+ }
238+
239+ var errStructPtrArray [][]* Inner
240+
241+ errStructPtrArray = append (errStructPtrArray , []* Inner {& Inner {"ok" }, & Inner {"" }, & Inner {"ok" }})
242+
243+ tmsp := & TestMultiDimensionalStructsPtr {
244+ Errs : errStructPtrArray ,
245+ }
246+
247+ errs := validate .Struct (tmsp )
248+ NotEqual (t , errs , nil )
249+ Equal (t , len (errs .Errors ), 1 )
250+ // for full test coverage
251+ fmt .Sprint (errs .Error ())
252+
253+ fieldErr := errs .Errors ["Errs" ]
254+ Equal (t , fieldErr .IsPlaceholderErr , true )
255+ Equal (t , fieldErr .IsSliceOrArray , true )
256+ Equal (t , fieldErr .Field , "Errs" )
257+ Equal (t , len (fieldErr .SliceOrArrayErrs ), 1 )
258+
259+ innerSlice1 , ok := fieldErr .SliceOrArrayErrs [0 ].(* FieldError )
260+ Equal (t , ok , true )
261+ Equal (t , innerSlice1 .IsPlaceholderErr , true )
262+ Equal (t , innerSlice1 .Field , "Errs[0]" )
263+
264+ flatFieldErr , ok := fieldErr .Flatten ()["[0][1].Inner.Name" ]
265+ Equal (t , ok , true )
266+ Equal (t , flatFieldErr .Field , "Name" )
267+ Equal (t , flatFieldErr .Tag , "required" )
268+
269+ structErrFlatten , ok := errs .Flatten ()["Errs[0][1].Inner.Name" ]
270+ Equal (t , ok , true )
271+ Equal (t , structErrFlatten .Field , "Name" )
272+ Equal (t , structErrFlatten .Tag , "required" )
273+
274+ errStructPtrArray = [][]* Inner {}
275+ errStructPtrArray = append (errStructPtrArray , []* Inner {& Inner {"ok" }, nil , & Inner {"ok" }})
276+
277+ tmsp = & TestMultiDimensionalStructsPtr {
278+ Errs : errStructPtrArray ,
279+ }
280+
281+ errs = validate .Struct (tmsp )
282+ NotEqual (t , errs , nil )
283+ Equal (t , len (errs .Errors ), 1 )
284+ // for full test coverage
285+ fmt .Sprint (errs .Error ())
286+
287+ fieldErr = errs .Errors ["Errs" ]
288+ Equal (t , fieldErr .IsPlaceholderErr , true )
289+ Equal (t , fieldErr .IsSliceOrArray , true )
290+ Equal (t , fieldErr .Field , "Errs" )
291+ Equal (t , len (fieldErr .SliceOrArrayErrs ), 1 )
292+
293+ innerSlice1 , ok = fieldErr .SliceOrArrayErrs [0 ].(* FieldError )
294+ Equal (t , ok , true )
295+ Equal (t , innerSlice1 .IsPlaceholderErr , true )
296+ Equal (t , innerSlice1 .Field , "Errs[0]" )
297+
298+ flatFieldErr , ok = fieldErr .Flatten ()["[0][1]" ]
299+ Equal (t , ok , true )
300+ Equal (t , flatFieldErr .Field , "Errs[0][1]" )
301+ Equal (t , flatFieldErr .Tag , "required" )
302+
303+ type TestMapStructPtr struct {
304+ Errs map [int ]* Inner `validate:"gt=0,dive,required"`
305+ }
306+
307+ mip := map [int ]* Inner {0 : & Inner {"ok" }, 3 : & Inner {"" }, 4 : & Inner {"ok" }}
308+
309+ msp := & TestMapStructPtr {
310+ Errs : mip ,
311+ }
312+
313+ errs = validate .Struct (msp )
314+ NotEqual (t , errs , nil )
315+ Equal (t , len (errs .Errors ), 1 )
316+
317+ fieldError := errs .Errors ["Errs" ]
318+ Equal (t , fieldError .IsPlaceholderErr , true )
319+ Equal (t , fieldError .IsMap , true )
320+ Equal (t , len (fieldError .MapErrs ), 1 )
321+
322+ innerStructError , ok := fieldError .MapErrs [3 ].(* StructErrors )
323+ Equal (t , ok , true )
324+ Equal (t , innerStructError .Struct , "Inner" )
325+ Equal (t , len (innerStructError .Errors ), 1 )
326+
327+ innerInnerFieldError , ok := innerStructError .Errors ["Name" ]
328+ Equal (t , ok , true )
329+ Equal (t , innerInnerFieldError .IsPlaceholderErr , false )
330+ Equal (t , innerInnerFieldError .IsSliceOrArray , false )
331+ Equal (t , innerInnerFieldError .Field , "Name" )
332+ Equal (t , innerInnerFieldError .Tag , "required" )
333+
334+ flatErrs , ok := errs .Flatten ()["Errs[3].Inner.Name" ]
335+ Equal (t , ok , true )
336+ Equal (t , flatErrs .Field , "Name" )
337+ Equal (t , flatErrs .Tag , "required" )
338+
339+ mip2 := map [int ]* Inner {0 : & Inner {"ok" }, 3 : nil , 4 : & Inner {"ok" }}
340+
341+ msp2 := & TestMapStructPtr {
342+ Errs : mip2 ,
343+ }
344+
345+ errs = validate .Struct (msp2 )
346+ NotEqual (t , errs , nil )
347+ Equal (t , len (errs .Errors ), 1 )
348+
349+ fieldError = errs .Errors ["Errs" ]
350+ Equal (t , fieldError .IsPlaceholderErr , true )
351+ Equal (t , fieldError .IsMap , true )
352+ Equal (t , len (fieldError .MapErrs ), 1 )
353+
354+ innerFieldError , ok := fieldError .MapErrs [3 ].(* FieldError )
355+ Equal (t , ok , true )
356+ Equal (t , innerFieldError .IsPlaceholderErr , false )
357+ Equal (t , innerFieldError .IsSliceOrArray , false )
358+ Equal (t , innerFieldError .Field , "Errs[3]" )
359+ Equal (t , innerFieldError .Tag , "required" )
360+
361+ flatErrs , ok = errs .Flatten ()["Errs[3]" ]
362+ Equal (t , ok , true )
363+ Equal (t , flatErrs .Field , "Errs[3]" )
364+ Equal (t , flatErrs .Tag , "required" )
365+
366+ type TestMapInnerArrayStruct struct {
367+ Errs map [int ][]string `validate:"gt=0,dive,dive,required"`
368+ }
369+
370+ mias := map [int ][]string {0 : []string {"ok" }, 3 : []string {"ok" , "" }, 4 : []string {"ok" }}
371+
372+ mia := & TestMapInnerArrayStruct {
373+ Errs : mias ,
374+ }
375+
376+ errs = validate .Struct (mia )
377+ NotEqual (t , errs , nil )
378+ Equal (t , len (errs .Errors ), 1 )
379+
380+ flatErrs , ok = errs .Flatten ()["Errs[3][1]" ]
381+ Equal (t , ok , true )
382+ Equal (t , flatErrs .Field , "Errs[3][1]" )
383+ Equal (t , flatErrs .Tag , "required" )
384+ }
385+
229386func TestInterfaceErrValidation (t * testing.T ) {
230387
231388 var v1 interface {}
@@ -578,6 +735,11 @@ func TestArrayDiveValidation(t *testing.T) {
578735 Equal (t , err .IsSliceOrArray , true )
579736 Equal (t , len (err .SliceOrArrayErrs ), 1 )
580737
738+ // flat := err.Flatten()
739+ // fe, ok := flat["[1]"]
740+ // Equal(t, ok, true)
741+ // Equal(t, fe.Tag, "required")
742+
581743 err = validate .Field (arr , "len=2,dive,required" )
582744 NotEqual (t , err , nil )
583745 Equal (t , err .IsPlaceholderErr , false )
@@ -606,6 +768,12 @@ func TestArrayDiveValidation(t *testing.T) {
606768 NotEqual (t , errs , nil )
607769 Equal (t , len (errs .Errors ), 1 )
608770
771+ // flat = errs.Flatten()
772+ // me, ok := flat["Errs[1]"]
773+ // Equal(t, ok, true)
774+ // Equal(t, me.Field, "Errs[1]")
775+ // Equal(t, me.Tag, "required")
776+
609777 fieldErr , ok := errs .Errors ["Errs" ]
610778 Equal (t , ok , true )
611779 Equal (t , fieldErr .IsPlaceholderErr , true )
@@ -666,13 +834,15 @@ func TestArrayDiveValidation(t *testing.T) {
666834 Equal (t , sliceError1 .IsPlaceholderErr , true )
667835 Equal (t , sliceError1 .IsSliceOrArray , true )
668836 Equal (t , len (sliceError1 .SliceOrArrayErrs ), 2 )
837+ Equal (t , sliceError1 .Field , "Errs[0]" )
669838
670839 innerSliceError1 , ok := sliceError1 .SliceOrArrayErrs [1 ].(* FieldError )
671840 Equal (t , ok , true )
672841 Equal (t , innerSliceError1 .IsPlaceholderErr , false )
673842 Equal (t , innerSliceError1 .Tag , required )
674843 Equal (t , innerSliceError1 .IsSliceOrArray , false )
675844 Equal (t , len (innerSliceError1 .SliceOrArrayErrs ), 0 )
845+ Equal (t , innerSliceError1 .Field , "Errs[0][1]" )
676846
677847 type Inner struct {
678848 Name string `validate:"required"`
@@ -736,12 +906,25 @@ func TestArrayDiveValidation(t *testing.T) {
736906 // for full test coverage
737907 fmt .Sprint (errs .Error ())
738908
909+ // flat := errs.Flatten()
910+ // // fmt.Println(errs)
911+ // fmt.Println(flat)
912+ // expect Errs[0][1].Inner.Name
913+ // me, ok := flat["Errs[1]"]
914+ // Equal(t, ok, true)
915+ // Equal(t, me.Field, "Errs[1]")
916+ // Equal(t, me.Tag, "required")
917+
739918 fieldErr , ok = errs .Errors ["Errs" ]
740919 Equal (t , ok , true )
741920 Equal (t , fieldErr .IsPlaceholderErr , true )
742921 Equal (t , fieldErr .IsSliceOrArray , true )
743922 Equal (t , len (fieldErr .SliceOrArrayErrs ), 3 )
744923
924+ // flat := fieldErr.Flatten()
925+ // fmt.Println(errs)
926+ // fmt.Println(flat)
927+
745928 sliceError1 , ok = fieldErr .SliceOrArrayErrs [0 ].(* FieldError )
746929 Equal (t , ok , true )
747930 Equal (t , sliceError1 .IsPlaceholderErr , true )
0 commit comments