diff --git a/go.sum b/go.sum index e863f51..de9b3b5 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,46 @@ +github.com/agnivade/wasmbrowsertest v0.4.0 h1:B2P8ZYqAmD3nmLkJaxuUFiv25J+2XUkOmhAJyfV0X0A= +github.com/agnivade/wasmbrowsertest v0.4.0/go.mod h1:baeI8tnJ+NNeVbOfF1/GaRmg6qiJOJ6BCnUASRFAtsk= +github.com/chromedp/cdproto v0.0.0-20210713064928-7d28b402946a/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U= +github.com/chromedp/cdproto v0.0.0-20211002082225-0242b9dca9f4 h1:5s+L1cvXzolXsfAChfBr6KmD86rJR5BTeJnz36vQCmo= +github.com/chromedp/cdproto v0.0.0-20211002082225-0242b9dca9f4/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U= +github.com/chromedp/chromedp v0.7.4 h1:U+0d3WbB/Oj4mDuBOI0P7S3PJEued5UZIl5AJ3QulwU= +github.com/chromedp/chromedp v0.7.4/go.mod h1:dBj+SXuQHznp6ZPwZeDDEBZKwclUwDLbZ0hjMialMYs= +github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/go-interpreter/wagon v0.6.0 h1:BBxDxjiJiHgw9EdkYXAWs8NHhwnazZ5P2EWBW5hFNWw= +github.com/go-interpreter/wagon v0.6.0/go.mod h1:5+b/MBYkclRZngKF5s6qrgWxSLgE9F5dFdO1hAueZLc= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= +github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= +github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b h1:GX4+fGLMW5XTmDXB3R6UhTwZIYqgAOdA19+Ea0+3CU4= +github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc/go.mod h1:NoCfSFWosfqMqmmD7hApkirIK9ozpHjxRnRxs1l413A= +golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211003122950-b1ebd4e1001c h1:EyJTLQbOxvk8V6oDdD8ILR1BOs3nEJXThD6aqsiPNkM= +golang.org/x/sys v0.0.0-20211003122950-b1ebd4e1001c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/marshal.go b/marshal.go index 2116dd7..6aaf47b 100644 --- a/marshal.go +++ b/marshal.go @@ -4,6 +4,7 @@ import ( "fmt" "reflect" "syscall/js" + "time" ) // Marshal to js.Value @@ -37,12 +38,23 @@ func marshalStruct(v reflect.Value) (js.Value, error) { t = t.Elem() v = v.Elem() } + + // Handle time.Time as a special case + switch timeVal := v.Interface().(type) { + case time.Time: + return js.ValueOf(timeVal.Format(time.RFC3339)), nil + } + m := map[string]interface{}{} for i := 0; i < t.NumField(); i++ { fld := t.Field(i) fv := v.Field(i) ft := fld.Type name := fld.Name + // Skip unexported fields + if !fv.CanInterface() { + continue + } tag := parseTag(fld.Tag) if tag.ignore { continue diff --git a/marshal_test.go b/marshal_test.go index 60f3cfa..e5ee91c 100644 --- a/marshal_test.go +++ b/marshal_test.go @@ -3,6 +3,7 @@ package jsref import ( "fmt" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -121,14 +122,20 @@ func TestMarshalStruct(t *testing.T) { require := require.New(t) lst := []string{"sdf", "eeee"} + testTime := time.Now() + testTimeString := testTime.Format(time.RFC3339) s := struct { - Name string - Age int - List []string + Name string + Age int + List []string + Time time.Time + unexported string }{ - Name: "tester", - Age: 666, - List: lst, + Name: "tester", + Age: 666, + List: lst, + Time: testTime, + unexported: "skip me", } out, err := Marshal(s) @@ -143,6 +150,11 @@ func TestMarshalStruct(t *testing.T) { for i := 0; i < list.Length(); i++ { require.Equal(lst[i], list.Index(i).String()) } + timeJS := out.Get("Time") + require.Equal(testTimeString, timeJS.String()) + unexported := out.Get("unexported") + require.True(unexported.IsUndefined()) + } func TestExample(t *testing.T) { diff --git a/unmarshal.go b/unmarshal.go index 563e7d7..a999683 100644 --- a/unmarshal.go +++ b/unmarshal.go @@ -4,6 +4,7 @@ import ( "fmt" "reflect" "syscall/js" + "time" ) // Unmarshal from js.Value @@ -32,9 +33,6 @@ func unmarshalStruct(v reflect.Value, val js.Value) error { if !IsValid(val) { return nil } - if !IsObject(val) { - return fmt.Errorf("val must be object for struct") - } t := v.Type() if isPtr(t) { if v.IsNil() { @@ -43,6 +41,20 @@ func unmarshalStruct(v reflect.Value, val js.Value) error { v = v.Elem() t = t.Elem() } + // Handle time.Time as a special case + switch v.Interface().(type) { + case time.Time: + timeVal, err := time.Parse(time.RFC3339, val.String()) + if err != nil { + return err + } + v.Set(reflect.ValueOf(timeVal)) + return nil + } + if !IsObject(val) { + return fmt.Errorf("val must be object for struct. val=%v", val) + } + for i := 0; i < t.NumField(); i++ { fld := t.Field(i) fv := v.Field(i) @@ -143,6 +155,10 @@ func unmarshalScalar(v reflect.Value, val js.Value) error { } v = v.Elem() } + // Skip unexported fields + if !v.CanInterface() { + return nil + } switch { case isBool(t): v.SetBool(val.Bool()) diff --git a/unmarshal_test.go b/unmarshal_test.go index 517144c..09d7088 100644 --- a/unmarshal_test.go +++ b/unmarshal_test.go @@ -3,6 +3,7 @@ package jsref import ( "syscall/js" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -41,15 +42,21 @@ func TestUnamrshalMap(t *testing.T) { } func TestUnamrshalStruct(t *testing.T) { + testTime := time.Now() + testTimeString := testTime.Format(time.RFC3339) obj := js.ValueOf(map[string]interface{}{ - "Ena": "one", - "dio": true, - "Tria": 3, + "Ena": "one", + "dio": true, + "Tria": 3, + "Time": testTimeString, + "unexported": "skip me", }) out := &struct { - Ena string - Dio bool `jsref:"dio"` - Tria uint + Ena string + Dio bool `jsref:"dio"` + Tria uint + Time time.Time + unexported string }{} err := Unmarshal(out, obj) @@ -59,5 +66,6 @@ func TestUnamrshalStruct(t *testing.T) { require.Equal("one", out.Ena) require.Equal(true, out.Dio) require.Equal(uint(3), out.Tria) - + timeOutString := out.Time.Format(time.RFC3339) + require.Equal(testTimeString, timeOutString) }