Skip to content

Commit 0c2ced0

Browse files
committed
add support structured tag fields
tags.go is copied from encoding/json in the go standard library. We're not doing anything with the field options yet, just parsing them out.
1 parent 5afcd79 commit 0c2ced0

File tree

4 files changed

+71
-2
lines changed

4 files changed

+71
-2
lines changed

query/encode.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ func Values(v interface{}) (url.Values, error) {
2020
for i := 0; i < typ.NumField(); i++ {
2121
sf := typ.Field(i)
2222

23-
name := sf.Tag.Get("url")
23+
tag := sf.Tag.Get("url")
24+
name, _ := parseTag(tag)
2425
if name == "" {
2526
name = sf.Name
2627
}

query/encode_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
func TestValues(t *testing.T) {
1111
s := struct {
12-
A string `url:"a"`
12+
A string `url:"a,omitempty"`
1313
B int
1414
}{"abc", 1}
1515
v, err := Values(s)

query/tags.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2011 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package query
6+
7+
import "strings"
8+
9+
// tagOptions is the string following a comma in a struct field's "json"
10+
// tag, or the empty string. It does not include the leading comma.
11+
type tagOptions string
12+
13+
// parseTag splits a struct field's json tag into its name and
14+
// comma-separated options.
15+
func parseTag(tag string) (string, tagOptions) {
16+
if idx := strings.Index(tag, ","); idx != -1 {
17+
return tag[:idx], tagOptions(tag[idx+1:])
18+
}
19+
return tag, tagOptions("")
20+
}
21+
22+
// Contains returns whether checks that a comma-separated list of options
23+
// contains a particular substr flag. substr must be surrounded by a
24+
// string boundary or commas.
25+
func (o tagOptions) Contains(optionName string) bool {
26+
if len(o) == 0 {
27+
return false
28+
}
29+
s := string(o)
30+
for s != "" {
31+
var next string
32+
i := strings.Index(s, ",")
33+
if i >= 0 {
34+
s, next = s[:i], s[i+1:]
35+
}
36+
if s == optionName {
37+
return true
38+
}
39+
s = next
40+
}
41+
return false
42+
}

query/tags_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2011 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package query
6+
7+
import "testing"
8+
9+
func TestTagParsing(t *testing.T) {
10+
name, opts := parseTag("field,foobar,foo")
11+
if name != "field" {
12+
t.Fatalf("name = %q, want field", name)
13+
}
14+
for _, tt := range []struct {
15+
opt string
16+
want bool
17+
}{
18+
{"foobar", true},
19+
{"foo", true},
20+
{"bar", false},
21+
} {
22+
if opts.Contains(tt.opt) != tt.want {
23+
t.Errorf("Contains(%q) = %v", tt.opt, !tt.want)
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)