dubbo.apache.org/dubbo-go/v3@v3.1.1/remoting/polaris/parser/parser.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package parser
    19  
    20  import (
    21  	"encoding/json"
    22  	"regexp"
    23  	"strconv"
    24  	"strings"
    25  )
    26  
    27  import (
    28  	"github.com/dubbogo/gost/log/logger"
    29  
    30  	"github.com/oliveagle/jsonpath"
    31  )
    32  
    33  const (
    34  	_pefixParam     = "param"
    35  	_prefixParamArr = "param["
    36  )
    37  
    38  var (
    39  	_arrayRegx, _ = regexp.Compile(`"^.+\\[[0-9]+\\]"`)
    40  )
    41  
    42  // ParseArgumentsByExpression follow https://goessner.net/articles/JsonPath/
    43  //
    44  //	{
    45  //	    "store":{
    46  //	        "book":[
    47  //	            {
    48  //	                "category":"reference",
    49  //	                "author":"Nigel Rees",
    50  //	                "title":"Sayings of the Century",
    51  //	                "price":8.95
    52  //	            },
    53  //	            {
    54  //	                "category":"fiction",
    55  //	                "author":"Evelyn Waugh",
    56  //	                "title":"Sword of Honor",
    57  //	                "price":12.99
    58  //	            },
    59  //	            {
    60  //	                "category":"fiction",
    61  //	                "author":"Herman Melville",
    62  //	                "title":"Moby Dick",
    63  //	                "isbn":"0-553-21311-3",
    64  //	                "price":8.99
    65  //	            },
    66  //	            {
    67  //	                "category":"fiction",
    68  //	                "author":"J. R. R. Tolkien",
    69  //	                "title":"The Lord of the Rings",
    70  //	                "isbn":"0-395-19395-8",
    71  //	                "price":22.99
    72  //	            }
    73  //	        ],
    74  //	        "bicycle":{
    75  //	            "color":"red",
    76  //	            "price":19.95
    77  //	        }
    78  //	    }
    79  //	}
    80  //
    81  // examples
    82  //   - case 1: param.$.store.book[*].author
    83  func ParseArgumentsByExpression(key string, parameters []interface{}) interface{} {
    84  	index, key := resolveIndex(key)
    85  	if index == -1 || index >= len(parameters) {
    86  		logger.Errorf("[Parser][Polaris] invalid expression for : %s", key)
    87  		return nil
    88  	}
    89  
    90  	data, err := json.Marshal(parameters[index])
    91  	if err != nil {
    92  		logger.Errorf("[Parser][Polaris] marshal parameter %+v fail : %+v", parameters[index], err)
    93  		return nil
    94  	}
    95  	var searchVal interface{}
    96  	_ = json.Unmarshal(data, &searchVal)
    97  	res, err := jsonpath.JsonPathLookup(searchVal, key)
    98  	if err != nil {
    99  		logger.Errorf("[Parser][Polaris] invalid do json path lookup by key : %s, err : %+v", key, err)
   100  	}
   101  
   102  	return res
   103  }
   104  
   105  func resolveIndex(key string) (int, string) {
   106  	if strings.HasPrefix(key, _prefixParamArr) {
   107  		// param[0].$.
   108  		endIndex := strings.Index(key, "]")
   109  		indexStr := key[len(_prefixParamArr):endIndex]
   110  		index, err := strconv.ParseInt(indexStr, 10, 32)
   111  		if err != nil {
   112  			return -1, ""
   113  		}
   114  		startIndex := endIndex + 2
   115  		if rune(key[endIndex+1]) != rune('.') {
   116  			startIndex = endIndex + 1
   117  		}
   118  		return int(index), key[startIndex:]
   119  	} else if strings.HasPrefix(key, _pefixParam) {
   120  		key = strings.TrimPrefix(key, _pefixParam+".")
   121  		return 0, strings.TrimPrefix(key, _pefixParam+".")
   122  	}
   123  
   124  	return -1, ""
   125  }