Removing fields from struct or hiding them in JSON Response

后端 未结 13 1417
孤街浪徒
孤街浪徒 2020-12-12 09:37

I\'ve created an API in Go that, upon being called, performs a query, creates an instance of a struct, and then encodes that struct as JSON before sending back to the caller

13条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-12 10:24

    Take three ingredients:

    1. The reflect package to loop over all the fields of a struct.

    2. An if statement to pick up the fields you want to Marshal, and

    3. The encoding/json package to Marshal the fields of your liking.

    Preparation:

    1. Blend them in a good proportion. Use reflect.TypeOf(your_struct).Field(i).Name() to get a name of the ith field of your_struct.

    2. Use reflect.ValueOf(your_struct).Field(i) to get a type Value representation of an ith field of your_struct.

    3. Use fieldValue.Interface() to retrieve the actual value (upcasted to type interface{}) of the fieldValue of type Value (note the bracket use - the Interface() method produces interface{}

    If you luckily manage not to burn any transistors or circuit-breakers in the process you should get something like this:

    func MarshalOnlyFields(structa interface{},
        includeFields map[string]bool) (jsona []byte, status error) {
        value := reflect.ValueOf(structa)
        typa := reflect.TypeOf(structa)
        size := value.NumField()
        jsona = append(jsona, '{')
        for i := 0; i < size; i++ {
            structValue := value.Field(i)
            var fieldName string = typa.Field(i).Name
            if marshalledField, marshalStatus := json.Marshal((structValue).Interface()); marshalStatus != nil {
                return []byte{}, marshalStatus
            } else {
                if includeFields[fieldName] {
                    jsona = append(jsona, '"')
                    jsona = append(jsona, []byte(fieldName)...)
                    jsona = append(jsona, '"')
                    jsona = append(jsona, ':')
                    jsona = append(jsona, (marshalledField)...)
                    if i+1 != len(includeFields) {
                        jsona = append(jsona, ',')
                    }
                }
            }
        }
        jsona = append(jsona, '}')
        return
    }
    

    Serving:

    serve with an arbitrary struct and a map[string]bool of fields you want to include, for example

    type magic struct {
        Magic1 int
        Magic2 string
        Magic3 [2]int
    }
    
    func main() {
        var magic = magic{0, "tusia", [2]int{0, 1}}
        if json, status := MarshalOnlyFields(magic, map[string]bool{"Magic1": true}); status != nil {
            println("error")
        } else {
            fmt.Println(string(json))
        }
    
    }
    

    Bon Appetit!

提交回复
热议问题