I am using ajg/form
package to marshal my nested struct to url encoded data.
package main
import (
"fmt"
"bytes"
"github.com/ajg/form"
)
type Subject struct {
SubjectTag string `form:"tag,omitempty"`
SubjectName string `form:"name,omitempty"`
}
type Student struct {
Name string `form:"stud_name,omitempty"`
SubjectList []Subject `form:"subjects,omitempty"`
}
func main() {
student := Student{
Name: "newStudent",
SubjectList: []Subject{
{SubjectTag: "mathstag", SubjectName: "maths"},
{SubjectTag: "englishtag", SubjectName: "english"},
},
}
runParse(student)
}
func runParse(i interface{}) {
buf := new(bytes.Buffer)
form.NewEncoder(buf).Encode(i)
body := buf.String()
fmt.Printf("Body: %#v
", body)
// Prints Body: "subjects.0.name=maths&subjects.0.tag=mathstag&subjects.1.name=english&subjects.1.tag=englishtag&stud_name=newStudent"
//After this I create an HTTP request client, and send a POST request with this body to a server.
}
Problem is my server doesn't understand dot delimited POST body, but it does understand the body in this format - "subjects[0][name]=maths&subjects[0][tag]=mathstag&subjects[1][name]=english&subjects[1][tag]=englishtag&stud_name=newStudent"
, which I have tested with Postman. How can I create a body like this using above struct? Is there any other package I can use?
The ajg/form
package isn't designed to easily do that. form.go
in package form
defines constant defaultDelimiter
to be the period/dot (.
) rune. That's then used in encode.go
and decode.go
in the same package, set as a field value in the Encoder
struct, and then passed in as an argument in calls to methods in node.go
.
You can easily override the default delimiter with a different character, specified as rune r
here:
encoder := form.NewEncoder(buf)
encoder.DelimitWith(r)
Will change the delimiter from dot to whatever you specify as rune r
.
Going beyond that would require overriding several methods, probably by creating intermediary types with the original types embedded in them, and then defining overriding functions where needed. For example, line 27 in node.go
:
y.merge(d, e, p+escape(d, e, k)+string(d), vs)
Would have to be changed so it doesn't just concatenate the delimiter, d
, but rather surrounds with braces (or parens, or quotes, or whatever you set it to use, as it would be best if that were configurable).
You can get a good idea of which areas of the code need to be changed by looking at this diff from when ajg
added support for custom delimiters and escapes: https://github.com/ajg/form/commit/66a87187c6cd884319abb7b97b623e9bb30e075b
If you don't want to take on all those new types and method overrides, you could write your own code to convert the ajg/form
package output to the format you need, or look into configuring/updating your server to recognize a single-character-delimited format.
If a server-side fix isn't easily available, then even better would be to fork/clone the ajg/form
repository, add optional left + right enclosing delimiter support, and submit a pull request after you get it working.