github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/format/syftjson/model/source.go (about) 1 package model 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 "strconv" 8 "strings" 9 10 "github.com/anchore/syft/syft/source" 11 "github.com/lineaje-labs/syft/syft/internal/sourcemetadata" 12 ) 13 14 // Source object represents the thing that was cataloged 15 type Source struct { 16 ID string `json:"id"` 17 Name string `json:"name"` 18 Version string `json:"version"` 19 Type string `json:"type"` 20 Metadata interface{} `json:"metadata"` 21 } 22 23 // sourceUnpacker is used to unmarshal Source objects 24 type sourceUnpacker struct { 25 ID string `json:"id,omitempty"` 26 Name string `json:"name"` 27 Version string `json:"version"` 28 Type string `json:"type"` 29 Metadata json.RawMessage `json:"metadata"` 30 Target json.RawMessage `json:"target"` // pre-v9 schema support 31 } 32 33 // UnmarshalJSON populates a source object from JSON bytes. 34 func (s *Source) UnmarshalJSON(b []byte) error { 35 var unpacker sourceUnpacker 36 err := json.Unmarshal(b, &unpacker) 37 if err != nil { 38 return err 39 } 40 41 s.Name = unpacker.Name 42 s.Version = unpacker.Version 43 s.Type = unpacker.Type 44 s.ID = unpacker.ID 45 46 if len(unpacker.Target) > 0 { 47 s.Type = cleanPreSchemaV9MetadataType(s.Type) 48 s.Metadata, err = extractPreSchemaV9Metadata(s.Type, unpacker.Target) 49 if err != nil { 50 return fmt.Errorf("unable to extract pre-schema-v9 source metadata: %w", err) 51 } 52 return nil 53 } 54 55 return unpackSrcMetadata(s, unpacker) 56 } 57 58 func unpackSrcMetadata(s *Source, unpacker sourceUnpacker) error { 59 rt := sourcemetadata.ReflectTypeFromJSONName(s.Type) 60 if rt == nil { 61 return fmt.Errorf("unable to find source metadata type=%q", s.Type) 62 } 63 64 val := reflect.New(rt).Interface() 65 if len(unpacker.Metadata) > 0 { 66 if err := json.Unmarshal(unpacker.Metadata, val); err != nil { 67 return err 68 } 69 } 70 71 s.Metadata = reflect.ValueOf(val).Elem().Interface() 72 73 return nil 74 } 75 76 func cleanPreSchemaV9MetadataType(t string) string { 77 t = strings.ToLower(t) 78 if t == "dir" { 79 return "directory" 80 } 81 return t 82 } 83 84 func extractPreSchemaV9Metadata(t string, target []byte) (interface{}, error) { 85 switch t { 86 case "directory", "dir": 87 cleanTarget, err := strconv.Unquote(string(target)) 88 if err != nil { 89 cleanTarget = string(target) 90 } 91 92 return source.DirectorySourceMetadata{ 93 Path: cleanTarget, 94 }, nil 95 96 case "file": 97 cleanTarget, err := strconv.Unquote(string(target)) 98 if err != nil { 99 cleanTarget = string(target) 100 } 101 102 return source.FileSourceMetadata{ 103 Path: cleanTarget, 104 }, nil 105 106 case "image": 107 var payload source.StereoscopeImageSourceMetadata 108 if err := json.Unmarshal(target, &payload); err != nil { 109 return nil, err 110 } 111 return payload, nil 112 113 default: 114 return nil, fmt.Errorf("unsupported package metadata type: %+v", t) 115 } 116 }