martini-contrib / binding

Martini handler for mapping and validating a raw request into a structure.
MIT License
140 stars 47 forks source link

Support for nested arrays with structs #40

Open murrekatt opened 9 years ago

murrekatt commented 9 years ago

Thanks for the great work you've done with martini and its companions like binding! :)

Now to the issue...It seems that it isn't possible to have a nested array of some own structs (yes, I saw no tests for it either) like so:

type Foo struct {
  Bars []Bar
}

type Bar struct {
  A string `form:"a"`
  B string `form:"b"`
}

Binding Foo with the above will not work and it ignores the form fields a and b even if they are passed in. Removing the [] and just having a single copy works fine (as you also have in the tests).

Before I start sending a PR I'd like to see what makes sense to do here.

Does it make sense to have an array of structs? I think so. Imagine having a form with a dynamic part where one can add zero or more of some set of fields. It would make sense to have a struct to represent those, and bang!, we have this very problem.

How would that look like on the form side to start with? I see that an array of strings for instance just takes all fields with the name and sticks them into the array. The implication of this is that it's not possible to have different fields with the same name. Would the same principle be a good approach now as well?

I'd like to hear what you guys who have worked on this a longer time have to say. What do you think is a good way to support what I ask for or is it even something you think makes sense to support?

Thanks!

murrekatt commented 9 years ago

The lack of grouping/hierarchy of the fields on the form side is a problem and it would be beneficial to have something that models it as the natural way one arranges the struct(s) like e.g. JSON would do it or a nested key-value store. This would give a namespace that allows for same named fields in different structs.

Let's look at an example. Say we have a Person with many PhoneNumbers and Addresses. It could look like this with a few structs.

type Person struct {
  Name string
  PhoneNumbers []PhoneNumber
  Addresses []Address
}

type PhoneNumber struct {
  CountryCode string
  Number string
}

type Address struct {
  Street string
  City string
  Country string
}

This could be as a JSON message like so

{
"person": {
  "name": "John Doe",
  "phonenumbers": [
    { "countrycode": "41", "number": "1234567890" },
    { "countrycode": "1", "number": "555-1234" }
  ],
  "addresses": [
    { "street": "Calm street 1", "city": "Zürich", "country": "Switzerland" },
    { "street": "Kleinstraße 2", "city": "Berlin", "country": "Germany" },
    { "street": "Le Grand Rue 10", "city": "Toulon", "country": "France" }
  ]
}
}

What about having the form use names in some way that models this too?

murrekatt commented 9 years ago

Here's for reference how Rails does it.

athom commented 8 years ago

hi, any progress on this issue?

mholt commented 8 years ago

(Not from me)

ghostiam commented 7 years ago

I have a ready-made code that does from this:

name=John+Doe&phoneNumber.countryCode=41&phoneNumber.number=1234567890&phoneNumber.countryCode=1&phoneNumber.number=555-1234&address.street=Calm+street+1&address.city=Zürich&address.country=Switzerland&address.street=Kleinstraße+2&address.city=Berlin&address.country=Germany&address.street=Le+Grand+Rue+10&address.city=Toulon&address.country=France

This:

PersonSlice{
            Name:"John Doe",
            PhoneNumbers: []PhoneNumber{
                {CountryCode:"41", Number:"1234567890"},
                {CountryCode:"1", Number:"555-1234"},
            },
            Addresses:[]Address{
                {Street:"Calm street 1", City:"Zürich", Country:"Switzerland"},
                {Street:"Kleinstraße 2", City:"Berlin", Country:"Germany"},
                {Street:"Le Grand Rue 10", City:"Toulon", Country:"France"},
            },
        },

But I uses a non-standard Parameter Naming Conventions (not like in php or Rails)