package statsapi import ( "encoding/json" "errors" "log" "strconv" "strings" ) type FeedParams struct { GamePk string } type FeedResponse map[string]any type Play struct { Result result About about AtBatIndex int } type result struct { Event string Description string RBI int AwayScore int HomeScore int } type about struct { AtBatIndex json.Number IsTopInning bool Inning json.Number IsScoringPlay bool CaptivatingIndex json.Number } func expand(arr []any, idx int) []any { var all []any if idx < len(arr) { all = arr } else { all = make([]any, idx+1) copy(all[:len(arr)], arr) all[idx] = make(map[string]any) } return all } func setLeaf(obj any, key string, value any) error { var err error switch v := obj.(type) { case map[string]any: log.Println("Formerly", v[key]) v[key] = value log.Println("Now", v[key]) case []any: idx, err := strconv.Atoi(key) if err != nil { break } v = expand(v, idx) log.Println("Formerly", v[idx]) v[idx] = value log.Println("Now", v[idx]) default: err = errors.New("couldn't determine type") } return err } func getLeaf(key string, obj any) (any, error) { switch v := obj.(type) { case map[string]any: val, ok := v[key] if !ok { return nil, errors.New("invalid key") } return val, nil case []any: idx, err := strconv.Atoi(key) if err != nil { return nil, err } if idx < 0 || idx >= len(v) { return nil, errors.New("invalid index") } return v[idx], nil default: return nil, errors.New("couldn't determine type") } } func set(path string, obj any, value any) error { elems := strings.Split(path, "/") leaf := elems[len(elems)-1] leafPath := strings.Join(elems[:len(elems)-1], "/") parent, err := get(leafPath, obj) if err != nil { return err } err = setLeaf(parent, leaf, value) return err } func get(path string, obj any) (any, error) { var err error first, rest, found := strings.Cut(path, "/") log.Println(first, rest) if !found { return getLeaf(first, obj) } else if first == "" { return get(rest, obj) } switch v := obj.(type) { case map[string]any: val, ok := v[first] if !ok { return v, errors.New("invalid key") } return get(rest, val) case []any: idx, err := strconv.Atoi(first) if err != nil { break } if idx < 0 || idx >= len(v) { return v, errors.New("invalid index") } return get(rest, v[idx]) default: err = errors.New("couldn't determine type") } return obj, err } func (f *FeedResponse) Patch(instr *instruction) error { // TODO: need to handle each type of instruction separately: add, // replace, remove, copy, move log.Println("updating", instr.Path) err := set(instr.Path, map[string]any(*f), instr.Value) return err }