Browse Source

codec: support 'json:' as fallback to 'codec:' in struct tag configuration.

When getting struct tag value, look for keys: codec, json (in that sequence).

Also, codecgen CLI will handle errors using fmt.Fprintf and os.Exit(1).
Ugorji Nwoke 11 years ago
parent
commit
f20364ed02
6 changed files with 25 additions and 16 deletions
  1. 1 0
      codec/0doc.go
  2. 1 0
      codec/README.md
  3. 4 2
      codec/codecgen/gen.go
  4. 0 1
      codec/decode.go
  5. 7 9
      codec/encode.go
  6. 12 4
      codec/helper.go

+ 1 - 0
codec/0doc.go

@@ -63,6 +63,7 @@ Rich Feature Set includes:
     User decides whether to return an error or silently skip data when keys or indexes
     in the data stream do not map to fields in the struct.
   - Encode/Decode from/to chan types (for iterative streaming support)
+  - Drop-in replacement for encoding/json. `json:` key in struct tag supported.
   - Provides a RPC Server and Client Codec for net/rpc communication protocol.
   - Handle unique idiosynchracies of codecs e.g. 
     - For messagepack, configure how ambiguities in handling raw bytes are resolved 

+ 1 - 0
codec/README.md

@@ -64,6 +64,7 @@ Rich Feature Set includes:
     User decides whether to return an error or silently skip data when keys or indexes
     in the data stream do not map to fields in the struct.
   - Encode/Decode from/to chan types (for iterative streaming support)
+  - Drop-in replacement for encoding/json. `json:` key in struct tag supported.
   - Provides a RPC Server and Client Codec for net/rpc communication protocol.
   - Handle unique idiosynchracies of codecs e.g. 
     - For messagepack, configure how ambiguities in handling raw bytes are resolved 

+ 4 - 2
codec/codecgen/gen.go

@@ -217,7 +217,9 @@ func main() {
 	u := flag.Bool("u", false, "Use unsafe, e.g. to avoid unnecessary allocation on []byte->string")
 
 	flag.Parse()
-	if err := Generate(*o, *t, *c, *u, *rt, regexp.MustCompile(*r), !*x, flag.Args()...); err != nil {
-		panic(err)
+	if err := Generate(*o, *t, *c, *u, *rt,
+		regexp.MustCompile(*r), !*x, flag.Args()...); err != nil {
+		fmt.Fprintf(os.Stderr, "codecgen error: %v\n", err)
+		os.Exit(1)
 	}
 }

+ 0 - 1
codec/decode.go

@@ -13,7 +13,6 @@ import (
 
 // Some tagging information for error messages.
 const (
-	msgTagDec             = "codec.decoder"
 	msgBadDesc            = "Unrecognized descriptor byte"
 	msgDecCannotExpandArr = "cannot expand go array from %v to stream length: %v"
 )

+ 7 - 9
codec/encode.go

@@ -13,10 +13,7 @@ import (
 )
 
 const (
-	// Some tagging information for error messages.
-	msgTagEnc         = "codec.encoder"
 	defEncByteBufSize = 1 << 6 // 4:16, 6:64, 8:256, 10:1024
-	// maxTimeSecs32 = math.MaxInt32 / 60 / 24 / 366
 )
 
 // AsSymbolFlag defines what should be encoded as symbols.
@@ -809,26 +806,26 @@ func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
 	return e
 }
 
-// Encode writes an object into a stream in the codec format.
-//
-// Encoding can be configured via the "codec" struct tag for the fields.
+// Encode writes an object into a stream.
 //
+// Encoding can be configured via the struct tag for the fields.
 // The "codec" key in struct field's tag value is the key name,
 // followed by an optional comma and options.
+// Note that the "json" key is used in the absence of the "codec" key.
 //
 // To set an option on all fields (e.g. omitempty on all fields), you
 // can create a field called _struct, and set flags on it.
 //
 // Struct values "usually" encode as maps. Each exported struct field is encoded unless:
-//    - the field's codec tag is "-", OR
-//    - the field is empty and its codec tag specifies the "omitempty" option.
+//    - the field's tag is "-", OR
+//    - the field is empty (empty or the zero value) and its tag specifies the "omitempty" option.
 //
 // When encoding as a map, the first string in the tag (before the comma)
 // is the map key string to use when encoding.
 //
 // However, struct values may encode as arrays. This happens when:
 //    - StructToArray Encode option is set, OR
-//    - the codec tag on the _struct field sets the "toarray" option
+//    - the tag on the _struct field sets the "toarray" option
 //
 // Values with types that implement MapBySlice are encoded as stream maps.
 //
@@ -840,6 +837,7 @@ func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
 //
 // Examples:
 //
+//      // NOTE: 'json:' can be used as struct tag key, in place 'codec:' below.
 //      type MyStruct struct {
 //          _struct bool    `codec:",omitempty"`   //set omitempty for every field
 //          Field1 string   `codec:"-"`            //skip this field

+ 12 - 4
codec/helper.go

@@ -116,8 +116,6 @@ import (
 )
 
 const (
-	structTagName = "codec"
-
 	scratchByteArrayLen = 32
 
 	// Support encoding.(Binary|Text)(Unm|M)arshaler.
@@ -622,6 +620,16 @@ func (ti *typeInfo) indexForEncName(name string) int {
 	return -1
 }
 
+func getStructTag(t reflect.StructTag) (s string) {
+	// check for tags: codec, json, in that order.
+	// this allows seamless support for many configured structs.
+	s = t.Get("codec")
+	if s == "" {
+		s = t.Get("json")
+	}
+	return
+}
+
 func getTypeInfo(rtid uintptr, rt reflect.Type) (pti *typeInfo) {
 	var ok bool
 	cachedTypeInfoMutex.RLock()
@@ -679,7 +687,7 @@ func getTypeInfo(rtid uintptr, rt reflect.Type) (pti *typeInfo) {
 	if rt.Kind() == reflect.Struct {
 		var siInfo *structFieldInfo
 		if f, ok := rt.FieldByName(structInfoFieldName); ok {
-			siInfo = parseStructFieldInfo(structInfoFieldName, f.Tag.Get(structTagName))
+			siInfo = parseStructFieldInfo(structInfoFieldName, getStructTag(f.Tag))
 			ti.toArray = siInfo.toArray
 		}
 		sfip := make([]*structFieldInfo, 0, rt.NumField())
@@ -705,7 +713,7 @@ func rgetTypeInfo(rt reflect.Type, indexstack []int, fnameToHastag map[string]bo
 		if tk := f.Type.Kind(); tk == reflect.Func {
 			continue
 		}
-		stag := f.Tag.Get(structTagName)
+		stag := getStructTag(f.Tag)
 		if stag == "-" {
 			continue
 		}