Skip to content

Commit

Permalink
feat (payload) Get() accept paths.like.this[15]
Browse files Browse the repository at this point in the history
  • Loading branch information
pentateu committed Apr 16, 2020
1 parent 9da6339 commit aae177a
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 2 deletions.
2 changes: 1 addition & 1 deletion context/contextFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (context *Context) BrokerDelegates() *moleculer.BrokerDelegates {
return context.broker
}

// ChildActionContext : create a chiold context for a specific action call.
// ChildActionContext : create a child context for a specific action call.
func (context *Context) ChildActionContext(actionName string, params moleculer.Payload, opts ...moleculer.Options) moleculer.BrokerContext {
parentContext := context
meta := parentContext.meta
Expand Down
1 change: 1 addition & 0 deletions moleculer.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type Payload interface {
Time() time.Time
TimeArray() []time.Time
Array() []Payload
At(index int) Payload
Len() int
Get(path string, defaultValue ...interface{}) Payload
//Only return a payload containing only the field specified
Expand Down
69 changes: 68 additions & 1 deletion payload/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package payload
import (
"errors"
"fmt"
"regexp"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -216,6 +217,17 @@ func (p *RawPayload) First() moleculer.Payload {
return New(nil)
}

//At returns the item at the given index
func (p *RawPayload) At(index int) moleculer.Payload {
if transformer := ArrayTransformer(&p.source); transformer != nil {
l := transformer.InterfaceArray(&p.source)
if index >= 0 && index < len(l) {
return New(l[index])
}
}
return nil
}

func (p *RawPayload) Array() []moleculer.Payload {
if transformer := ArrayTransformer(&p.source); transformer != nil {
source := transformer.InterfaceArray(&p.source)
Expand Down Expand Up @@ -439,7 +451,62 @@ func (p *RawPayload) mapGet(path string) (interface{}, bool) {
return nil, false
}

func (p *RawPayload) Get(path string, defaultValue ...interface{}) moleculer.Payload {
func isPath(s string) bool {
return strings.Contains(s, ".")
}

var indexedKey = regexp.MustCompile(`^(\w+)\[(\d+)\]$`)

//isIndexed checks if key is indexed e.g. stage[0]
func isIndexed(s string) bool {
return indexedKey.MatchString(s)
}

func splitIndex(s string) (key string, index int) {
parts := indexedKey.FindStringSubmatch(s)
key = parts[1]
index, _ = strconv.Atoi(parts[2])
return key, index
}

func (p *RawPayload) Get(s string, defaultValue ...interface{}) moleculer.Payload {
//check if is a path of key
if isPath(s) {
if defaultValue != nil {
return p.getPath(s, defaultValue)
}
return p.getPath(s)
}
if isIndexed(s) {
k, index := splitIndex(s)
var v moleculer.Payload
if defaultValue != nil {
v = p.getKey(k, defaultValue)
} else {
v = p.getKey(k)
}
return v.At(index)
}
if defaultValue != nil {
return p.getKey(s, defaultValue)
}
return p.getKey(s)
}

//getPath get a value using a path expression e.g. address.country.code
// it also accepts indexed lists like address.options[0].label
func (p *RawPayload) getPath(path string, defaultValue ...interface{}) moleculer.Payload {
parts := strings.Split(path, ".")
k := parts[0]
v := p.Get(k, defaultValue)
for i := 1; i < len(parts); i++ {
k = parts[i]
v = v.Get(k, defaultValue)
}
return v
}

func (p *RawPayload) getKey(path string, defaultValue ...interface{}) moleculer.Payload {
if value, ok := p.mapGet(path); ok {
return New(value)
}
Expand Down
28 changes: 28 additions & 0 deletions payload/payload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,4 +347,32 @@ var _ = Describe("Payload", func() {
Expect(snap.SnapshotMulti("PayloadError() .Error()", p.Error())).ShouldNot(HaveOccurred())
Expect(snap.SnapshotMulti("PayloadError() .ErrorPayload()", p.ErrorPayload())).ShouldNot(HaveOccurred())
})

type M map[string]interface{}
It("should deal field paths name.subname...", func() {
p := New(M{
"name": "John",
"lastname": "Snow",
"address": M{
"street": "jonny ave",
"country": M{
"code": "NZ",
"name": "New Zealand",
},
"options": []M{
M{
"label": "item 1",
},
M{
"label": "item 2",
},
},
},
})
Expect(p.Get("name").String()).Should(Equal("John"))
Expect(p.Get("address.street").String()).Should(Equal("jonny ave"))
Expect(p.Get("address.country.code").String()).Should(Equal("NZ"))
Expect(p.Get("address.options[0].label").String()).Should(Equal("item 1"))
Expect(p.Get("address.options[1].label").String()).Should(Equal("item 2"))
})
})
11 changes: 11 additions & 0 deletions serializer/jsonSerializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,17 @@ func (payload JSONPayload) TimeArray() []time.Time {
return nil
}

func (payload JSONPayload) At(index int) moleculer.Payload {
if payload.IsArray() {
source := payload.result.Array()
if index >= 0 && index < len(source) {
item := source[index]
return JSONPayload{item, payload.logger}
}
}
return nil
}

func (payload JSONPayload) Array() []moleculer.Payload {
if payload.IsArray() {
source := payload.result.Array()
Expand Down

0 comments on commit aae177a

Please sign in to comment.