Skip to content

Commit

Permalink
Merge pull request #36 from johanneswuerbach/time
Browse files Browse the repository at this point in the history
fix: support time.Time values
  • Loading branch information
snorwin authored Dec 14, 2023
2 parents 5734676 + a6cda54 commit c4ca5cd
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 22 deletions.
39 changes: 26 additions & 13 deletions patch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"strconv"
"strings"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
Expand All @@ -20,19 +21,20 @@ type A struct {
}

type B struct {
Str string `json:"str,omitempty"`
Bool bool `json:"bool"`
Int int `json:"int"`
Int8 int8 `json:"int8"`
Int16 int16 `json:"int16"`
Int32 int32 `json:"int32"`
Int64 int64 `json:"int64"`
Uint uint `json:"uint"`
Uint8 uint8 `json:"uint8"`
Uint16 uint16 `json:"uint16"`
Uint32 uint32 `json:"uint32"`
Uint64 uint64 `json:"uint64"`
UintPtr uintptr `json:"ptr" faker:"-"`
Str string `json:"str,omitempty"`
Bool bool `json:"bool"`
Int int `json:"int"`
Int8 int8 `json:"int8"`
Int16 int16 `json:"int16"`
Int32 int32 `json:"int32"`
Int64 int64 `json:"int64"`
Uint uint `json:"uint"`
Uint8 uint8 `json:"uint8"`
Uint16 uint16 `json:"uint16"`
Uint32 uint32 `json:"uint32"`
Uint64 uint64 `json:"uint64"`
UintPtr uintptr `json:"ptr" faker:"-"`
Time time.Time `json:"time"`
}

type C struct {
Expand Down Expand Up @@ -156,6 +158,17 @@ var _ = Describe("JSONPatch", func() {
// no change
testPatch(B{Uint: 1, Uint8: 1, Uint16: 1, Uint32: 1, Uint64: 1}, B{Uint: 1, Uint8: 1, Uint16: 1, Uint32: 1, Uint64: 1})
})
It("time", func() {
now := time.Now()
// add
testPatch(B{Time: now}, B{})
// remove
testPatch(B{}, B{Time: now})
// replace
testPatch(B{Time: now}, B{Time: now.Add(1 * time.Hour)})
// no change
testPatch(B{Time: now}, B{Time: now})
})
})
Context("CreateJsonPatch_map", func() {
It("string map", func() {
Expand Down
47 changes: 38 additions & 9 deletions walker.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"sort"
"strconv"
"strings"
"time"
)

const (
Expand Down Expand Up @@ -39,15 +40,7 @@ func (w *walker) walk(modified, current reflect.Value, pointer JSONPointer) erro
case reflect.Interface:
return w.processInterface(modified, current, pointer)
case reflect.String:
if modified.String() != current.String() {
if modified.String() == "" {
w.remove(pointer, current.String())
} else if current.String() == "" {
w.add(pointer, modified.String())
} else {
w.replace(pointer, modified.String(), current.String())
}
}
return w.processString(modified, current, pointer)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if modified.Int() != current.Int() {
w.replace(pointer, modified.Int(), current.Int())
Expand Down Expand Up @@ -80,6 +73,21 @@ func (w *walker) processInterface(modified reflect.Value, current reflect.Value,
return nil
}

// processString processes reflect.String values
func (w *walker) processString(modified reflect.Value, current reflect.Value, pointer JSONPointer) error {
if modified.String() != current.String() {
if modified.String() == "" {
w.remove(pointer, current.String())
} else if current.String() == "" {
w.add(pointer, modified.String())
} else {
w.replace(pointer, modified.String(), current.String())
}
}

return nil
}

// processMap processes reflect.Map values
func (w *walker) processMap(modified reflect.Value, current reflect.Value, pointer JSONPointer) error {
// NOTE: currently only map[string]interface{} are supported
Expand Down Expand Up @@ -248,6 +256,19 @@ func (w *walker) processStruct(modified, current reflect.Value, pointer JSONPoin
return nil
}

if modified.Type().PkgPath() == "time" && modified.Type().Name() == "Time" {
m, err := toTimeStrValue(modified)
if err != nil {
return err
}

c, err := toTimeStrValue(current)
if err != nil {
return err
}
return w.processString(m, c, pointer)
}

// process all struct fields, the order of the fields of the modified and current JSON object is identical because their types match
for j := 0; j < modified.NumField(); j++ {
tag := strings.Split(modified.Type().Field(j).Tag.Get(jsonTag), ",")[0]
Expand All @@ -264,6 +285,14 @@ func (w *walker) processStruct(modified, current reflect.Value, pointer JSONPoin
return nil
}

func toTimeStrValue(v reflect.Value) (reflect.Value, error) {
t, err := v.Interface().(time.Time).MarshalText()
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(string(t)), nil
}

// extractIgnoreSliceOrderMatchValue extracts the value which is used to match the modified and current values to ignore the slice order
func extractIgnoreSliceOrderMatchValue(value reflect.Value, fieldName string) string {
switch value.Kind() {
Expand Down

0 comments on commit c4ca5cd

Please sign in to comment.