github.com/cloudwego/hertz@v0.9.3/pkg/app/server/binding/internal/decoder/util.go (about)

     1  /*
     2   * Copyright 2024 CloudWeGo Authors
     3   *
     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
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    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.
    15   */
    16  
    17  package decoder
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  
    24  	"github.com/cloudwego/hertz/internal/bytesconv"
    25  	hJson "github.com/cloudwego/hertz/pkg/common/json"
    26  	"github.com/cloudwego/hertz/pkg/protocol"
    27  	"github.com/cloudwego/hertz/pkg/route/param"
    28  )
    29  
    30  const (
    31  	specialChar = "\x07"
    32  )
    33  
    34  // toDefaultValue will preprocess the default value and transfer it to be standard format
    35  func toDefaultValue(typ reflect.Type, defaultValue string) string {
    36  	switch typ.Kind() {
    37  	case reflect.Slice, reflect.Array, reflect.Map, reflect.Struct:
    38  		// escape single quote and double quote, replace single quote with double quote
    39  		defaultValue = strings.Replace(defaultValue, `"`, `\"`, -1)
    40  		defaultValue = strings.Replace(defaultValue, `\'`, specialChar, -1)
    41  		defaultValue = strings.Replace(defaultValue, `'`, `"`, -1)
    42  		defaultValue = strings.Replace(defaultValue, specialChar, `'`, -1)
    43  	}
    44  	return defaultValue
    45  }
    46  
    47  // stringToValue is used to dynamically create reflect.Value for 'text'
    48  func stringToValue(elemType reflect.Type, text string, req *protocol.Request, params param.Params, config *DecodeConfig) (v reflect.Value, err error) {
    49  	v = reflect.New(elemType).Elem()
    50  	if customizedFunc, exist := config.TypeUnmarshalFuncs[elemType]; exist {
    51  		val, err := customizedFunc(req, params, text)
    52  		if err != nil {
    53  			return reflect.Value{}, err
    54  		}
    55  		return val, nil
    56  	}
    57  	switch elemType.Kind() {
    58  	case reflect.Struct:
    59  		err = hJson.Unmarshal(bytesconv.S2b(text), v.Addr().Interface())
    60  	case reflect.Map:
    61  		err = hJson.Unmarshal(bytesconv.S2b(text), v.Addr().Interface())
    62  	case reflect.Array, reflect.Slice:
    63  		// do nothing
    64  	default:
    65  		decoder, err := SelectTextDecoder(elemType)
    66  		if err != nil {
    67  			return reflect.Value{}, fmt.Errorf("unsupported type %s for slice/array", elemType.String())
    68  		}
    69  		err = decoder.UnmarshalString(text, v, config.LooseZeroMode)
    70  		if err != nil {
    71  			return reflect.Value{}, fmt.Errorf("unable to decode '%s' as %s: %w", text, elemType.String(), err)
    72  		}
    73  	}
    74  
    75  	return v, err
    76  }