在Go语言中解析嵌入式结构的表单值。

huangapple go评论96阅读模式
英文:

Parse embedded Struct form values in GoLang

问题

我有一个包含另一个结构体数组的结构体,例如:

type Struct1 struct {
  Value string
  Items []Struct2
}

type Struct2 struct {
  Value string
}

我正在使用gorilla schema将我的表单值解码为Struct1。嵌套结构体Struct2的值没有传递过来。

当我查看FormValue("Struct2")的日志时,返回的是'[Object object], [Object object]'。

非常感谢任何帮助。

编辑
表单的结构示例:

使用AngularJS:

var data = $scope.struct1;
$http({
  method: 'POST',
  url: url,
  data: data,
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  transformRequest: function(obj) {
    var str = [];
    for (var p in obj)
      str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
    return str.join("&");
  }
})
.then(function successCallback(response) {
  console.log(response);
}, function errorCallback(response) {

});
英文:

I have a struct that includes an array of another struct, eg

type Struct1 struct {
  Value         string
  Items         []Struct2
}
type Struct2 struct {
  Value         string
}

I am using gorilla schema to decode my Form values into Struct 1.
The values for the embedded struct, Struct 2, are not coming through.

When I look at the logs for the FormValue("Struct2") it returns '[Object object], [Object object]'

Any help would be greatly appreciated

EDIT
An example of the structure of the form,

Using AngularJS,

var data = $scope.struct1;
$http({
      method: 'POST',
        url:url, 
        data : data, 
        headers : {'Content-Type': 'application/x-www-form-urlencoded'},
        transformRequest: function(obj) {
        var str = [];
        for(var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj

)); return str.join("&"); } }) .then(function successCallback(response) { console.log(response); }, function errorCallback(response) { });

答案1

得分: 1

可能是你的HTML表单的结构设计不正确。你可能需要提交你的输入和/或HTML表单设计。

gorilla/schemadecode函数期望以map[string][]string类型的变量作为值输入,你可以从文档中的示例和包中的测试文件中看到。下面是一个简单的完整脚本,它只是包装了文档中的示例并打印结果:

package main

import (
    "fmt"
    "github.com/gorilla/schema"
)

type Person struct {
    Name  string
    Phone string
}

func main() {
    values := map[string][]string{
        "Name":  {"John"},
        "Phone": {"999-999-999"},
    }
    person := new(Person)
    decoder := schema.NewDecoder()
    decoder.Decode(person, values)
    fmt.Printf("Person: %v\n", person)
}

输出结果为Person: &{John 999-999-999}

这是map[string][]string类型的正确字面量形式,你可以通过声明和赋值来验证它,然后运行它而不会出错:

var values map[string][]string
values = map[string][]string{
    "Name":  {"John"},
    "Phone": {"999-999-999"},
}

现在,map[string][]string显然不支持gorilla/schema支持的所有类型,比如你问题中的类型:结构体的切片。但是HTML表单的处理使得翻译是有意义的:它会不断追加索引和字段名,并使用点分隔符创建所需的结构。所以对于你在问题中发布的类型,我编写了以下脚本将值解码到结构体中:

package main

import (
    "fmt"
    "github.com/gorilla/schema"
)

type Struct1 struct {
    Value string
    Items []Struct2
}

type Struct2 struct {
    Value string
}

func main() {
    values := map[string][]string{
        "Value":          {"the thing with the items"},
        "Items.0.Value":  {"a"},
        "Items.1.Value":  {"b"},
        "Items.2.Value":  {"c"},
    }
    s1 := new(Struct1)
    decoder := schema.NewDecoder()
    decoder.Decode(s1, values)
    fmt.Printf("S1: %v\n", s1)
}

运行结果为:

S1: &{the thing with the items [{a} {b} {c}]}

这证明了如果输入与结构设计匹配,decode函数可以成功填充你的结构体设计。

因此,你可以尝试验证你的输入是否符合这个模式——它是否具有类似数组索引和带有点分隔符的字段名,以符合你的结构设计。如果不符合,那就意味着你的结构设计需要更新以适应输入的格式。

你可以在gorilla/schema包的decode_test.go文件中看到对这种类型结构的解码示例,比如以下代码:

type Foo struct {
    F01 int
    F02 Bar
    Bif []Baz
}

type Bar struct {
    F01 string
    F02 string
    F03 string
    F14 string
    S05 string
    Str string
}

type Baz struct {
    F99 []string
}

func TestSimpleExample(t *testing.T) {
    data := map[string][]string{
        "F01":       {"1"},
        "F02.F01":   {"S1"},
        "F02.F02":   {"S2"},
        "F02.F03":   {"S3"},
        "F02.F14":   {"S4"},
        "F02.S05":   {"S5"},
        "F02.Str":   {"Str"},
        "Bif.0.F99": {"A", "B", "C"},
    }

Foo结构体有一个名为Bif的字段,类型为[]BazBaz是一个结构体,所以我们有了一个结构体切片类型,就像你的问题中一样。Baz有一个名为F99的字段。你可以看到输入使用字符串值"Bif.0.F99"进行引用。

你可以将这个文件中的示例和其他示例作为参考。

英文:

It's possible that you don't have the right struct design for your HTML form. You might want to post your input and/or your HTML form design.

gorilla/schema's decode expects the values input to be passed as a variable of type map[string][]string, as you can see both from the example in the documentation and from the test files in the package. Here's a simple complete script that just wraps the example from the documentation and prints the result:

package main

import(
    "fmt"
    "github.com/gorilla/schema"
)

type Person struct {
    Name  string
    Phone string
}

func main() {
    values := map[string][]string{
        "Name":  {"John"},
        "Phone": {"999-999-999"},
    }
    person := new(Person)
    decoder := schema.NewDecoder()
    decoder.Decode(person, values)
    fmt.Printf("Person: %v\n", person)
}

That outputs Person: &{John 999-999-999}.

That is the correct form for a map literal of type map[string][]string, as you can demonstrate by performing a declaration followed by an assignment and running it without error:

var values map[string][]string
values = map[string][]string{
    "Name":  {"John"},
    "Phone": {"999-999-999"},
}

Now map[string][]string doesn't obviously support all the types that gorilla/schema supports, such as the type in your question: slices of structs. But the HTML form is processed such that a translation makes sense: it keeps appending indices and field names with dot separators to create the desired structure. So for the types you posted in your question, I wrote this script to decode values into the structs:

package main

import(
    "fmt"
    "github.com/gorilla/schema"
)

type Struct1 struct {
  Value         string
  Items         []Struct2
}

type Struct2 struct {
  Value         string
}

func main() {
    values := map[string][]string{
        "Value": {"the thing with the items"},
        "Items.0.Value": {"a"},
        "Items.1.Value": {"b"},
        "Items.2.Value": {"c"},
    }
    s1 := new(Struct1)
    decoder := schema.NewDecoder()
    decoder.Decode(s1, values)
    fmt.Printf("S1: %v\n", s1)
}

Running that outputs:

S1: &{the thing with the items [{a} {b} {c}]}

That demonstrates that decode can populate your struct design without error, if its input matches that design.

So you might try to verify that your input matches that scheme -- that it has those array-like indices and field names with the dot separator in a way that conforms to your struct design. And if it does not, that indicates that your struct design needs to be updated to fit the format of your input.

You can see examples of decode working on this type of structure in the decode_test.go file in the gorilla/schema package, such as these lines:

type Foo struct {
	F01 int
	F02 Bar
	Bif []Baz
}

type Bar struct {
	F01 string
	F02 string
	F03 string
	F14 string
	S05 string
	Str string
}

type Baz struct {
	F99 []string
}

func TestSimpleExample(t *testing.T) {
	data := map[string][]string{
		"F01":       {"1"},
		"F02.F01":   {"S1"},
		"F02.F02":   {"S2"},
		"F02.F03":   {"S3"},
		"F02.F14":   {"S4"},
		"F02.S05":   {"S5"},
		"F02.Str":   {"Str"},
		"Bif.0.F99": {"A", "B", "C"},
}

The Foo struct has a field named Bif of type []Baz. Baz is a struct -- so we have a slice of structs type, like in your question. Baz has a field named F99. You can see that the input is referenced with the string value "Bif.0.F99".

Use this and other examples in the test file as your guide.

huangapple
  • 本文由 发表于 2017年5月24日 19:31:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/44157149.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定