Skip to content

Commit

Permalink
Arrays (#155)
Browse files Browse the repository at this point in the history
* Fix parsing to array types

* Handle conversions from float to int for arrays
  • Loading branch information
ohler55 committed Dec 18, 2023
1 parent 3af4d72 commit f563a34
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 5 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

The structure and content of this file follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [1.21.0] - unreleased
## [1.21.0] - 2023-12-18
### Added
- Added the Expr function `BracketString` to force the use of bracket
notation to for normalized paths as described by the draft IETF
JSONPath document in section 2.7.
- Added `jp.Expr.Locate()` function that returns normalized paths for JSONPath expression.
### Fixed
- TBD Unmarshal now supports arrays such as `[4]int`.
- Unmarshal now supports arrays such as `[4]int`.

## [1.20.3] - 2023-11-09
### Added
Expand Down
20 changes: 18 additions & 2 deletions alt/recomposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ func (r *Recomposer) recomp(v any, rv reflect.Value) {
rv = rv.Elem()
}
switch rv.Kind() {
case reflect.Array, reflect.Slice:
case reflect.Slice:
va, ok := (v).([]any)
if !ok {
vv := reflect.ValueOf(v)
Expand Down Expand Up @@ -346,6 +346,23 @@ func (r *Recomposer) recomp(v any, rv reflect.Value) {
}
}
rv.Set(av)
case reflect.Array:
vv := reflect.ValueOf(v)
if vv.Kind() != reflect.Slice {
panic(fmt.Errorf("can only recompose a %s from a []any, not a %T", rv.Type(), v))
}
inSize := vv.Len()
size := rv.Len()
for i := 0; i < inSize; i++ {
if size <= i {
break
}
// Kind of awkward but the double reflect is needed to get the
// actual type of the element value if the slice input is []any.
ev := vv.Index(i).Interface()
ri := rv.Index(i)
r.setValue(ev, ri, nil)
}
case reflect.Map:
if v == nil {
return
Expand Down Expand Up @@ -404,7 +421,6 @@ func (r *Recomposer) recomp(v any, rv reflect.Value) {
}
break
}

vv := reflect.ValueOf(v)
if vv.Kind() != reflect.Map {
panic(fmt.Errorf("can only recompose a %s from a map[string]any, not a %T", rv.Type(), v))
Expand Down
18 changes: 18 additions & 0 deletions alt/recomposer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -838,3 +838,21 @@ func TestRecomposeReflectNumber(t *testing.T) {
src["asInt"] = json.Number("123.4")
tt.Panic(t, func() { _ = r.MustRecompose(src, &pan) })
}

type Triple [3]int

func TestRecomposeReflectArray(t *testing.T) {
r, err := alt.NewRecomposer("type", nil)
tt.Nil(t, err, "NewRecomposer")

var tri Triple

_ = r.MustRecompose([]any{1, 2, 3}, &tri)
tt.Equal(t, `[1 2 3]`, pretty.SEN(tri))

tri = Triple{0, 0, 0}
_ = r.MustRecompose([]any{1, 2, 3, 4}, &tri)
tt.Equal(t, `[1 2 3]`, pretty.SEN(tri))

tt.Panic(t, func() { _ = r.MustRecompose(map[string]any{"a": 1}, &tri) })
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/ohler55/ojg

go 1.20
go 1.21
3 changes: 3 additions & 0 deletions jp/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type Any struct {
X any
}

type triple [3]int

var (
getTestData = []*getData{
{path: "", expect: []any{}},
Expand Down Expand Up @@ -155,6 +157,7 @@ var (
{path: "a..b", expect: []any{112, 122, 132, 142}},
{path: "[1]", expect: []any{2}, data: []int{1, 2, 3}},
{path: "[-1]", expect: []any{3}, data: []int{1, 2, 3}},
{path: "[1]", expect: []any{2}, data: triple{1, 2, 3}},
{path: "[-1,'a']", expect: []any{3}, data: []int{1, 2, 3}},
{path: "$[::]", expect: []any{1, 2, 3}, data: []int{1, 2, 3}},
{path: "[-1,'a'].x",
Expand Down
1 change: 1 addition & 0 deletions jp/locate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var (
{path: "", expect: []string{}},
{path: "a.b", data: map[string]any{"a": map[string]any{"b": 2}, "x": 3}, expect: []string{"a.b"}},
{path: "a[1]", data: map[string]any{"a": []any{1, 2, 3}}, expect: []string{"a[1]"}},
{path: "[1]", data: triple{1, 2, 3}, expect: []string{"[1]"}},
{path: "a[-1]", data: map[string]any{"a": []any{1, 2, 3}}, expect: []string{"a[2]"}},
{path: "a[*]", data: map[string]any{"a": []any{1, 2, 3}}, expect: []string{"a[0]", "a[1]", "a[2]"}},
{path: "$.a.*.b", max: 2, expect: []string{"$.a[0].b", "$.a[1].b"}},
Expand Down
12 changes: 12 additions & 0 deletions oj/unmashall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,15 @@ func TestUnmarshaler(t *testing.T) {
tt.Equal(t, 1, len(tags))
tt.Equal(t, 1, tags["k1"])
}

type Triple [3]int

func TestUnmarshalArray(t *testing.T) {
var tri Triple
src := []byte(`[1.0, 2, 3]`)
err := oj.Unmarshal(src, &tri)
tt.Nil(t, err)
tt.Equal(t, 1, tri[0])
tt.Equal(t, 2, tri[1])
tt.Equal(t, 3, tri[2])
}

0 comments on commit f563a34

Please sign in to comment.