| Index: go/src/infra/libs/jsutil/jsutil.go
|
| diff --git a/go/src/infra/libs/jsutil/jsutil.go b/go/src/infra/libs/jsutil/jsutil.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1899600db96a2bd3dea90d3acea5eb2c144df2cd
|
| --- /dev/null
|
| +++ b/go/src/infra/libs/jsutil/jsutil.go
|
| @@ -0,0 +1,75 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package jsutil
|
| +
|
| +import (
|
| + "fmt"
|
| +)
|
| +
|
| +// Get is like GetError, except that if GetError would return an error, this
|
| +// function panics instead.
|
| +func Get(data interface{}, pathElems ...interface{}) interface{} {
|
| + r, err := GetError(data, pathElems...)
|
| + if err != nil {
|
| + panic(err)
|
| + }
|
| + return r
|
| +}
|
| +
|
| +// GetError retrieves a value from a 'jsonish' data object, given a path to
|
| +// follow.
|
| +//
|
| +// data is assumed to be either a map[string]interface{}, or a []interface{}.
|
| +//
|
| +// pathElems should either be strings or int's. Any other type will cause a
|
| +// panic. So don't do it.
|
| +//
|
| +// A pathElem of a string implies that GetError should expect a map at that
|
| +// location in the jsonish data. An int implies that it should expect a list.
|
| +// If this expectation is false, an error is returned.
|
| +//
|
| +// If you attempt to index into a list such that the index is out of bounds,
|
| +// you'll get a panic just like if you passed an index to a slice that was out
|
| +// of bounds.
|
| +//
|
| +// Accessing a map key which doesn't exist will return nil.
|
| +//
|
| +// Example:
|
| +// data = {
|
| +// "some": [
|
| +// {"nested": {"value": 10}}
|
| +// ]
|
| +// }
|
| +//
|
| +// GetError(data, "some") #=> [{"nested":...}]
|
| +// GetError(data, "some", 0) #=> {"nested":...}
|
| +// GetError(data, "some", 0, "nested") #=> {"value": 10}
|
| +// GetError(data, "some", 0, "nested", "value") #=> 10
|
| +// GetError(data, "wat") #=> nil
|
| +// GetError(data, "wat", "something") #=> panic(nil deref)
|
| +// GetError(data, "some", 1) #=> panic(out of bounds)
|
| +func GetError(data interface{}, pathElems ...interface{}) (interface{}, error) {
|
| + for len(pathElems) > 0 {
|
| + idx := pathElems[0]
|
| + pathElems = pathElems[1:]
|
| + switch i := idx.(type) {
|
| + case int:
|
| + d, ok := data.([]interface{})
|
| + if !ok {
|
| + return nil, fmt.Errorf("jsutil.GetError: expected []interface{}, but got %T", data)
|
| + }
|
| + data = d[i]
|
| + case string:
|
| + d, ok := data.(map[string]interface{})
|
| + if !ok {
|
| + return nil, fmt.Errorf("jsutil.GetError: expected map[string]interface{}, but got %T", data)
|
| + }
|
| + data = d[i]
|
| + default:
|
| + return nil, fmt.Errorf("jsutil.GetError: expected string or int in pathElems, got %T instead", idx)
|
| + }
|
| + }
|
| + return data, nil
|
| +}
|
|
|