github.com/vmware/govmomi@v0.51.0/vim25/types/json.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package types
     6  
     7  import (
     8  	"bytes"
     9  	"io"
    10  	"reflect"
    11  	"time"
    12  
    13  	"github.com/vmware/govmomi/vim25/json"
    14  )
    15  
    16  const (
    17  	discriminatorMemberName  = "_typeName"
    18  	primitiveValueMemberName = "_value"
    19  )
    20  
    21  var discriminatorTypeRegistry = map[string]reflect.Type{
    22  	"boolean":  reflect.TypeOf(true),
    23  	"byte":     reflect.TypeOf(uint8(0)),
    24  	"short":    reflect.TypeOf(int16(0)),
    25  	"int":      reflect.TypeOf(int32(0)),
    26  	"long":     reflect.TypeOf(int64(0)),
    27  	"float":    reflect.TypeOf(float32(0)),
    28  	"double":   reflect.TypeOf(float64(0)),
    29  	"string":   reflect.TypeOf(""),
    30  	"binary":   reflect.TypeOf([]byte{}),
    31  	"dateTime": reflect.TypeOf(time.Now()),
    32  }
    33  
    34  // NewJSONDecoder creates JSON decoder configured for VMOMI.
    35  func NewJSONDecoder(r io.Reader) *json.Decoder {
    36  	res := json.NewDecoder(r)
    37  	res.SetDiscriminator(
    38  		discriminatorMemberName,
    39  		primitiveValueMemberName,
    40  		json.DiscriminatorToTypeFunc(func(name string) (reflect.Type, bool) {
    41  			if res, ok := TypeFunc()(name); ok {
    42  				return res, true
    43  			}
    44  			if res, ok := discriminatorTypeRegistry[name]; ok {
    45  				return res, true
    46  			}
    47  			return nil, false
    48  		}),
    49  	)
    50  	return res
    51  }
    52  
    53  // VMOMI primitive names
    54  var discriminatorNamesRegistry = map[reflect.Type]string{
    55  	reflect.TypeOf(true):       "boolean",
    56  	reflect.TypeOf(uint8(0)):   "byte",
    57  	reflect.TypeOf(int16(0)):   "short",
    58  	reflect.TypeOf(int32(0)):   "int",
    59  	reflect.TypeOf(int64(0)):   "long",
    60  	reflect.TypeOf(float32(0)): "float",
    61  	reflect.TypeOf(float64(0)): "double",
    62  	reflect.TypeOf(""):         "string",
    63  	reflect.TypeOf([]byte{}):   "binary",
    64  	reflect.TypeOf(time.Now()): "dateTime",
    65  }
    66  
    67  // NewJSONEncoder creates JSON encoder configured for VMOMI.
    68  func NewJSONEncoder(w *bytes.Buffer) *json.Encoder {
    69  	enc := json.NewEncoder(w)
    70  	enc.SetDiscriminator(
    71  		discriminatorMemberName,
    72  		primitiveValueMemberName,
    73  		json.DiscriminatorEncodeTypeNameRootValue|
    74  			json.DiscriminatorEncodeTypeNameAllObjects,
    75  	)
    76  	enc.SetTypeToDiscriminatorFunc(VmomiTypeName)
    77  	return enc
    78  }
    79  
    80  // VmomiTypeName computes the VMOMI type name of a go type. It uses a lookup
    81  // table for VMOMI primitive types and the default discriminator function for
    82  // other types.
    83  func VmomiTypeName(t reflect.Type) (discriminator string) {
    84  	// Look up primitive type names from VMOMI protocol
    85  	if name, ok := discriminatorNamesRegistry[t]; ok {
    86  		return name
    87  	}
    88  	name := json.DefaultDiscriminatorFunc(t)
    89  	return name
    90  }