commit ff18262ef2f5be4acf13cd9c83e2b7117a057baf
parent 4fc4320ce1c21434fb19f506945973e9189a341b
Author: Francois Parquet <francois.parquet@gmail.com>
Date: Wed, 30 May 2018 22:27:34 +0800
Merge pull request #31 from m1ome/marshal-any
Added MarshalAny() support
Diffstat:
2 files changed, 102 insertions(+), 69 deletions(-)
diff --git a/encode.go b/encode.go
@@ -1,9 +1,10 @@
package gojay
import (
- "fmt"
"io"
+ "fmt"
"reflect"
+ "encoding/json"
)
// MarshalJSONObject returns the JSON encoding of v.
@@ -97,74 +98,90 @@ func MarshalJSONArray(v MarshalerJSONArray) ([]byte, error) {
// fmt.Println(b) // {"id":123456}
// }
func Marshal(v interface{}) ([]byte, error) {
- switch vt := v.(type) {
- case MarshalerJSONObject:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeObject(vt)
- case MarshalerJSONArray:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeArray(vt)
- case string:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeString(vt)
- case bool:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeBool(vt)
- case int:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt(vt)
- case int64:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt64(vt)
- case int32:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt(int(vt))
- case int16:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt(int(vt))
- case int8:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt(int(vt))
- case uint64:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt(int(vt))
- case uint32:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt(int(vt))
- case uint16:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt(int(vt))
- case uint8:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeInt(int(vt))
- case float64:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeFloat(vt)
- case float32:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeFloat32(vt)
- case *EmbeddedJSON:
- enc := BorrowEncoder(nil)
- defer enc.Release()
- return enc.encodeEmbeddedJSON(vt)
- default:
- return nil, InvalidMarshalError(fmt.Sprintf(invalidMarshalErrorMsg, reflect.TypeOf(vt).String()))
- }
+ return marshal(v, false)
+}
+
+// MarshalAny returns the JSON encoding of v.
+//
+// MarshalAny takes interface v and encodes it according to its type.
+// Basic example with a string:
+// b, err := gojay.Marshal("test")
+// fmt.Println(b) // "test"
+//
+// If v implements Marshaler or Marshaler interface
+// it will call the corresponding methods.
+//
+// If it cannot find any supported type it will be marshalled though default Go "json" package.
+// Warning, this function can be slower, than a default "Marshal"
+//
+// type TestStruct struct {
+// id int
+// }
+//
+// func main() {
+// test := &TestStruct{
+// id: 123456,
+// }
+// b, _ := gojay.Marshal(test)
+// fmt.Println(b) // {"id": 123456}
+// }
+func MarshalAny(v interface{}) ([]byte, error) {
+ return marshal(v, true)
+}
+
+func marshal(v interface{}, any bool) ([]byte, error) {
+ var (
+ enc = BorrowEncoder(nil)
+
+ buf []byte
+ err error
+ )
+
+ buf, err = func() ([]byte, error) {
+ switch vt := v.(type) {
+ case MarshalerJSONObject:
+ return enc.encodeObject(vt)
+ case MarshalerJSONArray:
+ return enc.encodeArray(vt)
+ case string:
+ return enc.encodeString(vt)
+ case bool:
+ return enc.encodeBool(vt)
+ case int:
+ return enc.encodeInt(vt)
+ case int64:
+ return enc.encodeInt64(vt)
+ case int32:
+ return enc.encodeInt(int(vt))
+ case int16:
+ return enc.encodeInt(int(vt))
+ case int8:
+ return enc.encodeInt(int(vt))
+ case uint64:
+ return enc.encodeInt(int(vt))
+ case uint32:
+ return enc.encodeInt(int(vt))
+ case uint16:
+ return enc.encodeInt(int(vt))
+ case uint8:
+ return enc.encodeInt(int(vt))
+ case float64:
+ return enc.encodeFloat(vt)
+ case float32:
+ return enc.encodeFloat32(vt)
+ case *EmbeddedJSON:
+ return enc.encodeEmbeddedJSON(vt)
+ default:
+ if any {
+ return json.Marshal(vt)
+ }
+
+ return nil, InvalidMarshalError(fmt.Sprintf(invalidMarshalErrorMsg, reflect.TypeOf(vt).String()))
+ }
+ } ()
+
+ enc.Release()
+ return buf, err
}
// MarshalerJSONObject is the interface to implement for struct to be encoded
diff --git a/encode_object_test.go b/encode_object_test.go
@@ -274,6 +274,22 @@ func TestEncoderObjectMarshalAPI(t *testing.T) {
string(r),
"Result of marshalling is different as the one expected")
})
+ t.Run("marshal-any-object", func(t *testing.T) {
+ test := struct {
+ Foo string
+ Bar int
+ }{
+ "test",
+ 100,
+ }
+ r, err := MarshalAny(test)
+ assert.Nil(t, err, "Error should be nil")
+ assert.Equal(
+ t,
+ `{"Foo":"test","Bar":100}`,
+ string(r),
+ "Result of marshalling is different as the one expected")
+ })
}
type TestObectOmitEmpty struct {