Skip to content

Commit 2aec29e

Browse files
authored
Merge pull request #967 from jackchenjc/issue-966
fix: Generate proper error message for 'unique' validation tag
2 parents c47232d + be22b17 commit 2aec29e

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

common/validator.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//go:build !no_dto_validator
22

33
//
4-
// Copyright (C) 2020-2024 IOTech Ltd
4+
// Copyright (C) 2020-2025 IOTech Ltd
55
//
66
// SPDX-License-Identifier: Apache-2.0
77

@@ -103,6 +103,13 @@ func getErrorMessage(e validator.FieldError) string {
103103
msg = fmt.Sprintf("%s field should be one of %s", fieldName, fieldValue)
104104
case "gt":
105105
msg = fmt.Sprintf("%s field should greater than %s", fieldName, fieldValue)
106+
case "unique":
107+
// If the tag contains a field param, it means that the unique tag is used for a slice of struct
108+
if fieldValue != "" {
109+
msg = fmt.Sprintf("%s field should only contain unique elements with unique '%s' values", fieldName, fieldValue)
110+
} else {
111+
msg = fmt.Sprintf("%s field should only contain unique elements", fieldName)
112+
}
106113
case dtoDurationTag:
107114
msg = fmt.Sprintf("%s field should follows the ISO 8601 Durations format, e.g.,100ms, 24h, or be greater than or equal to the minimum value %s ", fieldName, fieldValue)
108115
case dtoUuidTag:

common/validator_test.go

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// Copyright (C) 2025 IOTech Ltd
3+
//
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
package common
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
type TestItem struct {
15+
Name string
16+
UniqueArray []string `validate:"unique"`
17+
UniqueSliceOfStruct []TestItem `validate:"unique=Name"` // only one field is supported
18+
}
19+
20+
// The test only covers the validation of the "unique" tag at the time of writing this comment.
21+
// TODO: Add more tests to cover other validation tags if needed
22+
23+
// TestValidate tests the Validate function
24+
func TestValidate(t *testing.T) {
25+
26+
validUniqueArray := TestItem{
27+
UniqueArray: []string{"a", "b", "c"},
28+
}
29+
invalidUniqueArray := TestItem{
30+
UniqueArray: []string{"a", "a", "c"},
31+
}
32+
validUniqueSliceOfSturct := TestItem{
33+
UniqueSliceOfStruct: []TestItem{
34+
{Name: "a"},
35+
{Name: "b"},
36+
},
37+
}
38+
invalidUniqueSliceOfSturct := TestItem{
39+
UniqueSliceOfStruct: []TestItem{
40+
{Name: "a"},
41+
{Name: "a"},
42+
},
43+
}
44+
45+
tests := []struct {
46+
name string
47+
input any
48+
expected bool
49+
}{
50+
{"valid, unique tag for arrays and slices", validUniqueArray, false},
51+
{"invalid, unique tag for arrays and slices", invalidUniqueArray, true},
52+
{"valid, unique tag for slices of struct", validUniqueSliceOfSturct, false},
53+
{"invalid, unique tag for slices of struct", invalidUniqueSliceOfSturct, true},
54+
}
55+
for _, tt := range tests {
56+
t.Run(tt.name, func(t *testing.T) {
57+
err := Validate(tt.input)
58+
if tt.expected {
59+
require.Error(t, err)
60+
}
61+
})
62+
}
63+
}

0 commit comments

Comments
 (0)