github.com/xmplusdev/xray-core@v1.8.10/common/reflect/marshal.go (about)

     1  package reflect
     2  
     3  import (
     4  	"encoding/json"
     5  	"reflect"
     6  
     7  	cserial "github.com/xmplusdev/xray-core/common/serial"
     8  )
     9  
    10  func MarshalToJson(v interface{}) (string, bool) {
    11  	if itf := marshalInterface(v, true); itf != nil {
    12  		if b, err := json.MarshalIndent(itf, "", "  "); err == nil {
    13  			return string(b[:]), true
    14  		}
    15  	}
    16  	return "", false
    17  }
    18  
    19  func marshalTypedMessage(v *cserial.TypedMessage, ignoreNullValue bool) interface{} {
    20  	if v == nil {
    21  		return nil
    22  	}
    23  	tmsg, err := v.GetInstance()
    24  	if err != nil {
    25  		return nil
    26  	}
    27  	r := marshalInterface(tmsg, ignoreNullValue)
    28  	if msg, ok := r.(map[string]interface{}); ok {
    29  		msg["_TypedMessage_"] = v.Type
    30  	}
    31  	return r
    32  }
    33  
    34  func marshalSlice(v reflect.Value, ignoreNullValue bool) interface{} {
    35  	r := make([]interface{}, 0)
    36  	for i := 0; i < v.Len(); i++ {
    37  		rv := v.Index(i)
    38  		if rv.CanInterface() {
    39  			value := rv.Interface()
    40  			r = append(r, marshalInterface(value, ignoreNullValue))
    41  		}
    42  	}
    43  	return r
    44  }
    45  
    46  func marshalStruct(v reflect.Value, ignoreNullValue bool) interface{} {
    47  	r := make(map[string]interface{})
    48  	t := v.Type()
    49  	for i := 0; i < v.NumField(); i++ {
    50  		rv := v.Field(i)
    51  		if rv.CanInterface() {
    52  			ft := t.Field(i)
    53  			name := ft.Name
    54  			value := rv.Interface()
    55  			tv := marshalInterface(value, ignoreNullValue)
    56  			if tv != nil || !ignoreNullValue {
    57  				r[name] = tv
    58  			}
    59  		}
    60  	}
    61  	return r
    62  }
    63  
    64  func marshalMap(v reflect.Value, ignoreNullValue bool) interface{} {
    65  	// policy.level is map[uint32] *struct
    66  	kt := v.Type().Key()
    67  	vt := reflect.TypeOf((*interface{})(nil))
    68  	mt := reflect.MapOf(kt, vt)
    69  	r := reflect.MakeMap(mt)
    70  	for _, key := range v.MapKeys() {
    71  		rv := v.MapIndex(key)
    72  		if rv.CanInterface() {
    73  			iv := rv.Interface()
    74  			tv := marshalInterface(iv, ignoreNullValue)
    75  			if tv != nil || !ignoreNullValue {
    76  				r.SetMapIndex(key, reflect.ValueOf(&tv))
    77  			}
    78  		}
    79  	}
    80  	return r.Interface()
    81  }
    82  
    83  func marshalIString(v interface{}) (r string, ok bool) {
    84  	defer func() {
    85  		if err := recover(); err != nil {
    86  			r = ""
    87  			ok = false
    88  		}
    89  	}()
    90  
    91  	if iStringFn, ok := v.(interface{ String() string }); ok {
    92  		return iStringFn.String(), true
    93  	}
    94  	return "", false
    95  }
    96  
    97  func marshalKnownType(v interface{}, ignoreNullValue bool) (interface{}, bool) {
    98  	switch ty := v.(type) {
    99  	case cserial.TypedMessage:
   100  		return marshalTypedMessage(&ty, ignoreNullValue), true
   101  	case *cserial.TypedMessage:
   102  		return marshalTypedMessage(ty, ignoreNullValue), true
   103  	case map[string]json.RawMessage:
   104  		return ty, true
   105  	case []json.RawMessage:
   106  		return ty, true
   107  	case *json.RawMessage:
   108  		return ty, true
   109  	case json.RawMessage:
   110  		return ty, true
   111  	default:
   112  		return nil, false
   113  	}
   114  }
   115  
   116  func isValueKind(kind reflect.Kind) bool {
   117  	switch kind {
   118  	case reflect.Bool,
   119  		reflect.Int,
   120  		reflect.Int8,
   121  		reflect.Int16,
   122  		reflect.Int32,
   123  		reflect.Int64,
   124  		reflect.Uint,
   125  		reflect.Uint8,
   126  		reflect.Uint16,
   127  		reflect.Uint32,
   128  		reflect.Uint64,
   129  		reflect.Uintptr,
   130  		reflect.Float32,
   131  		reflect.Float64,
   132  		reflect.Complex64,
   133  		reflect.Complex128,
   134  		reflect.String:
   135  		return true
   136  	default:
   137  		return false
   138  	}
   139  }
   140  
   141  func marshalInterface(v interface{}, ignoreNullValue bool) interface{} {
   142  
   143  	if r, ok := marshalKnownType(v, ignoreNullValue); ok {
   144  		return r
   145  	}
   146  
   147  	rv := reflect.ValueOf(v)
   148  	if rv.Kind() == reflect.Ptr {
   149  		rv = rv.Elem()
   150  	}
   151  	k := rv.Kind()
   152  	if k == reflect.Invalid {
   153  		return nil
   154  	}
   155  	if isValueKind(k) {
   156  		return v
   157  	}
   158  
   159  	switch k {
   160  	case reflect.Struct:
   161  		return marshalStruct(rv, ignoreNullValue)
   162  	case reflect.Slice:
   163  		return marshalSlice(rv, ignoreNullValue)
   164  	case reflect.Array:
   165  		return marshalSlice(rv, ignoreNullValue)
   166  	case reflect.Map:
   167  		return marshalMap(rv, ignoreNullValue)
   168  	default:
   169  		break
   170  	}
   171  
   172  	if str, ok := marshalIString(v); ok {
   173  		return str
   174  	}
   175  	return nil
   176  }