157
jsonx/json.go
Normal file
157
jsonx/json.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package jsonx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ToRawMessage(i interface{}, defaultValue string) (json.RawMessage, error) {
|
||||
m := json.RawMessage{}
|
||||
var b []byte
|
||||
var err error
|
||||
b, err = json.Marshal(&i)
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
|
||||
b = bytes.TrimSpace(b)
|
||||
if len(b) == 0 || bytes.EqualFold(b, []byte("null")) {
|
||||
b = []byte(defaultValue)
|
||||
}
|
||||
err = m.UnmarshalJSON(b)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// ToJson Change interface to json string
|
||||
func ToJson(i interface{}, defaultValue string) string {
|
||||
if i == nil {
|
||||
return defaultValue
|
||||
}
|
||||
vo := reflect.ValueOf(i)
|
||||
switch vo.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
|
||||
if vo.IsNil() {
|
||||
return defaultValue
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
b, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err = json.Compact(&buf, b)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
if json.Valid(buf.Bytes()) {
|
||||
return buf.String()
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func ToPrettyJson(i interface{}) string {
|
||||
if i == nil {
|
||||
return "null"
|
||||
}
|
||||
vo := reflect.ValueOf(i)
|
||||
switch vo.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
|
||||
if vo.IsNil() {
|
||||
return "null"
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
b, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("%+v", i)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err = json.Indent(&buf, b, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Sprintf("%+v", i)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// EmptyObjectRawMessage 空对象
|
||||
func EmptyObjectRawMessage() json.RawMessage {
|
||||
v := json.RawMessage{}
|
||||
_ = v.UnmarshalJSON([]byte("{}"))
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// EmptyArrayRawMessage 空数组
|
||||
func EmptyArrayRawMessage() json.RawMessage {
|
||||
v := json.RawMessage{}
|
||||
_ = v.UnmarshalJSON([]byte("[]"))
|
||||
return v
|
||||
}
|
||||
|
||||
// IsEmptyRawMessage 验证数据是否为空
|
||||
func IsEmptyRawMessage(data json.RawMessage) bool {
|
||||
if data == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
b, err := data.MarshalJSON()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
s := string(bytes.TrimSpace(b))
|
||||
if s == "" || s == "[]" || s == "{}" || strings.EqualFold(s, "null") {
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.Index(s, " ") != -1 {
|
||||
s = strings.ReplaceAll(s, " ", "")
|
||||
}
|
||||
return s == "[]" || s == "{}"
|
||||
}
|
||||
|
||||
func Convert(from json.RawMessage, to any) error {
|
||||
if IsEmptyRawMessage(from) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var b []byte
|
||||
b, err := from.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(b, &to)
|
||||
}
|
||||
|
||||
// Extract 提取字符串中的有效 JSON 数据
|
||||
// 比如 `{"a": 1, "b": 2}}}}a` 提取后的数据为 `{"a": 1, "b": 2}`
|
||||
func Extract(str string) (string, error) {
|
||||
str = strings.TrimSpace(str)
|
||||
n := len(str)
|
||||
if n == 0 {
|
||||
return "", errors.New("jsonx: empty string")
|
||||
}
|
||||
if json.Valid([]byte(str)) {
|
||||
return str, nil
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
if str[i] == '{' || str[i] == '[' {
|
||||
for j := n; j > i; j-- {
|
||||
substr := str[i:j]
|
||||
if json.Valid([]byte(substr)) {
|
||||
return substr, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", errors.New("jsonx: not found")
|
||||
}
|
||||
166
jsonx/json_test.go
Normal file
166
jsonx/json_test.go
Normal file
@@ -0,0 +1,166 @@
|
||||
package jsonx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestToJson(t *testing.T) {
|
||||
var names []string
|
||||
testCases := []struct {
|
||||
Number int
|
||||
Value interface{}
|
||||
DefaultValue string
|
||||
Except string
|
||||
}{
|
||||
{1, []string{}, "[]", "[]"},
|
||||
{2, struct{}{}, "", "{}"},
|
||||
{3, struct {
|
||||
Name string
|
||||
Age int
|
||||
}{"Hello", 12}, "", `{"Name":"hello","Age":12}`},
|
||||
{4, struct {
|
||||
Name string `json:"a"`
|
||||
Age int `json:"b"`
|
||||
}{"Hello", 12}, "", `{"a":"hello","b":12}`},
|
||||
{5, nil, "abc", "abc"},
|
||||
{6, []int{1, 2}, "null", "[1,2]"},
|
||||
{7, []string{"a", "b"}, "null", `["a","b"]`},
|
||||
{8, 1, "[]", "1"},
|
||||
{9, "abc", "[]", `"abc"`},
|
||||
{10, nil, "[]", `[]`},
|
||||
{11, names, "[]", `[]`},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
s := ToJson(testCase.Value, testCase.DefaultValue)
|
||||
if !strings.EqualFold(s, testCase.Except) {
|
||||
t.Errorf("%d %#v except: %s actual: %s", testCase.Number, testCase.Value, testCase.Except, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyObject(t *testing.T) {
|
||||
result := "{}"
|
||||
if b, err := EmptyObjectRawMessage().MarshalJSON(); err == nil {
|
||||
eValue := string(b)
|
||||
if !strings.EqualFold(eValue, result) {
|
||||
t.Errorf("Excepted value: %s, actual value: %s", eValue, result)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyArray(t *testing.T) {
|
||||
result := "[]"
|
||||
if b, err := EmptyArrayRawMessage().MarshalJSON(); err == nil {
|
||||
eValue := string(b)
|
||||
if !strings.EqualFold(eValue, result) {
|
||||
t.Errorf("Excepted value: %s, actual value: %s", eValue, result)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEmptyRawMessage(t *testing.T) {
|
||||
type testCase struct {
|
||||
Number int
|
||||
Value json.RawMessage
|
||||
Empty bool
|
||||
}
|
||||
v1, _ := ToRawMessage([]string{}, "[]")
|
||||
v2, _ := ToRawMessage([]string{"a", "b"}, "[]")
|
||||
v3, _ := ToRawMessage([]int{1, 2, 3}, "[]")
|
||||
v4, _ := ToRawMessage(struct {
|
||||
Name string
|
||||
Age int
|
||||
}{"John", 10}, "{}")
|
||||
v5, _ := ToRawMessage(nil, "[]")
|
||||
a := json.RawMessage{}
|
||||
a.UnmarshalJSON([]byte("null"))
|
||||
b := json.RawMessage{}
|
||||
b.UnmarshalJSON([]byte(""))
|
||||
c := json.RawMessage{}
|
||||
c.UnmarshalJSON([]byte("[ ]"))
|
||||
testCases := []testCase{
|
||||
{1, json.RawMessage{}, true},
|
||||
{2, EmptyObjectRawMessage(), true},
|
||||
{3, EmptyArrayRawMessage(), true},
|
||||
{4, v1, true},
|
||||
{5, v2, false},
|
||||
{6, v3, false},
|
||||
{7, v4, false},
|
||||
{8, v5, true},
|
||||
{9, a, true},
|
||||
{10, b, true},
|
||||
{11, c, true},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
v := IsEmptyRawMessage(tc.Value)
|
||||
if v != tc.Empty {
|
||||
t.Errorf("%d except: %v, actual: %v", tc.Number, tc.Empty, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvert(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Number int
|
||||
From json.RawMessage
|
||||
Except any
|
||||
}{
|
||||
{1, nil, struct{}{}},
|
||||
{2, EmptyArrayRawMessage(), []struct{}{}},
|
||||
{3, []byte(`{"ID":1,"Name":"hiscaler"}`), struct {
|
||||
ID int
|
||||
Name string
|
||||
}{}},
|
||||
{4, []byte(`{"ID":1,"Name":"hiscaler","age":1}`), struct {
|
||||
ID int
|
||||
Name string
|
||||
age int
|
||||
}{}},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
exceptValue := testCase.Except
|
||||
err := Convert(testCase.From, &exceptValue)
|
||||
assert.Equalf(t, nil, err, "Test %d", testCase.Number)
|
||||
actualValue := ""
|
||||
if testCase.From != nil {
|
||||
actualValue = ToJson(exceptValue, "null")
|
||||
}
|
||||
t.Logf(`
|
||||
#%d %s
|
||||
↓
|
||||
%#v`, testCase.Number, testCase.From, exceptValue)
|
||||
assert.Equalf(t, string(testCase.From), actualValue, "Test %d", testCase.Number)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtract(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Number int
|
||||
From string
|
||||
Except string
|
||||
HasError bool
|
||||
}{
|
||||
{1, "", "", true},
|
||||
{2, "{}", "{}", false},
|
||||
{3, " {} ", "{}", false},
|
||||
{4, `{"a": 1, "b": 2}`, `{"a": 1, "b": 2}`, false},
|
||||
{5, `{"a": 1, "b": 2}}}}a`, `{"a": 1, "b": 2}`, false},
|
||||
{6, `{"a": 1, "b": 2}}}}<!--This page has been excluded -->`, `{"a": 1, "b": 2}`, false},
|
||||
{7, "[]", "[]", false},
|
||||
{8, "[]1[]2", "[]", false},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
exceptValue := testCase.Except
|
||||
actualValue, err := Extract(testCase.From)
|
||||
assert.Equalf(t, testCase.HasError, err != nil, "Test HasError %d", testCase.Number)
|
||||
assert.Equalf(t, exceptValue, actualValue, "Test Value %d", testCase.Number)
|
||||
}
|
||||
}
|
||||
246
jsonx/parser.go
Normal file
246
jsonx/parser.go
Normal file
@@ -0,0 +1,246 @@
|
||||
package jsonx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.cloudyne.io/go/hiscaler-gox/bytex"
|
||||
"git.cloudyne.io/go/hiscaler-gox/stringx"
|
||||
)
|
||||
|
||||
// Parser is a json string parse helper and not required define struct.
|
||||
// You can use Find() method get the path value, and convert to string, int, int64, float32, float64, bool value.
|
||||
// And you can use Exists() method check path is exists
|
||||
// Usage:
|
||||
// parser := jsonx.NewParser("[0,1,2]")
|
||||
// parser.Find("1").Int() // Return 1, founded
|
||||
// parser.Find("10", 0).Int() // Return 0 because not found, you give a default value 0
|
||||
|
||||
type Parser struct {
|
||||
data reflect.Value
|
||||
value reflect.Value
|
||||
}
|
||||
|
||||
type ParseFinder Parser
|
||||
|
||||
func (pf ParseFinder) Interface() interface{} {
|
||||
return pf.value.Interface()
|
||||
}
|
||||
|
||||
func (pf ParseFinder) String() string {
|
||||
switch pf.value.Kind() {
|
||||
case reflect.Invalid:
|
||||
return ""
|
||||
default:
|
||||
return stringx.String(pf.value.Interface())
|
||||
}
|
||||
}
|
||||
|
||||
func (pf ParseFinder) Float32() float32 {
|
||||
switch pf.value.Kind() {
|
||||
case reflect.Invalid:
|
||||
return 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return float32(pf.value.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return float32(pf.value.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return float32(pf.value.Float())
|
||||
case reflect.Bool:
|
||||
if pf.value.Bool() {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case reflect.String:
|
||||
d, err := strconv.ParseFloat(pf.value.String(), 32)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return float32(d)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (pf ParseFinder) Float64() float64 {
|
||||
switch pf.value.Kind() {
|
||||
case reflect.Invalid:
|
||||
return 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return float64(pf.value.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return float64(pf.value.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return pf.value.Float()
|
||||
case reflect.Bool:
|
||||
if pf.value.Bool() {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case reflect.String:
|
||||
d, _ := strconv.ParseFloat(pf.value.String(), 64)
|
||||
return d
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (pf ParseFinder) Int() int {
|
||||
switch pf.value.Kind() {
|
||||
case reflect.Invalid:
|
||||
return 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return int(pf.value.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return int(pf.value.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return int(pf.value.Float())
|
||||
case reflect.Bool:
|
||||
if pf.value.Bool() {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case reflect.String:
|
||||
d, _ := strconv.Atoi(pf.value.String())
|
||||
return d
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (pf ParseFinder) Int64() int64 {
|
||||
switch pf.value.Kind() {
|
||||
case reflect.Invalid:
|
||||
return 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return pf.value.Int()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return int64(pf.value.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return int64(pf.value.Float())
|
||||
case reflect.Bool:
|
||||
if pf.value.Bool() {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case reflect.String:
|
||||
d, err := strconv.ParseInt(pf.value.String(), 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return d
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (pf ParseFinder) Bool() bool {
|
||||
switch pf.value.Kind() {
|
||||
case reflect.Invalid:
|
||||
return false
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return pf.value.Int() > 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return pf.value.Uint() > 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return pf.value.Float() > 0
|
||||
case reflect.Bool:
|
||||
return pf.value.Bool()
|
||||
case reflect.String:
|
||||
v, _ := strconv.ParseBool(pf.value.String())
|
||||
return v
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func getElement(v reflect.Value, p string) reflect.Value {
|
||||
switch v.Kind() {
|
||||
case reflect.Map:
|
||||
vv := v.MapIndex(reflect.ValueOf(p))
|
||||
if vv.Kind() == reflect.Interface {
|
||||
vv = vv.Elem()
|
||||
}
|
||||
return vv
|
||||
case reflect.Array, reflect.Slice:
|
||||
if i, err := strconv.Atoi(p); err == nil {
|
||||
if i >= 0 && i < v.Len() {
|
||||
v = v.Index(i)
|
||||
for v.Kind() == reflect.Interface {
|
||||
v = v.Elem()
|
||||
}
|
||||
return v
|
||||
}
|
||||
}
|
||||
}
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
func NewParser(s string) *Parser {
|
||||
p := &Parser{}
|
||||
return p.LoadString(s)
|
||||
}
|
||||
|
||||
func (p *Parser) LoadString(s string) *Parser {
|
||||
return p.LoadBytes(stringx.ToBytes(s))
|
||||
}
|
||||
|
||||
func (p *Parser) LoadBytes(bytes []byte) *Parser {
|
||||
if bytex.IsBlank(bytes) {
|
||||
return p
|
||||
}
|
||||
|
||||
var sd interface{}
|
||||
if err := json.Unmarshal(bytes, &sd); err != nil {
|
||||
return p
|
||||
}
|
||||
p.data = reflect.ValueOf(sd)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p Parser) Exists(path string) bool {
|
||||
if !p.data.IsValid() || path == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
data := p.data
|
||||
parts := strings.Split(path, ".")
|
||||
n := len(parts)
|
||||
for i := 0; i < n; i++ {
|
||||
if data = getElement(data, parts[i]); !data.IsValid() {
|
||||
return false
|
||||
}
|
||||
if i == n-1 {
|
||||
// is last path
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) Find(path string, defaultValue ...interface{}) *ParseFinder {
|
||||
if len(defaultValue) > 0 {
|
||||
p.value = reflect.ValueOf(defaultValue[0])
|
||||
}
|
||||
if !p.data.IsValid() || path == "" {
|
||||
return (*ParseFinder)(p)
|
||||
}
|
||||
|
||||
data := p.data
|
||||
// find the value corresponding to the path
|
||||
// if any part of path cannot be located, return the default value
|
||||
parts := strings.Split(path, ".")
|
||||
n := len(parts)
|
||||
for i := 0; i < n; i++ {
|
||||
if data = getElement(data, parts[i]); !data.IsValid() {
|
||||
return (*ParseFinder)(p)
|
||||
}
|
||||
if i == n-1 {
|
||||
// is last path
|
||||
p.value = data
|
||||
}
|
||||
}
|
||||
return (*ParseFinder)(p)
|
||||
}
|
||||
78
jsonx/parser_test.go
Normal file
78
jsonx/parser_test.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package jsonx
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParser_Find(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
json string
|
||||
path string
|
||||
defaultValue interface{}
|
||||
valueKind reflect.Kind
|
||||
Except interface{}
|
||||
}{
|
||||
{"string1", "", "a", "", reflect.String, ""},
|
||||
{"string2", `{"a":1}`, "a", 2, reflect.String, "1"},
|
||||
{"string3", `{"a":true}`, "a", 2, reflect.String, "true"},
|
||||
{"string4", `{"a":true}`, "a.b", false, reflect.String, "false"},
|
||||
{"string5", `{"a":{"b": {"c": 123}}}`, "a.b", "{}", reflect.String, `{"c":123}`},
|
||||
{"string6", `{"a":{"b": {"c": 123}}}`, "a.b.c", "", reflect.String, "123"},
|
||||
{"string7", `{"a":{"b": {"c": [1,2,3]}}}`, "a.b.c.0", "", reflect.String, "1"},
|
||||
{"string8", `{"a":{"b": {"c": [1,2,3]}}}`, "a.b.c.2", "", reflect.String, "3"},
|
||||
{"string9", `{"a":{"b": {"c": [1,2,3]}}}`, "", "110", reflect.String, "110"},
|
||||
{"int1", `{"a":1}`, "a", 2, reflect.Int, 1},
|
||||
{"int2", `{"a":1}`, "aa", 2, reflect.Int, 2},
|
||||
{"int641", `{"a":1}`, "a", 2, reflect.Int64, int64(1)},
|
||||
{"int641", `{"a":1}`, "aa", 2, reflect.Int64, int64(2)},
|
||||
{"bool1", `{"a":true}`, "a", false, reflect.Bool, true},
|
||||
{"bool2", `{"a":true}`, "a.b", false, reflect.Bool, false},
|
||||
{"float321", `{"a":1.23}`, "a", 0, reflect.Float32, float32(1.23)},
|
||||
{"float322", `{"a":1.23}`, "b", 0, reflect.Float32, float32(0)},
|
||||
{"float641", `{"a":1.23}`, "a", 0, reflect.Float64, 1.23},
|
||||
{"float642", `{"a":1.23}`, "b", 0, reflect.Float64, 0.0},
|
||||
{"interface1", `{"a":1.23}`, "b", 0, reflect.Interface, 0},
|
||||
{"interface2", `null`, "b", 0, reflect.Interface, 0},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
var v interface{}
|
||||
switch testCase.valueKind {
|
||||
case reflect.String:
|
||||
v = NewParser(testCase.json).Find(testCase.path, testCase.defaultValue).String()
|
||||
case reflect.Int:
|
||||
v = NewParser(testCase.json).Find(testCase.path, testCase.defaultValue).Int()
|
||||
case reflect.Int64:
|
||||
v = NewParser(testCase.json).Find(testCase.path, testCase.defaultValue).Int64()
|
||||
case reflect.Float32:
|
||||
v = NewParser(testCase.json).Find(testCase.path, testCase.defaultValue).Float32()
|
||||
case reflect.Float64:
|
||||
v = NewParser(testCase.json).Find(testCase.path, testCase.defaultValue).Float64()
|
||||
case reflect.Bool:
|
||||
v = NewParser(testCase.json).Find(testCase.path, testCase.defaultValue).Bool()
|
||||
case reflect.Interface:
|
||||
v = NewParser(testCase.json).Find(testCase.path, testCase.defaultValue).Interface()
|
||||
}
|
||||
assert.Equal(t, testCase.Except, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParser_Exists(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
json string
|
||||
path string
|
||||
Except bool
|
||||
}{
|
||||
{"exists1", "", "a", false},
|
||||
{"exists2", `{"a"}`, "a", false},
|
||||
{"exists3", `{"a":1}`, "a", true},
|
||||
{"exists4", `{"a":[0,1,2]}`, "a.1", true},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
v := NewParser(testCase.json).Exists(testCase.path)
|
||||
assert.Equal(t, testCase.Except, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user