func (jp *JPath) Find(path string) (interface{}, error) {
keys := strings.Split(path, jp.Separator)
index := len(keys) - 1 //路径的尽头
m := jp.data
for i, v := range keys {
if m == nil {
return nil, errors.New(fmt.Sprintf("path %+v not found ", path))
}
//数组判断
if !strings.HasSuffix(v, ARRAY_TYPE_SUFFIX) {
data := m[v]
//到达了要寻找的路径末尾
if i == index {
if data == nil {
return nil, errors.New(fmt.Sprintf("path %+v not found ", path))
}
return data, nil
}
//path中这个节点并不是数组也不是路径的结尾、只需要处理字符串和map的情况
switch data.(type) {
case map[string]interface{}:
m = data.(map[string]interface{})
case string:
m_sub, _ := strToMap(m[v].(string), false)
m[v] = m_sub
m = m_sub
case []interface{}:
return nil, errors.New(fmt.Sprintf("key %+v error,array should be like this [index]", path))
default:
return nil, errors.New(fmt.Sprintf("key %+v error,it is not string or map", v))
}
} else {
//匹配出[index]
flag := ARRAY_REGEX.FindString(v)
value, err := strconv.Atoi(flag[1 : len(flag)-1])
if err != nil {
return nil, errors.New(fmt.Sprintf("illegal index args %+v", flag))
}
key := strings.Split(v, flag)[0] //获取数组路径的前缀、例如simple[1]中的simple
data := m[key]
//这段路径被用户作为数组传入、只需要处理数组的情况
switch data.(type) {
case []interface{}:
arr := data.([]interface{})
if value > len(arr)-1 {
return nil, errors.New(fmt.Sprintf("key %+v error,it is larger than array last index %+v", v, len(arr)-1))
}
tmp := arr[value]
if i == index {
if tmp == nil {
return nil, errors.New(fmt.Sprintf("path %+v not found ", path))
}
return tmp, nil
}
//对数组中取出的值、要进行再次判断、因为它并不是路径的最后、需要再生成一个map以便于获取下一层value
switch tmp.(type) {
case map[string]interface{}:
m = tmp.(map[string]interface{})
case string:
m_sub, _ := strToMap(tmp.(string), false)
m[v] = m_sub
m = m_sub
default:
return nil, errors.New(fmt.Sprintf("key %+v error,it is not string or map", v))
}
//在并发场景下、会需要将map完全递归生成。会有这种类型、统一处理了
case []map[string]interface{}:
arr := data.([]map[string]interface{})
if value > len(arr)-1 {
return nil, errors.New(fmt.Sprintf("key %+v error,it is larger than array last index %+v", v, len(arr)-1))
}
tmp := arr[value]
if i == index {
if tmp == nil {
return nil, errors.New(fmt.Sprintf("path %+v not found ", path))
}
return tmp, nil
}
m = tmp
default:
return nil, errors.New(fmt.Sprintf("key %+v error,it is not a array", v))
}
}
}
return nil, errors.New(fmt.Sprintf("path %+v not found ", path))
}
评论