@@ -859,7 +859,7 @@ func EncodeTypedValue(val any, enc gnmipb.Encoding, opts ...EncodeTypedValueOpt)
859859 if err != nil {
860860 return nil , fmt .Errorf ("cannot marshal enum, %v" , err )
861861 }
862- return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_StringVal {en }}, nil
862+ return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_StringVal {StringVal : en }}, nil
863863 }
864864
865865 vv := reflect .ValueOf (val )
@@ -871,9 +871,9 @@ func EncodeTypedValue(val any, enc gnmipb.Encoding, opts ...EncodeTypedValueOpt)
871871 return nil , fmt .Errorf ("cannot represent field value %v as TypedValue" , val )
872872 case vv .Type ().Name () == BinaryTypeName :
873873 // This is a binary type which is defined as a []byte, so we encode it as the bytes.
874- return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_BytesVal {vv .Bytes ()}}, nil
874+ return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_BytesVal {BytesVal : vv .Bytes ()}}, nil
875875 case vv .Type ().Name () == EmptyTypeName :
876- return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_BoolVal {vv .Bool ()}}, nil
876+ return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_BoolVal {BoolVal : vv .Bool ()}}, nil
877877 case vv .Kind () == reflect .Slice :
878878 sval , err := leaflistToSlice (vv , false )
879879 if err != nil {
@@ -884,7 +884,7 @@ func EncodeTypedValue(val any, enc gnmipb.Encoding, opts ...EncodeTypedValueOpt)
884884 if err != nil {
885885 return nil , err
886886 }
887- return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_LeaflistVal {arr }}, nil
887+ return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_LeaflistVal {LeaflistVal : arr }}, nil
888888 case util .IsValueStructPtr (vv ):
889889 nv , err := unwrapUnionInterfaceValue (vv , false )
890890 if err != nil {
@@ -893,7 +893,7 @@ func EncodeTypedValue(val any, enc gnmipb.Encoding, opts ...EncodeTypedValueOpt)
893893 vv = reflect .ValueOf (nv )
894894 // Apart from binary, all other possible union subtypes are scalars or typedefs of scalars.
895895 if vv .Type ().Name () == BinaryTypeName {
896- return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_BytesVal {vv .Bytes ()}}, nil
896+ return & gnmipb.TypedValue {Value : & gnmipb.TypedValue_BytesVal {BytesVal : vv .Bytes ()}}, nil
897897 }
898898 case util .IsValuePtr (vv ):
899899 vv = vv .Elem ()
@@ -1593,6 +1593,15 @@ func jsonValue(field reflect.Value, parentMod string, args jsonOutputConfig) (an
15931593
15941594 prependModuleNameIref := args .rfc7951Config != nil && (args .rfc7951Config .AppendModuleName || args .rfc7951Config .PrependModuleNameIdentityref )
15951595
1596+ // When jsonValue is called using the output of reflect.ValueOf()
1597+ // instead of reflect.StructField, any interface type is lost through
1598+ // re-packing to the empty interface (any). This means the Kind of a
1599+ // union field is no longer the union type, but its underlying concrete
1600+ // type. This flag is used to detect failures during unmarshalling that
1601+ // may be due to this issue, which will be handled later assuming that
1602+ // the given type is named using one of the ygot-generated union names.
1603+ var mightBeUnion bool
1604+
15961605 switch field .Kind () {
15971606 case reflect .Map :
15981607 var err error
@@ -1663,6 +1672,10 @@ func jsonValue(field reflect.Value, parentMod string, args jsonOutputConfig) (an
16631672 // For output, we map the enumerated value to the string name of the enum.
16641673 v , set , err := enumFieldToString (field , prependModuleNameIref )
16651674 if err != nil {
1675+ if _ , ok := unionSingletonUnderlyingTypes [field .Type ().Name ()]; ok {
1676+ mightBeUnion = true
1677+ break
1678+ }
16661679 return nil , err
16671680 }
16681681
@@ -1692,6 +1705,15 @@ func jsonValue(field reflect.Value, parentMod string, args jsonOutputConfig) (an
16921705 return nil , err
16931706 }
16941707 return value , nil
1708+ case field .Elem ().Kind () == reflect .Bool && field .Elem ().Type ().Name () == EmptyTypeName :
1709+ switch {
1710+ case args .jType == RFC7951 && field .Elem ().Bool ():
1711+ return []any {nil }, nil
1712+ case field .Elem ().Bool ():
1713+ return true , nil
1714+ default :
1715+ return nil , nil
1716+ }
16951717 default :
16961718 if value , err = resolveUnionVal (field .Elem ().Interface (), prependModuleNameIref ); err != nil {
16971719 return nil , err
@@ -1704,14 +1726,39 @@ func jsonValue(field reflect.Value, parentMod string, args jsonOutputConfig) (an
17041726 // A non-pointer field of type boolean is an empty leaf within the YANG schema.
17051727 // For RFC7951 this is represented as a null JSON array (i.e., [null]). For internal
17061728 // JSON if the leaf is present and set, it is rendered as 'true', or as nil otherwise.
1707- switch {
1708- case args .jType == RFC7951 && field .Type ().Name () == EmptyTypeName && field .Bool ():
1709- value = []any {nil }
1710- case field .Bool ():
1711- value = true
1729+ if field .Type ().Name () == EmptyTypeName {
1730+ switch {
1731+ case args .jType == RFC7951 && field .Bool ():
1732+ value = []any {nil }
1733+ case field .Bool ():
1734+ value = true
1735+ }
1736+ } else {
1737+ if _ , ok := unionSingletonUnderlyingTypes [field .Type ().Name ()]; ok {
1738+ mightBeUnion = true
1739+ break
1740+ }
17121741 }
17131742 default :
1714- return nil , fmt .Errorf ("got unexpected field type, was: %v" , field .Kind ())
1743+ mightBeUnion = true
1744+ }
1745+
1746+ if mightBeUnion {
1747+ underlyingType , ok := unionSingletonUnderlyingTypes [field .Type ().Name ()]
1748+ if ! ok {
1749+ return nil , fmt .Errorf ("got unexpected field type, was: %v (%s)" , field .Kind (), field .Type ().Name ())
1750+ }
1751+
1752+ if ! field .Type ().ConvertibleTo (underlyingType ) {
1753+ return nil , fmt .Errorf ("ygot internal error: union type %q inconvertible to underlying type %q" , field .Type ().Name (), underlyingType )
1754+ }
1755+ var err error
1756+ if value , err = resolveUnionVal (field .Interface (), prependModuleNameIref ); err != nil {
1757+ return nil , err
1758+ }
1759+ if args .jType == RFC7951 {
1760+ value = writeIETFScalarJSON (value )
1761+ }
17151762 }
17161763
17171764 if errs .Err () != nil {
0 commit comments