2

I have a route which works with multipart/form-data. All was good before I tried to pass nested objects via postman. There are a lot of code in this function but I removed it for this question because it does not matter.

func (h *handler) SubmitFormNewPark(w http.ResponseWriter, r *http.Request) {
    ctx := context.InitFromHTTP(w, r, "submit_form_new_park")
    defer ctx.OnExit(nil)

    err := r.ParseMultipartForm(0)
    if err != nil {
        logger.Get().Warn(ctx, "can't parse new park form", zap.Error(err))
        h.writeResponse(ctx, w, models.FormParkResponse{Success: false})
        return
    }

    multipartForm := make(map[string]interface{})
    for key, value := range r.MultipartForm.Value {
        multipartForm[key] = value
    }
}

Firstly all was good because I had not nested object

enter image description here

But after I added nested object there are different keys in r.MultipartForm.Value

enter image description here

If I print the r.MultipartForm.Value I get next map

map[city:[city] entity_name:[entity_name] ip_info[ip_address]:[ip_address] ip_info[ip_fio]:[ip_fio] name:[Name] office_address:[office address] office_phone:[74954954949]]

But I expect get "ip_info" key as map with keys ip_address and ip_fio

I also tried to use keys such as ip_info[0][ip_fio] and ip_info[0][ip_address].

2
  • I think that golang parameter parsing just takes the literal name ( as you can see the key in your map). I have only been able to read an array of params on the same key like this. Eg.req.GetParameters("ip_info[ip_fio]"). What I did was send multiple values on the same key and GetParameters will return a string slice with the values from that key. Commented Jan 20, 2021 at 9:28
  • 1
    Unlike with JSON, for example, there is no standard way of nesting objects in multipart/form-data. There are several (incompatible) ways of marshaling complex/nested structures into this type of data. I'm not sure which format postman uses (and maybe it supports multiple ones), but you'll need to find a Go library that's compatible with that format. Or if it's an option, maybe use JSON, or some other more flexible data type instead. Commented Jan 20, 2021 at 10:11

2 Answers 2

2

You can parse nested objects with this code:

Note: You can improove this example to recursively parse nested objects in nested objects

package main

import (
    "fmt"
    "log"
    "net/http"
    "regexp"
)

var rxNestedKey = regexp.MustCompile(`^(?P<key>[A-Za-z0-9_]+)\[(?P<n_key>[A-Za-z0-9_]+)\]$`)

func Handler(w http.ResponseWriter, r *http.Request) {
    err := r.ParseMultipartForm(0)
    if err != nil {

        return
    }

    multipartForm := map[string]interface{}{}
    nestedBuf := map[string]map[string]interface{}{}

    for key, value := range r.MultipartForm.Value {
        // check key has nested key
        if rxNestedKey.MatchString(key) {
            // parse nested key (nK) and key (k)
            k := rxNestedKey.FindStringSubmatch(key)[1]
            nK := rxNestedKey.FindStringSubmatch(key)[2]

            if nestedBuf[k] == nil {
                nestedBuf[k] = map[string]interface{}{}
            }
            nestedBuf[k][nK] = value
        } else {
            multipartForm[key] = value
        }
    }

    // collect all nested data from buff
    for k, v := range nestedBuf {
        multipartForm[k] = v
    }

    fmt.Printf("%+v\n", multipartForm)
}

func main() {
    http.HandleFunc("/", Handler)
    log.Fatal(http.ListenAndServe("localhost:8080", nil))
}

request

Parsed as:

map[ip:map[address:[127.0.0.1] port:[8080]] office_city:[Moscow] office_phone:[7845612349879]]
Sign up to request clarification or add additional context in comments.

Comments

0

This helped me figure out how to pass nested data. Thank you.

postman form-data request with nested data

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.