2 * Copyright 2020 Huawei Technologies Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
26 type JSONPathInfo struct {
27 ParentNode reflect.Value
38 func (e *JpErr) Error() string {
39 return fmt.Sprintf("jpath error info:%s, json path:%s", e.ErrDes, e.JPath)
42 func ObjReflectPath(p reflect.Value, v reflect.Value, path string) JSONPathInfo {
43 fieldName, subPath := GetFirstName(path)
47 return JSONPathInfo{e: &JpErr{"reflect.Invalid", path}}
49 case reflect.Slice, reflect.Array:
50 return ObjReflectPathArray(v, fieldName, subPath)
52 return ObjReflectPathStruct(v, fieldName, subPath)
55 return ObjReflectPathMap(v, fieldName, subPath)
59 return JSONPathInfo{e: &JpErr{"pointer is null", path}}
61 return ObjReflectPath(p, v.Elem(), path)
62 case reflect.Interface:
64 return JSONPathInfo{e: &JpErr{"kind is interface, nil", path}}
68 return ReflectSafeAddr(v, v.Elem())
70 return ObjReflectPath(p, v.Elem(), path)
73 return GetFieldFromPath(p, v, path)
77 func ObjReflectPathArray(v reflect.Value, fieldName string, subPath string) JSONPathInfo {
79 mapInfo := ReflectSafeAddr(v, reflect.ValueOf(nil))
84 idx, err := strconv.Atoi(fieldName)
86 return JSONPathInfo{e: &JpErr{"Atoi error", fieldName}}
89 return JSONPathInfo{e: &JpErr{"Index out of range", fieldName}}
92 return ReflectSafeAddr(v, v.Index(idx))
94 return ObjReflectPath(v, v.Index(idx), subPath)
97 func ObjReflectPathStruct(v reflect.Value, fieldName string, subPath string) JSONPathInfo {
100 for i := 0; i < v.NumField(); i++ {
101 if !MatchJSONFieldName(vType, i, fieldName) {
105 return ReflectSafeAddr(v, v.Field(i))
107 return ObjReflectPath(v, v.Field(i), subPath)
109 return JSONPathInfo{e: &JpErr{"can not find field in struct", fieldName}}
113 func ObjReflectPathMap(v reflect.Value, fieldName string, subPath string) JSONPathInfo {
114 for _, key := range v.MapKeys() {
115 if ReflectValueToString(key) != fieldName {
120 mapInfo := ReflectSafeAddr(v, reflect.ValueOf(nil))
121 mapInfo.CurName = fieldName
124 return ObjReflectPath(v, v.MapIndex(key), subPath)
128 mapInfo := ReflectSafeAddr(v, reflect.ValueOf(nil))
129 mapInfo.CurName = fieldName
133 return JSONPathInfo{e: &JpErr{"path not in map:" + fieldName, subPath}}
136 func GetFirstName(path string) (string, string) {
144 pos := strings.IndexByte(newPath, '/')
148 subPath := newPath[pos:]
149 firstName := newPath[0:pos]
150 escape := strings.IndexByte(firstName, '~')
152 firstName = strings.Replace(firstName, "~1", "/", -1)
153 firstName = strings.Replace(firstName, "~0", "~", -1)
155 return firstName, subPath
158 func MatchJSONFieldName(vType reflect.Type, i int, jsonName string) bool {
159 tag := vType.Field(i).Tag
160 if !strings.Contains(string(tag), jsonName) {
163 name := tag.Get("json")
165 name = strings.ToLower(vType.Field(i).Name)
167 pos := strings.IndexByte(name, ',')
172 if name == jsonName {
179 func GetFieldFromPath(p reflect.Value, v reflect.Value, path string) JSONPathInfo {
180 var info JSONPathInfo
182 return JSONPathInfo{e: &JpErr{"CanAddr false", path}}
186 case reflect.Invalid:
187 return JSONPathInfo{e: &JpErr{"Kind invalid", path}}
189 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
194 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
207 case reflect.Slice, reflect.Map:
215 case reflect.Chan, reflect.Func:
216 return JSONPathInfo{e: &JpErr{"Kind Chan or Func", path}}
218 return JSONPathInfo{e: &JpErr{"upexpect Kint: reflect.Array, reflect.Struct, reflect.Interface", path}}
222 func ReflectValueToString(v reflect.Value) string {
224 case reflect.Invalid:
226 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
227 return strconv.FormatInt(v.Int(), 10)
228 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
229 return strconv.FormatUint(v.Uint(), 10)
231 return strconv.FormatBool(v.Bool())
234 case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Slice, reflect.Map:
241 func ReflectSafeAddr(p reflect.Value, v reflect.Value) JSONPathInfo {
242 var info JSONPathInfo