arrays - decoding nested json objects in go -


i found posts on how decoding json nested objects in go, tried apply answers problem, managed find partial solution.

my json file this:

{ "user":{     "gender":"male",     "age":"21-30",     "id":"80b1ea88-19d7-24e8-52cc-65cf6fb9b380"     }, "trials":{     "0":{"index":0,"word":"word 1","time":3000,"keyboard":true,"train":true,"type":"a"},     "1":{"index":1,"word":"word 2","time":3000,"keyboard":true,"train":true,"type":"a"},     }, "answers":{     "training":[         {"ans":0,"rt":null,"gtans":"word 1","correct":0},         {"ans":0,"rt":null,"gtans":"word 2","correct":0}         ],     "test":[         {"ans":0,"rt":null,"gtans":true,"correct":0},         {"ans":0,"rt":null,"gtans":true,"correct":0}         ]     } } 

basically need parse information inside , save them go structure. code below managed extract user information, looks complicated me , won't easy apply same thing "answers" fields contains 2 arrays more 100 entries each. here code i'm using now:

type userdetails struct {     id     string `json:"id"`     age    string `json:"age"`     gender string `json:"gender"` }  type jsonrawdata map[string]interface { }  func getjsoncontent(r *http.request) ( userdetails) {     defer r.body.close()     jsonbody, err := ioutil.readall(r.body)     var userdatacurr userdetails     if err != nil {         log.printf("couldn't read request body: %s", err)     } else {         var f jsonrawdata         err := json.unmarshal(jsonbody, &f)         if err != nil {             log.printf("error unmashalling: %s", err)         } else {             user := f["user"].(map[string]interface{})             userdatacurr.id = user["id"].(string)             userdatacurr.gender = user["gender"].(string)             userdatacurr.age = user["age"].(string)         }     }     return userdatacurr } 

any suggestions? lot!

you're doing hard way using interface{} , not taking advantage of encoding/json gives you.

i'd (note assumed there error type of "gtans" field , made boolean, don't give enough information know "rt" field):

package main  import (         "encoding/json"         "fmt"         "io"         "log"         "strconv"         "strings" )  const input = `{ "user":{     "gender":"male",     "age":"21-30",     "id":"80b1ea88-19d7-24e8-52cc-65cf6fb9b380"     }, "trials":{     "0":{"index":0,"word":"word 1","time":3000,"keyboard":true,"train":true,"type":"a"},     "1":{"index":1,"word":"word 2","time":3000,"keyboard":true,"train":true,"type":"a"}     }, "answers":{     "training":[         {"ans":0,"rt":null,"gtans":true,"correct":0},         {"ans":0,"rt":null,"gtans":true,"correct":0}         ],     "test":[         {"ans":0,"rt":null,"gtans":true,"correct":0},         {"ans":0,"rt":null,"gtans":true,"correct":0}         ]     } }`  type whatever struct {         user struct {                 gender gender   `json:"gender"`                 age    range    `json:"age"`                 id     idstring `json:"id"`         } `json:"user"`         trials map[string]struct {                 index int    `json:"index"`                 word  string `json:"word"`                 time  int    // should time.duration?                 train bool   `json:"train"`                 type  string `json:"type"`         } `json:"trials"`         answers map[string][]struct {                 answer    int             `json:"ans"`                 rt        json.rawmessage // ??? type                 gotanswer bool            `json:"gtans"`                 correct   int             `json:"correct"`         } `json:"answers"` }  // using custom types show custom marshalling:  type idstring string // todo custom unmarshal , format/error checking  type gender int  const (         male gender = iota         female )  func (g *gender) unmarshaljson(b []byte) error {         var s string         err := json.unmarshal(b, &s)         if err != nil {                 return err         }         switch strings.tolower(s) {         case "male":                 *g = male         case "female":                 *g = female         default:                 return fmt.errorf("invalid gender %q", s)         }         return nil } func (g gender) marshaljson() ([]byte, error) {         switch g {         case male:                 return []byte(`"male"`), nil         case female:                 return []byte(`"female"`), nil         default:                 return nil, fmt.errorf("invalid gender %v", g)         } }  type range struct{ min, max int }  func (r *range) unmarshaljson(b []byte) error {         // xxx improved         _, err := fmt.sscanf(string(b), `"%d-%d"`, &r.min, &r.max)         return err } func (r range) marshaljson() ([]byte, error) {         return []byte(fmt.sprintf(`"%d-%d"`, r.min, r.max)), nil         // or:         b := make([]byte, 0, 8)         b = append(b, '"')         b = strconv.appendint(b, int64(r.min), 10)         b = append(b, '-')         b = strconv.appendint(b, int64(r.max), 10)         b = append(b, '"')         return b, nil }  func fromjson(r io.reader) (whatever, error) {         var x whatever         dec := json.newdecoder(r)         err := dec.decode(&x)         return x, err }  func main() {         // use http.get or whatever io.reader,         // (e.g. response.body).         // playground, substitute fixed string         r := strings.newreader(input)          // if had string or []byte:         //     var x whatever         //     err := json.unmarshal([]byte(input), &x)          x, err := fromjson(r)         if err != nil {                 log.fatal(err)         }         fmt.println(x)         fmt.printf("%+v\n", x)          b, err := json.marshalindent(x, "", "  ")         if err != nil {                 log.fatal(err)         }         fmt.printf("re-marshalled: %s\n", b)  } 

playground

of course if want reuse sub-types pull them out of "whatever" type own named types.

also, note use of json.decoder rather reading in data ahead of time. try , avoid use of ioutil.readall unless need data @ once.


Comments

Popular posts from this blog

android - MPAndroidChart - How to add Annotations or images to the chart -

javascript - Add class to another page attribute using URL id - Jquery -

firefox - Where is 'webgl.osmesalib' parameter? -