Filtering JSON output to include/exclude fields?

987 views
Skip to first unread message

Jens-Uwe Mager

unread,
Jan 4, 2014, 4:44:08 PM1/4/14
to golan...@googlegroups.com
I have a structure that I need to dump out in JSON format and depending upon circumstances I have to include or exclude certain fields. Until now I used the field attribute `json:"-"` to avoid serializing internal fields for the client program. But now I would like to dump all database records for backup purposes, now I need all fields. How do I accomplish this? Any pointers?

Alex Zorin

unread,
Jan 4, 2014, 5:55:31 PM1/4/14
to golan...@googlegroups.com
I ran into this problem and didn't find any particularly nice solutions.

1. Use a separate encoding for the backups (such as bson)
2. Use reflect to turn your struct into a map (maybe with https://github.com/mitchellh/mapstructure or encoding/json), and then serialize the map using json.

Alex

Jens-Uwe Mager

unread,
Jan 4, 2014, 7:39:53 PM1/4/14
to golan...@googlegroups.com
Thanks, that got me in the right direction. As a first approximation I use something like this:

func mapOrSliceOf(value interface{}) interface{} {
    v := reflect.Indirect(reflect.ValueOf(value))
    switch v.Kind() {
    case reflect.Slice, reflect.Array:
        switch v.Type().Elem().Kind() {
        case reflect.Uint8:
            return v.Interface()
        default:
            var a []interface{}
            for i := 0; i < v.Len(); i++ {
                a = append(a, mapOrSliceOf(v.Index(i).Interface()))
            }
            return a
        }
    case reflect.Struct:
        switch v.Type().PkgPath() + "." + v.Type().Name() {
        case "time.Time":
            return v.Interface()
        default:
            a := make(map[string]interface{})
            for i := 0; i < v.NumField(); i++ {
                a[v.Type().Field(i).Name] = mapOrSliceOf(v.Field(i).Interface())
            }
            return a
        }
    case reflect.Bool, reflect.Int, reflect.Uint, reflect.Float32, reflect.Float64, reflect.String:
        return v.Interface()
    default:
        panic("mapOrSliceOf: cannot handle type " + v.Kind().String())
    }
    return nil
}
Reply all
Reply to author
Forward
0 new messages