The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/pkg/util/json.go

113 lines
3.8 KiB

package util
import (
"encoding/json"
"github.com/jmespath/go-jmespath"
"github.com/grafana/grafana/pkg/util/errutil"
)
pkg/util/*: Add missing function comments. See, $ gometalinter --vendor --deadline 10m --disable-all --enable=golint ./... encoding.go:15:1:warning: comment on exported function GetRandomString should be of the form "GetRandomString ..." (golint) encoding.go:30:1:warning: exported function EncodePassword should have comment or be unexported (golint) encoding.go:35:1:warning: comment on exported function EncodeMd5 should be of the form "EncodeMd5 ..." (golint) encoding.go:42:1:warning: comment on exported function PBKDF2 should be of the form "PBKDF2 ..." (golint) encoding.go:80:1:warning: exported function GetBasicAuthHeader should have comment or be unexported (golint) encoding.go:85:1:warning: exported function DecodeBasicAuthHeader should have comment or be unexported (golint) encoding.go:105:1:warning: exported function RandomHex should have comment or be unexported (golint) encryption.go:14:1:warning: exported function Decrypt should have comment or be unexported (golint) encryption.go:39:1:warning: exported function Encrypt should have comment or be unexported (golint) ip.go:7:1:warning: exported function SplitIpPort should have comment or be unexported (golint) json.go:3:6:warning: exported type DynMap should have comment or be unexported (golint) md5.go:22:1:warning: comment on exported function Md5SumString should be of the form "Md5SumString ..." (golint) strings.go:10:1:warning: exported function StringsFallback2 should have comment or be unexported (golint) strings.go:14:1:warning: exported function StringsFallback3 should have comment or be unexported (golint) strings.go:27:1:warning: exported function SplitString should have comment or be unexported (golint) strings.go:35:1:warning: exported function GetAgeString should have comment or be unexported (golint) url.go:8:6:warning: exported type UrlQueryReader should have comment or be unexported (golint) url.go:12:1:warning: exported function NewUrlQueryReader should have comment or be unexported (golint) url.go:23:1:warning: exported method UrlQueryReader.Get should have comment or be unexported (golint) url.go:32:1:warning: exported function JoinUrlFragments should have comment or be unexported (golint) validation.go:16:1:warning: exported function IsEmail should have comment or be unexported (golint)
6 years ago
// DynMap defines a dynamic map interface.
type DynMap map[string]any
var (
// ErrEmptyJSON is an error for empty attribute in JSON.
ErrEmptyJSON = errutil.NewBase(errutil.StatusBadRequest,
"json-missing-body", errutil.WithPublicMessage("Empty JSON provided"))
// ErrNoAttributePathSpecified is an error for no attribute path specified.
ErrNoAttributePathSpecified = errutil.NewBase(errutil.StatusBadRequest,
"json-no-attribute-path-specified", errutil.WithPublicMessage("No attribute path specified"))
// ErrFailedToUnmarshalJSON is an error for failure in unmarshalling JSON.
ErrFailedToUnmarshalJSON = errutil.NewBase(errutil.StatusBadRequest,
"json-failed-to-unmarshal", errutil.WithPublicMessage("Failed to unmarshal JSON"))
// ErrFailedToSearchJSON is an error for failure in searching JSON.
ErrFailedToSearchJSON = errutil.NewBase(errutil.StatusBadRequest,
"json-failed-to-search", errutil.WithPublicMessage("Failed to search JSON with provided path"))
)
// SearchJSONForStringSliceAttr searches for a slice attribute in a JSON object and returns a string slice.
// The attributePath parameter is a string that specifies the path to the attribute.
// The data parameter is the JSON object that we're searching. It can be a byte slice or a go type.
func SearchJSONForStringSliceAttr(attributePath string, data any) ([]string, error) {
val, err := searchJSONForAttr(attributePath, data)
if err != nil {
return []string{}, err
}
ifArr, ok := val.([]any)
if !ok {
return []string{}, nil
}
result := []string{}
for _, v := range ifArr {
if strVal, ok := v.(string); ok {
result = append(result, strVal)
}
}
return result, nil
}
// SearchJSONForStringAttr searches for a specific attribute in a JSON object and returns a string.
// The attributePath parameter is a string that specifies the path to the attribute.
// The data parameter is the JSON object that we're searching. It can be a byte slice or a go type.
func SearchJSONForStringAttr(attributePath string, data any) (string, error) {
val, err := searchJSONForAttr(attributePath, data)
if err != nil {
return "", err
}
strVal, ok := val.(string)
if ok {
return strVal, nil
}
return "", nil
}
// searchJSONForAttr searches for a specific attribute in a JSON object.
// The attributePath parameter is a string that specifies the path to the attribute.
// The data parameter is the JSON object that we're searching.
// The function returns the value of the attribute and an error if one occurred.
func searchJSONForAttr(attributePath string, data any) (any, error) {
// If no attribute path is specified, return an error
if attributePath == "" {
return "", ErrNoAttributePathSpecified.Errorf("attribute path: %q", attributePath)
}
// If the data is nil, return an error
if data == nil {
return "", ErrEmptyJSON.Errorf("empty json, attribute path: %q", attributePath)
}
// Copy the data to a new variable
var jsonData = data
// If the data is a byte slice, try to unmarshal it into a JSON object
if dataBytes, ok := data.([]byte); ok {
// If the byte slice is empty, return an error
if len(dataBytes) == 0 {
return "", ErrEmptyJSON.Errorf("empty json, attribute path: %q", attributePath)
}
// Try to unmarshal the byte slice
if err := json.Unmarshal(dataBytes, &jsonData); err != nil {
return "", ErrFailedToUnmarshalJSON.Errorf("%v: %w", "failed to unmarshal user info JSON response", err)
}
}
// Search for the attribute in the JSON object
value, err := jmespath.Search(attributePath, jsonData)
if err != nil {
return "", ErrFailedToSearchJSON.Errorf("failed to search user info JSON response with provided path: %q: %w", attributePath, err)
}
// Return the value and nil error
return value, nil
}