Skip to content

Commit 4b84dab

Browse files
authored
refactor: migrate from github.com/aquasecurity/jfather to github.com/go-json-experiment/json (#8591)
1 parent 9792611 commit 4b84dab

File tree

15 files changed

+336
-279
lines changed

15 files changed

+336
-279
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ require (
4848
github.com/docker/go-units v0.5.0
4949
github.com/fatih/color v1.18.0
5050
github.com/go-git/go-git/v5 v5.14.0
51-
github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535 // Replace with encoding/json/v2 when proposal is accepted. Track https://github.com/golang/go/issues/71497
51+
github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 // Replace with encoding/json/v2 when proposal is accepted. Track https://github.com/golang/go/issues/71497
5252
github.com/go-openapi/runtime v0.28.0 // indirect
5353
github.com/go-openapi/strfmt v0.23.0 // indirect
5454
github.com/go-redis/redis/v8 v8.11.5

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -1127,8 +1127,8 @@ github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7
11271127
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
11281128
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
11291129
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
1130-
github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535 h1:yE7argOs92u+sSCRgqqe6eF+cDaVhSPlioy1UkA0p/w=
1131-
github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535/go.mod h1:BWmvoE1Xia34f3l/ibJweyhrT+aROb/FQ6d+37F0e2s=
1130+
github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 h1:F8d1AJ6M9UQCavhwmO6ZsrYLfG8zVFWfEfMS2MXPkSY=
1131+
github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
11321132
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
11331133
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
11341134
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=

pkg/dependency/parser/c/conan/parse.go

+19-49
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
package conan
22

33
import (
4-
"io"
54
"slices"
65
"strings"
76

7+
"github.com/go-json-experiment/json"
8+
"github.com/go-json-experiment/json/jsontext"
89
"github.com/samber/lo"
910
"golang.org/x/xerrors"
1011

11-
"github.com/aquasecurity/jfather"
1212
"github.com/aquasecurity/trivy/pkg/dependency"
1313
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
1414
"github.com/aquasecurity/trivy/pkg/log"
1515
xio "github.com/aquasecurity/trivy/pkg/x/io"
16+
xjson "github.com/aquasecurity/trivy/pkg/x/json"
1617
)
1718

1819
type LockFile struct {
@@ -25,19 +26,20 @@ type GraphLock struct {
2526
}
2627

2728
type Node struct {
28-
Ref string `json:"ref"`
29-
Requires []string `json:"requires"`
30-
StartLine int
31-
EndLine int
29+
Ref string `json:"ref"`
30+
Requires []string `json:"requires"`
31+
xjson.Location
3232
}
33+
type Requires []Require
3334

3435
type Require struct {
3536
Dependency string
36-
StartLine int
37-
EndLine int
37+
xjson.Location
3838
}
3939

40-
type Requires []Require
40+
func (r *Require) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
41+
return json.UnmarshalDecode(dec, &r.Dependency)
42+
}
4143

4244
type Parser struct {
4345
logger *log.Logger
@@ -63,7 +65,7 @@ func (p *Parser) parseV1(lock LockFile) ([]ftypes.Package, []ftypes.Dependency,
6365
if node.Ref == "" {
6466
continue
6567
}
66-
pkg, err := toPackage(node.Ref, node.StartLine, node.EndLine)
68+
pkg, err := toPackage(node.Ref, node.Location)
6769
if err != nil {
6870
p.logger.Debug("Parse ref error", log.Err(err))
6971
continue
@@ -105,7 +107,7 @@ func (p *Parser) parseV2(lock LockFile) ([]ftypes.Package, []ftypes.Dependency,
105107
var pkgs []ftypes.Package
106108

107109
for _, req := range lock.Requires {
108-
pkg, err := toPackage(req.Dependency, req.StartLine, req.EndLine)
110+
pkg, err := toPackage(req.Dependency, req.Location)
109111
if err != nil {
110112
p.logger.Debug("Creating package entry from requirement failed", log.Err(err))
111113
continue
@@ -118,12 +120,7 @@ func (p *Parser) parseV2(lock LockFile) ([]ftypes.Package, []ftypes.Dependency,
118120

119121
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
120122
var lock LockFile
121-
122-
input, err := io.ReadAll(r)
123-
if err != nil {
124-
return nil, nil, xerrors.Errorf("failed to read conan lock file: %w", err)
125-
}
126-
if err := jfather.Unmarshal(input, &lock); err != nil {
123+
if err := xjson.UnmarshalRead(r, &lock); err != nil {
127124
return nil, nil, xerrors.Errorf("failed to decode conan lock file: %w", err)
128125
}
129126

@@ -152,42 +149,15 @@ func parsePackage(text string) (string, string, error) {
152149
return ss[0], ss[1], nil
153150
}
154151

155-
func toPackage(pkg string, startLine, endLine int) (ftypes.Package, error) {
152+
func toPackage(pkg string, location xjson.Location) (ftypes.Package, error) {
156153
name, version, err := parsePackage(pkg)
157154
if err != nil {
158155
return ftypes.Package{}, err
159156
}
160157
return ftypes.Package{
161-
ID: dependency.ID(ftypes.Conan, name, version),
162-
Name: name,
163-
Version: version,
164-
Locations: []ftypes.Location{
165-
{
166-
StartLine: startLine,
167-
EndLine: endLine,
168-
},
169-
},
158+
ID: dependency.ID(ftypes.Conan, name, version),
159+
Name: name,
160+
Version: version,
161+
Locations: []ftypes.Location{ftypes.Location(location)},
170162
}, nil
171163
}
172-
173-
// UnmarshalJSONWithMetadata needed to detect start and end lines of deps
174-
func (n *Node) UnmarshalJSONWithMetadata(node jfather.Node) error {
175-
if err := node.Decode(&n); err != nil {
176-
return err
177-
}
178-
// Decode func will overwrite line numbers if we save them first
179-
n.StartLine = node.Range().Start.Line
180-
n.EndLine = node.Range().End.Line
181-
return nil
182-
}
183-
184-
func (r *Require) UnmarshalJSONWithMetadata(node jfather.Node) error {
185-
var dep string
186-
if err := node.Decode(&dep); err != nil {
187-
return err
188-
}
189-
r.Dependency = dep
190-
r.StartLine = node.Range().Start.Line
191-
r.EndLine = node.Range().End.Line
192-
return nil
193-
}

pkg/dependency/parser/dotnet/core_deps/parse.go

+8-31
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
package core_deps
22

33
import (
4-
"io"
54
"sort"
65
"strings"
76
"sync"
87

98
"github.com/samber/lo"
109
"golang.org/x/xerrors"
1110

12-
"github.com/aquasecurity/jfather"
1311
"github.com/aquasecurity/trivy/pkg/dependency"
1412
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
1513
"github.com/aquasecurity/trivy/pkg/log"
1614
xio "github.com/aquasecurity/trivy/pkg/x/io"
15+
xjson "github.com/aquasecurity/trivy/pkg/x/json"
1716
)
1817

1918
type dotNetDependencies struct {
@@ -23,9 +22,8 @@ type dotNetDependencies struct {
2322
}
2423

2524
type dotNetLibrary struct {
26-
Type string `json:"type"`
27-
StartLine int
28-
EndLine int
25+
Type string `json:"type"`
26+
xjson.Location
2927
}
3028

3129
type RuntimeTarget struct {
@@ -52,12 +50,7 @@ func NewParser() *Parser {
5250

5351
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
5452
var depsFile dotNetDependencies
55-
56-
input, err := io.ReadAll(r)
57-
if err != nil {
58-
return nil, nil, xerrors.Errorf("read error: %w", err)
59-
}
60-
if err = jfather.Unmarshal(input, &depsFile); err != nil {
53+
if err := xjson.UnmarshalRead(r, &depsFile); err != nil {
6154
return nil, nil, xerrors.Errorf("failed to decode .deps.json file: %w", err)
6255
}
6356

@@ -87,15 +80,10 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc
8780
}
8881

8982
pkgs = append(pkgs, ftypes.Package{
90-
ID: dependency.ID(ftypes.DotNetCore, split[0], split[1]),
91-
Name: split[0],
92-
Version: split[1],
93-
Locations: []ftypes.Location{
94-
{
95-
StartLine: lib.StartLine,
96-
EndLine: lib.EndLine,
97-
},
98-
},
83+
ID: dependency.ID(ftypes.DotNetCore, split[0], split[1]),
84+
Name: split[0],
85+
Version: split[1],
86+
Locations: []ftypes.Location{ftypes.Location(lib.Location)},
9987
})
10088
}
10189

@@ -118,14 +106,3 @@ func (p *Parser) isRuntimeLibrary(targetLibs map[string]TargetLib, library strin
118106
// Check that `runtime`, `runtimeTarget` and `native` sections are not empty
119107
return !lo.IsEmpty(lib)
120108
}
121-
122-
// UnmarshalJSONWithMetadata needed to detect start and end lines of deps
123-
func (t *dotNetLibrary) UnmarshalJSONWithMetadata(node jfather.Node) error {
124-
if err := node.Decode(&t); err != nil {
125-
return err
126-
}
127-
// Decode func will overwrite line numbers if we save them first
128-
t.StartLine = node.Range().Start.Line
129-
t.EndLine = node.Range().End.Line
130-
return nil
131-
}

pkg/dependency/parser/dotnet/core_deps/parse_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func TestParse(t *testing.T) {
8282
{
8383
name: "sad path",
8484
file: "testdata/invalid.deps.json",
85-
wantErr: "failed to decode .deps.json file: EOF",
85+
wantErr: "failed to decode .deps.json file: jsontext: unexpected EOF within",
8686
},
8787
}
8888

pkg/dependency/parser/nodejs/npm/parse.go

+7-45
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package npm
22

33
import (
44
"fmt"
5-
"io"
65
"maps"
76
"path"
87
"slices"
@@ -12,13 +11,13 @@ import (
1211
"github.com/samber/lo"
1312
"golang.org/x/xerrors"
1413

15-
"github.com/aquasecurity/jfather"
1614
"github.com/aquasecurity/trivy/pkg/dependency"
1715
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
1816
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
1917
"github.com/aquasecurity/trivy/pkg/log"
2018
"github.com/aquasecurity/trivy/pkg/set"
2119
xio "github.com/aquasecurity/trivy/pkg/x/io"
20+
xjson "github.com/aquasecurity/trivy/pkg/x/json"
2221
)
2322

2423
const nodeModulesDir = "node_modules"
@@ -34,8 +33,7 @@ type Dependency struct {
3433
Dependencies map[string]Dependency `json:"dependencies"`
3534
Requires map[string]string `json:"requires"`
3635
Resolved string `json:"resolved"`
37-
StartLine int
38-
EndLine int
36+
xjson.Location
3937
}
4038

4139
type Package struct {
@@ -49,8 +47,7 @@ type Package struct {
4947
Dev bool `json:"dev"`
5048
Link bool `json:"link"`
5149
Workspaces []string `json:"workspaces"`
52-
StartLine int
53-
EndLine int
50+
xjson.Location
5451
}
5552

5653
type Parser struct {
@@ -65,11 +62,7 @@ func NewParser() *Parser {
6562

6663
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
6764
var lockFile LockFile
68-
input, err := io.ReadAll(r)
69-
if err != nil {
70-
return nil, nil, xerrors.Errorf("read error: %w", err)
71-
}
72-
if err := jfather.Unmarshal(input, &lockFile); err != nil {
65+
if err := xjson.UnmarshalRead(r, &lockFile); err != nil {
7366
return nil, nil, xerrors.Errorf("decode error: %w", err)
7467
}
7568

@@ -117,10 +110,6 @@ func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftype
117110
}
118111

119112
pkgID := packageID(pkgName, pkg.Version)
120-
location := ftypes.Location{
121-
StartLine: pkg.StartLine,
122-
EndLine: pkg.EndLine,
123-
}
124113

125114
var ref ftypes.ExternalRef
126115
if pkg.Resolved != "" {
@@ -145,7 +134,7 @@ func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftype
145134
sortExternalReferences(savedPkg.ExternalReferences)
146135
}
147136

148-
savedPkg.Locations = append(savedPkg.Locations, location)
137+
savedPkg.Locations = append(savedPkg.Locations, ftypes.Location(pkg.Location))
149138
sort.Sort(savedPkg.Locations)
150139

151140
pkgs[pkgID] = savedPkg
@@ -159,7 +148,7 @@ func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftype
159148
Relationship: lo.Ternary(pkgIndirect, ftypes.RelationshipIndirect, ftypes.RelationshipDirect),
160149
Dev: pkg.Dev,
161150
ExternalReferences: lo.Ternary(ref.URL != "", []ftypes.ExternalRef{ref}, nil),
162-
Locations: []ftypes.Location{location},
151+
Locations: []ftypes.Location{ftypes.Location(pkg.Location)},
163152
}
164153
pkgs[pkgID] = newPkg
165154

@@ -304,12 +293,7 @@ func (p *Parser) parseV1(dependencies map[string]Dependency, versions map[string
304293
URL: dep.Resolved,
305294
},
306295
},
307-
Locations: []ftypes.Location{
308-
{
309-
StartLine: dep.StartLine,
310-
EndLine: dep.EndLine,
311-
},
312-
},
296+
Locations: []ftypes.Location{ftypes.Location(dep.Location)},
313297
}
314298
pkgs = append(pkgs, pkg)
315299

@@ -396,28 +380,6 @@ func joinPaths(paths ...string) string {
396380
return strings.Join(paths, "/")
397381
}
398382

399-
// UnmarshalJSONWithMetadata needed to detect start and end lines of deps for v1
400-
func (t *Dependency) UnmarshalJSONWithMetadata(node jfather.Node) error {
401-
if err := node.Decode(&t); err != nil {
402-
return err
403-
}
404-
// Decode func will overwrite line numbers if we save them first
405-
t.StartLine = node.Range().Start.Line
406-
t.EndLine = node.Range().End.Line
407-
return nil
408-
}
409-
410-
// UnmarshalJSONWithMetadata needed to detect start and end lines of deps for v2 or newer
411-
func (t *Package) UnmarshalJSONWithMetadata(node jfather.Node) error {
412-
if err := node.Decode(&t); err != nil {
413-
return err
414-
}
415-
// Decode func will overwrite line numbers if we save them first
416-
t.StartLine = node.Range().Start.Line
417-
t.EndLine = node.Range().End.Line
418-
return nil
419-
}
420-
421383
func packageID(name, version string) string {
422384
return dependency.ID(ftypes.Npm, name, version)
423385
}

0 commit comments

Comments
 (0)