Skip to content

Commit 6fa3f8f

Browse files
authored
Merge pull request #1 from luedigernet/master
Added map structure.Decoder to get support for son fields of type timeTime
2 parents f05ce96 + bce3985 commit 6fa3f8f

File tree

2 files changed

+60
-11
lines changed

2 files changed

+60
-11
lines changed

jsonhal.go

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"errors"
88
"fmt"
99
"reflect"
10+
"time"
1011

1112
"github.com/mitchellh/mapstructure"
1213
)
@@ -44,6 +45,7 @@ type Embedder interface {
4445
type Hal struct {
4546
Links map[string]*Link `json:"_links,omitempty"`
4647
Embedded map[string]Embedded `json:"_embedded,omitempty"`
48+
decoder *mapstructure.Decoder
4749
}
4850

4951
// SetLink sets a link (self, next, etc). Title argument is optional
@@ -105,13 +107,46 @@ func (h *Hal) CountEmbedded(name string) (int, error) {
105107
return reflect.ValueOf(interface{}(e)).Len(), nil
106108
}
107109

110+
// decodeHook is used to support datatypes that mapstructure does not support native
111+
func (h *Hal) decodeHook(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
112+
113+
// only if target datatype is time.Time and if source datatype is string
114+
if t == reflect.TypeOf(time.Time{}) && f == reflect.TypeOf("") {
115+
return time.Parse(time.RFC3339, data.(string))
116+
}
117+
118+
//everything else would not be handled for now
119+
return data, nil
120+
}
121+
108122
// DecodeEmbedded decodes embedded objects into a struct
109-
func (h *Hal) DecodeEmbedded(name string, result interface{}) error {
123+
func (h *Hal) DecodeEmbedded(name string, result interface{}) (err error) {
124+
var dec *mapstructure.Decoder
125+
defer func() {
126+
if r := recover(); r != nil {
127+
err = r.(error)
128+
129+
}
130+
}()
131+
110132
e, err := h.GetEmbedded(name)
111133
if err != nil {
112-
return err
134+
panic(err)
135+
}
136+
//setup a new decoder if not already present
137+
if h.decoder == nil {
138+
dec, err = mapstructure.NewDecoder(&mapstructure.DecoderConfig{Result: result, DecodeHook: h.decodeHook})
139+
if err != nil {
140+
panic(err)
141+
}
142+
h.decoder = dec
143+
}
144+
145+
err = h.decoder.Decode(e)
146+
if err != nil {
147+
panic(err)
113148
}
114-
return mapstructure.Decode(interface{}(e), result)
149+
return nil
115150
}
116151

117152
// DeleteEmbedded removes an embedded resource named name if it is found

jsonhal_test.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import (
66
"log"
77
"reflect"
88
"testing"
9+
"time"
910

1011
"github.com/RichardKnop/jsonhal"
12+
1113
"github.com/stretchr/testify/assert"
1214
)
1315

@@ -21,8 +23,9 @@ type HelloWorld struct {
2123
// Foobar is a simple test struct
2224
type Foobar struct {
2325
jsonhal.Hal
24-
ID uint `json:"id"`
25-
Name string `json:"name"`
26+
ID uint `json:"id"`
27+
Name string `json:"name"`
28+
Date time.Time `json:"date"`
2629
}
2730

2831
// Qux is a simple test struct
@@ -67,7 +70,8 @@ var expectedJSON3 = []byte(`{
6770
}
6871
},
6972
"id": 1,
70-
"name": "Foo bar 1"
73+
"name": "Foo bar 1",
74+
"date":"2017-09-12T08:45:20Z"
7175
}
7276
},
7377
"id": 1,
@@ -89,7 +93,8 @@ var expectedJSON4 = []byte(`{
8993
}
9094
},
9195
"id": 1,
92-
"name": "Foo bar 1"
96+
"name": "Foo bar 1",
97+
"date":"2017-09-12T08:45:20Z"
9398
},
9499
{
95100
"_links": {
@@ -98,7 +103,8 @@ var expectedJSON4 = []byte(`{
98103
}
99104
},
100105
"id": 2,
101-
"name": "Foo bar 2"
106+
"name": "Foo bar 2",
107+
"date":"2017-09-12T08:45:20Z"
102108
}
103109
]
104110
},
@@ -121,7 +127,8 @@ var expectedJSON5 = []byte(`{
121127
}
122128
},
123129
"id": 1,
124-
"name": "Foo bar 1"
130+
"name": "Foo bar 1",
131+
"date":"2017-09-12T08:45:20Z"
125132
},
126133
{
127134
"_links": {
@@ -130,7 +137,8 @@ var expectedJSON5 = []byte(`{
130137
}
131138
},
132139
"id": 2,
133-
"name": "Foo bar 2"
140+
"name": "Foo bar 2",
141+
"date":"2017-09-12T08:45:20Z"
134142
}
135143
],
136144
"quxes": [
@@ -204,6 +212,7 @@ func TestHal(t *testing.T) {
204212
assert.Equal(t, expected.String(), string(actual))
205213

206214
// Let's add more links and a single embedded resource
215+
date, _ := time.Parse(time.RFC3339, "2017-09-12T08:45:20Z")
207216
helloWorld = &HelloWorld{ID: 1, Name: "Hello World"}
208217
helloWorld.SetLink(
209218
"self", // name
@@ -220,7 +229,7 @@ func TestHal(t *testing.T) {
220229
"/v1/hello/world?offset=0&limit=2", // href
221230
"", // title
222231
)
223-
foobar = &Foobar{ID: 1, Name: "Foo bar 1"}
232+
foobar = &Foobar{ID: 1, Name: "Foo bar 1", Date: date}
224233
foobar.SetLink("self", "/v1/foo/bar/1", "")
225234
helloWorld.SetEmbedded("foobar", jsonhal.Embedded(foobar))
226235

@@ -254,6 +263,7 @@ func TestHal(t *testing.T) {
254263
},
255264
ID: 1,
256265
Name: "Foo bar 1",
266+
Date: date,
257267
},
258268
{
259269
Hal: jsonhal.Hal{
@@ -263,6 +273,7 @@ func TestHal(t *testing.T) {
263273
},
264274
ID: 2,
265275
Name: "Foo bar 2",
276+
Date: date,
266277
},
267278
}
268279
helloWorld.SetEmbedded("foobars", jsonhal.Embedded(foobars))
@@ -297,6 +308,7 @@ func TestHal(t *testing.T) {
297308
},
298309
ID: 1,
299310
Name: "Foo bar 1",
311+
Date: date,
300312
},
301313
{
302314
Hal: jsonhal.Hal{
@@ -306,6 +318,7 @@ func TestHal(t *testing.T) {
306318
},
307319
ID: 2,
308320
Name: "Foo bar 2",
321+
Date: date,
309322
},
310323
}
311324
helloWorld.SetEmbedded("foobars", jsonhal.Embedded(foobars))
@@ -491,6 +504,7 @@ func TestUnmarshalingAndDecodeEmbedded(t *testing.T) {
491504
assert.NoError(t, hw.DecodeEmbedded("foobar", f))
492505
assert.Equal(t, uint(1), f.ID)
493506
assert.Equal(t, "Foo bar 1", f.Name)
507+
assert.Equal(t, "2017-09-12T08:45:20Z", f.Date.Format(time.RFC3339))
494508

495509
// Slice of embedded objects
496510

0 commit comments

Comments
 (0)