Skip to content

Commit

Permalink
refactor: UnmarshalJSON function
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriyLewen committed Sep 10, 2024
1 parent 5fff7ac commit 0613621
Showing 1 changed file with 12 additions and 58 deletions.
70 changes: 12 additions & 58 deletions pkg/types/finding.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,89 +52,43 @@ func NewModifiedFinding(f finding, status FindingStatus, statement, source strin
}
}

// MarshalJSON correctly marshals ModifiedFinding.Finding given the type and `MarshalJSON` functions of struct fields
func (m *ModifiedFinding) MarshalJSON() ([]byte, error) {
var raw struct {
Type FindingType `json:"Type"`
Status FindingStatus `json:"Status"`
Statement string `json:"Statement"`
Source string `json:"Source"`
Finding json.RawMessage `json:"Finding"`
}
raw.Type = m.Type
raw.Status = m.Status
raw.Statement = m.Statement
raw.Source = m.Source

// Define a `Finding` type and marshal as a struct of that type.
// This is necessary to run the `MarshalJSON` functions on the struct fields.
var err error
switch val := m.Finding.(type) {
case DetectedVulnerability:
if raw.Finding, err = json.Marshal(&val); err != nil {
return nil, xerrors.Errorf("unable to marshal `DetectedVulnerability` Findings: %w", err)
}
case DetectedMisconfiguration:
if raw.Finding, err = json.Marshal(&val); err != nil {
return nil, xerrors.Errorf("unable to marshal `DetectedMisconfiguration` Findings: %w", err)
}
case DetectedSecret:
if raw.Finding, err = json.Marshal(&val); err != nil {
return nil, xerrors.Errorf("unable to marshal `DetectedSecret` Findings: %w", err)
}
case DetectedLicense:
if raw.Finding, err = json.Marshal(&val); err != nil {
return nil, xerrors.Errorf("unable to marshal `DetectedLicense` Findings: %w", err)
}
default:
return nil, xerrors.Errorf("invalid Finding type: %T", val)
}

return json.Marshal(&raw)
}

// UnmarshalJSON unmarshals ModifiedFinding given the type and `UnmarshalJSON` functions of struct fields
func (m *ModifiedFinding) UnmarshalJSON(data []byte) error {
raw := struct {
Type FindingType `json:"Type"`
Status FindingStatus `json:"Status"`
Statement string `json:"Statement"`
Source string `json:"Source"`
Finding json.RawMessage `json:"Finding"`
}{}
type Alias ModifiedFinding
aux := &struct {
Finding json.RawMessage `json:"Finding"`
*Alias
}{
Alias: (*Alias)(m),
}

if err := json.Unmarshal(data, &raw); err != nil {
if err := json.Unmarshal(data, &aux); err != nil {
return err
}

m.Type = raw.Type
m.Status = raw.Status
m.Statement = raw.Statement
m.Source = raw.Source

// Select struct by m.Type to avoid errors with Unmarshal
switch m.Type {
case FindingTypeVulnerability:
rawFinding := DetectedVulnerability{}
if err := json.Unmarshal(raw.Finding, &rawFinding); err != nil {
if err := json.Unmarshal(aux.Finding, &rawFinding); err != nil {
return xerrors.Errorf("unable to unmarshal %q type: %w", m.Type, err)
}
m.Finding = rawFinding
case FindingTypeMisconfiguration:
rawFinding := DetectedMisconfiguration{}
if err := json.Unmarshal(raw.Finding, &rawFinding); err != nil {
if err := json.Unmarshal(aux.Finding, &rawFinding); err != nil {
return xerrors.Errorf("unable to unmarshal %q type: %w", m.Type, err)
}
m.Finding = rawFinding
case FindingTypeSecret:
rawFinding := DetectedSecret{}
if err := json.Unmarshal(raw.Finding, &rawFinding); err != nil {
if err := json.Unmarshal(aux.Finding, &rawFinding); err != nil {
return xerrors.Errorf("unable to unmarshal %q type: %w", m.Type, err)
}
m.Finding = rawFinding
case FindingTypeLicense:
rawFinding := DetectedLicense{}
if err := json.Unmarshal(raw.Finding, &rawFinding); err != nil {
if err := json.Unmarshal(aux.Finding, &rawFinding); err != nil {
return xerrors.Errorf("unable to unmarshal %q type: %w", m.Type, err)
}
m.Finding = rawFinding
Expand Down

0 comments on commit 0613621

Please sign in to comment.