Fix: Parse package.json with non-standard fields in 'author' section (#3300)

* Improved parsing of package.json 'author' section

Signed-off-by: Piotr Radkowski <piotr.radkowski@contractors.roche.com>

* test: parse 'package.json' files with non-standard fields in author section

Signed-off-by: Piotr Radkowski <piotr.radkowski@contractors.roche.com>

---------

Signed-off-by: Piotr Radkowski <piotr.radkowski@contractors.roche.com>
Co-authored-by: Piotr Radkowski <piotr.radkowski@contractors.roche.com>
This commit is contained in:
Piotr Radkowski 2024-10-07 16:26:04 +02:00 committed by GitHub
parent 25f5c6729f
commit 3b9c55d28b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 12 deletions

View File

@ -82,23 +82,23 @@ func parsePackageJSON(_ context.Context, _ file.Resolver, _ *generic.Environment
func (a *author) UnmarshalJSON(b []byte) error { func (a *author) UnmarshalJSON(b []byte) error {
var authorStr string var authorStr string
var fields map[string]string
var auth author var auth author
if err := json.Unmarshal(b, &authorStr); err != nil { if err := json.Unmarshal(b, &authorStr); err == nil {
// string parsing did not work, assume a map was given // successfully parsed as a string, now parse that string into fields
// for more information: https://docs.npmjs.com/files/package.json#people-fields-author-contributors fields := internal.MatchNamedCaptureGroups(authorPattern, authorStr)
if err := mapstructure.Decode(fields, &auth); err != nil {
return fmt.Errorf("unable to decode package.json author: %w", err)
}
} else {
// it's a map that may contain fields of various data types (not just strings)
var fields map[string]interface{}
if err := json.Unmarshal(b, &fields); err != nil { if err := json.Unmarshal(b, &fields); err != nil {
return fmt.Errorf("unable to parse package.json author: %w", err) return fmt.Errorf("unable to parse package.json author: %w", err)
} }
} else { if err := mapstructure.Decode(fields, &auth); err != nil {
// parse out "name <email> (url)" into an author struct return fmt.Errorf("unable to decode package.json author: %w", err)
fields = internal.MatchNamedCaptureGroups(authorPattern, authorStr) }
}
// translate the map into a structure
if err := mapstructure.Decode(fields, &auth); err != nil {
return fmt.Errorf("unable to decode package.json author: %w", err)
} }
*a = auth *a = auth

View File

@ -179,6 +179,27 @@ func TestParsePackageJSON(t *testing.T) {
}, },
}, },
}, },
{
Fixture: "test-fixtures/pkg-json/package-author-non-standard.json",
ExpectedPkg: pkg.Package{
Name: "npm",
Version: "6.14.6",
PURL: "pkg:npm/npm@6.14.6",
Type: pkg.NpmPkg,
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-author-non-standard.json")),
),
Language: pkg.JavaScript,
Metadata: pkg.NpmPackage{
Name: "npm",
Version: "6.14.6",
Author: "npm Inc. (https://www.npmjs.com/)",
Homepage: "https://docs.npmjs.com/",
URL: "https://github.com/npm/cli",
Description: "a package manager for JavaScript",
},
},
},
} }
for _, test := range tests { for _, test := range tests {

View File

@ -0,0 +1,16 @@
{
"version": "6.14.6",
"name": "npm",
"description": "a package manager for JavaScript",
"homepage": "https://docs.npmjs.com/",
"author": {
"name": "npm Inc.",
"url": "https://www.npmjs.com/",
"organization": true
},
"repository": {
"type": "git",
"url": "https://github.com/npm/cli"
},
"license": "Artistic-2.0"
}