Преглед на файлове

codec: clarify/simplify Anonymous support

Previously, we only inlined anonymous fields when there was
no struct tag defined.

We have now clarified that, and we inline anonymous fields everytime except:
- a replacement field name is specified in the struct tag
- it is of an Interface Type

This is more inline with encoding/json support of anonymous fields.

Fixes #98
Ugorji Nwoke преди 10 години
родител
ревизия
3ac1de126a
променени са 2 файла, в които са добавени 14 реда и са изтрити 9 реда
  1. 8 4
      codec/encode.go
  2. 6 5
      codec/helper.go

+ 8 - 4
codec/encode.go

@@ -870,9 +870,9 @@ func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
 // The empty values (for omitempty option) are false, 0, any nil pointer
 // or interface value, and any array, slice, map, or string of length zero.
 //
-// Anonymous fields are encoded inline if the struct tag is "effectively" blank
-// i.e. it is not present or does not have any parameters specified.
-// Else they are encoded as regular fields.
+// Anonymous fields are encoded inline except:
+//    - the struct tag specifies a replacement name (first value)
+//    - the field is of an interface type
 //
 // Examples:
 //
@@ -883,6 +883,9 @@ func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
 //          Field2 int      `codec:"myName"`       //Use key "myName" in encode stream
 //          Field3 int32    `codec:",omitempty"`   //use key "Field3". Omit if empty.
 //          Field4 bool     `codec:"f4,omitempty"` //use key "f4". Omit if empty.
+//          io.Reader                              //use key "Reader".
+//          MyStruct        `codec:"my1"           //use key "my1".
+//          MyStruct                               //inline it
 //          ...
 //      }
 //
@@ -892,8 +895,9 @@ func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
 //      }
 //
 // The mode of encoding is based on the type of the value. When a value is seen:
+//   - If a Selfer, call its CodecEncodeSelf method
 //   - If an extension is registered for it, call that extension function
-//   - If it implements BinaryMarshaler, call its MarshalBinary() (data []byte, err error)
+//   - If it implements encoding.(Binary|Text|JSON)Marshaler, call its Marshal(Binary|Text|JSON) method
 //   - Else encode it based on its reflect.Kind
 //
 // Note that struct field names and keys in map[string]XXX will be treated as symbols.

+ 6 - 5
codec/helper.go

@@ -482,9 +482,9 @@ type structFieldInfo struct {
 	toArray   bool // if field is _struct, is the toArray set?
 }
 
-func (si *structFieldInfo) isZero() bool {
-	return si.encName == "" && len(si.is) == 0 && si.i == 0 && !si.omitEmpty && !si.toArray
-}
+// func (si *structFieldInfo) isZero() bool {
+// 	return si.encName == "" && len(si.is) == 0 && si.i == 0 && !si.omitEmpty && !si.toArray
+// }
 
 // rv returns the field of the struct.
 // If anonymous, it returns an Invalid
@@ -753,11 +753,12 @@ func rgetTypeInfo(rt reflect.Type, indexstack []int, fnameToHastag map[string]bo
 		// if anonymous and there is no struct tag (or it's blank)
 		// and its a struct (or pointer to struct), inline it.
 		var doInline bool
-		if f.Anonymous {
+		if f.Anonymous && f.Type.Kind() != reflect.Interface {
 			doInline = stag == ""
 			if !doInline {
 				si = parseStructFieldInfo("", stag)
-				doInline = si.isZero()
+				doInline = si.encName == ""
+				// doInline = si.isZero()
 				// fmt.Printf(">>>> doInline for si.isZero: %s: %v\n", f.Name, doInline)
 			}
 		}