Beispiel #1
0
func getResourceField(v interface{}) (f *structs.Field, err error) {
	var ok bool

	if !structs.IsStruct(v) {
		err = errors.New("not a struct")
	} else if f, ok = structs.New(v).FieldOk("Id"); !ok {
		err = errors.New("no 'Id' field")
	} else if _, ok = f.Value().(int); !ok {
		err = errors.New("Id field is not an int")
	}

	return
}
Beispiel #2
0
// Determine whether the struct's id will be omitted in json encoding.
func isIdOmitted(v interface{}) (bool, error) {

	if structs.IsStruct(v) {
		if f, err := getResourceField(v); err != nil {
			return false, err
		} else if jsonTag := f.Tag("json"); jsonTag == "" {
			// No json tag means the id field won't be ommitted.
			return false, nil
		} else {
			// getResourceField() ensures this is an int.
			id := f.Value().(int)
			// Json tags are comma separated. 'omitempty' means id == 0 -> id field
			// not included in generated json. Also note spacing, like "id,
			// omitempty" is significant and prevents a tag from taking effect so no
			// need for trimming.
			//
			// See http://golang.org/pkg/encoding/json/#Marshal
			for _, field := range strings.Split(jsonTag, ",") {
				if field == "omitempty" && id == 0 {
					return true, nil
				}
			}
		}
	} else {
		ty := reflect.TypeOf(v)
		switch ty.Kind() {
		case reflect.Map:
			if _, ok := v.(map[string]interface{}); !ok {
				return false, errors.New("Invalid map")
			} else {
				return false, nil
			}
		case reflect.Ptr:
			return isIdOmitted(reflect.Indirect(reflect.ValueOf(v)).Interface())
		}
	}

	// Id field exists, no 'omitempty' tag so not omitted.
	return false, nil
}