├── .travis.yml ├── AUTHORS ├── LICENSE ├── Makefile ├── README.md ├── gen_go.go ├── gen_go_test.go ├── gen_thrift.go ├── gen_thrift_test.go ├── lint.go ├── main.go ├── parser.go ├── parser_test.go ├── schema └── schema.go └── testdata ├── go.golden ├── nvd ├── CVE_JSON_4.0_min.schema ├── cvss-v2.0.json ├── cvss-v3.0.json └── nvd_cve_feed_json_1.0.schema └── thrift.golden /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | os: osx 4 | 5 | go: 6 | - "1.10" 7 | - "1.x" 8 | 9 | git: 10 | depth: 1 11 | 12 | before_script: 13 | - brew install thrift 14 | 15 | script: 16 | - make 17 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of jsonschema2go authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS file. 3 | # 4 | # Names should be added to this file as 5 | # Name or Organization 6 | # 7 | # The email address is not required for organizations. 8 | # 9 | # Please keep the list sorted. 10 | 11 | Alexandre Fiori 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018-present jsonschema2go authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * The names of authors or contributors may NOT be used to endorse or 14 | promote products derived from this software without specific prior 15 | written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TEST_SCHEMA=testdata/nvd/nvd_cve_feed_json_1.0.schema 2 | 3 | all: \ 4 | binary \ 5 | test \ 6 | test-gen-go \ 7 | test-gen-thrift 8 | 9 | binary: 10 | go build -v 11 | 12 | test: 13 | go test -v -cover 14 | 15 | gen-golden: binary 16 | ./jsonschema2go -gen go $(TEST_SCHEMA) > testdata/go.golden 17 | ./jsonschema2go -gen thrift $(TEST_SCHEMA) > testdata/thrift.golden 18 | 19 | test-gen-go: binary 20 | mkdir -p .test/go 21 | ./jsonschema2go -gen go -o .test/go/schema.go -gofmt $(TEST_SCHEMA) 22 | (cd .test/go && go build -v) 23 | 24 | test-gen-thrift: binary 25 | mkdir -p .test/thrift 26 | ./jsonschema2go -gen thrift -o .test/thrift/schema.thrift $(TEST_SCHEMA) 27 | (cd .test/thrift && thrift -gen go schema.thrift) 28 | 29 | clean: 30 | rm -rf .test jsonschema2go 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jsonschema2go 2 | 3 | [![Build Status](https://secure.travis-ci.org/fiorix/jsonschema2go.png)](http://travis-ci.org/fiorix/jsonschema2go) 4 | 5 | jsonschema2go is a code generator for JSON schemas. Supports schemas from local files or URL, and generates Go code, or thrift spec. 6 | 7 | This is a very naive and incomplete implementation. I wrote this code specifically to codegen the [NVD JSON schema](https://nvd.nist.gov/vuln/data-feeds#JSON_FEED), based on a few requirements: 8 | 9 | * The output is a single file 10 | * Consistent output given same input 11 | * Capable of generating at least Go and Thrift 12 | 13 | ### Download, install 14 | 15 | Requires Go 1.10 or newer. The generated thrift spec requires thrift compiler 0.11 or newer. 16 | 17 | Assuming you have a working Go environment: 18 | 19 | ``` 20 | go get github.com/fiorix/jsonschema2go 21 | go install github.com/fiorix/jsonschema2go 22 | ``` 23 | 24 | Output binary is $GOPATH/bin/jsonschema2go. 25 | 26 | ### Usage 27 | 28 | ``` 29 | use: ./jsonschema2go [flags] schema.json 30 | The input schema may be a local file or URL. 31 | -gen string 32 | set output format: go, thrift (default "go") 33 | -gofmt 34 | run gofmt on generated go code 35 | -gopkg string 36 | set name of generated go package (default "schema") 37 | -goptr 38 | generate go struct fields as pointers 39 | -o string 40 | set name of output file (default "-") 41 | -thriftns string 42 | set comma separated list of thrift namespaces (default "go schema,py schema") 43 | ``` 44 | 45 | --- 46 | 47 | Generate Go code: 48 | 49 | ``` 50 | jsonschema2go -gen go https://csrc.nist.gov/schema/nvd/feed/1.0/nvd_cve_feed_json_1.0.schema 51 | ``` 52 | 53 | Generate Thrift spec: 54 | 55 | ``` 56 | jsonschema2go -gen thrift https://csrc.nist.gov/schema/nvd/feed/1.0/nvd_cve_feed_json_1.0.schema 57 | ``` 58 | 59 | ### Generated type names 60 | 61 | Naming is hard. In jsonschema2go I made the choice to name generated Go and Thrift types after their respective filenames. In JSON schema, the body of the document is a type, like a struct, and it has no name. Hence using the filename with some normalization to idiomatic Go, with an adjusted list of keywords (e.g. CVE) for initialisms. 62 | 63 | You can see what it looks like in the golden files in the testdata directory. -------------------------------------------------------------------------------- /gen_go.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "flag" 6 | "fmt" 7 | "io" 8 | "os" 9 | "os/exec" 10 | "regexp" 11 | "sort" 12 | "strings" 13 | ) 14 | 15 | var ( 16 | flagGoPkg = flag.String("gopkg", "schema", "set name of generated go package") 17 | flagGoPtr = flag.Bool("goptr", false, "generate go struct fields as pointers") 18 | flagGoFmt = flag.Bool("gofmt", false, "run gofmt on generated go code") 19 | ) 20 | 21 | var goPublicTypeRegexp = regexp.MustCompile("[0-9A-Za-z]+") 22 | 23 | func goPublicType(name string) string { 24 | parts := goPublicTypeRegexp.FindAllString(name, -1) 25 | 26 | name = "" 27 | for _, part := range parts { 28 | p := strings.ToUpper(part) 29 | if _, exists := commonInitialisms[p]; exists { 30 | name += p 31 | } else { 32 | name += strings.Title(part) 33 | } 34 | } 35 | 36 | return name 37 | } 38 | 39 | var goTypeConv = typeConv{ 40 | "boolean": "bool", 41 | "number": "float64", 42 | "string": "string", 43 | } 44 | 45 | // GenGo generates Go code to w. 46 | func GenGo(w io.Writer, jsonSchemaURL string) error { 47 | list, err := ParseSchema(jsonSchemaURL) 48 | if err != nil { 49 | return err 50 | } 51 | 52 | pkg := *flagGoPkg 53 | var b bytes.Buffer 54 | fmt.Fprintf(&b, "// Package %s was auto-generated.\n", pkg) 55 | fmt.Fprintf(&b, "// Command: %s\n", commandLine()) 56 | fmt.Fprintf(&b, "package %s\n\n", pkg) 57 | 58 | for _, structType := range list { 59 | structName := goPublicType(structType.Name) 60 | fmt.Fprintf(&b, "// %s was auto-generated.\n", structName) 61 | if structType.Desc != "" { 62 | if !strings.HasSuffix(structType.Desc, ".") { 63 | structType.Desc += "." 64 | } 65 | fmt.Fprintf(&b, "// %s\n", structType.Desc) 66 | } 67 | if structType.File != "" { 68 | fmt.Fprintf(&b, "// Source: %s\n", structType.File) 69 | } 70 | fmt.Fprintf(&b, "type %s struct {\n", structName) 71 | 72 | fields := make([]string, 0, len(structType.Fields)) 73 | 74 | for _, structField := range structType.Fields { 75 | if structField.Type == "null" { 76 | continue 77 | } 78 | 79 | var line strings.Builder 80 | fmt.Fprintf(&line, "\t%s ", goPublicType(structField.Name)) 81 | if structField.IsSlice { 82 | fmt.Fprintf(&line, "[]") 83 | } 84 | if structField.IsStruct { 85 | if *flagGoPtr { 86 | fmt.Fprintf(&line, "*") 87 | } 88 | io.WriteString(&line, goPublicType(structField.Type)) 89 | } else { 90 | io.WriteString(&line, goTypeConv.Get(structField.Type)) 91 | } 92 | omit := "" 93 | if _, required := structType.Required[structField.Name]; !required { 94 | omit = ",omitempty" 95 | } 96 | fmt.Fprintf(&line, " `json:\"%s%s\"`", structField.Name, omit) 97 | fields = append(fields, line.String()) 98 | } 99 | 100 | sort.Strings(fields) 101 | io.WriteString(&b, strings.Join(fields, "\n")) 102 | io.WriteString(&b, "\n}\n\n") 103 | } 104 | 105 | if !*flagGoFmt { 106 | _, err := io.Copy(w, &b) 107 | return err 108 | } 109 | 110 | cmd := exec.Command("gofmt") 111 | cmd.Stdin = &b 112 | cmd.Stdout = w 113 | cmd.Stderr = os.Stderr 114 | return cmd.Run() 115 | } 116 | -------------------------------------------------------------------------------- /gen_go_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGenGo(t *testing.T) { 8 | testGenEqualGolden(t, GenGo, "testdata/go.golden") 9 | } 10 | -------------------------------------------------------------------------------- /gen_thrift.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io" 7 | "regexp" 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | var ( 13 | flagThriftNS = flag.String("thriftns", "go schema,py schema", "set comma separated list of thrift namespaces") 14 | ) 15 | 16 | var thriftPublicTypeRegexp = regexp.MustCompile("[0-9A-Za-z]+") 17 | 18 | func thriftPublicType(name string) string { 19 | parts := thriftPublicTypeRegexp.FindAllString(name, -1) 20 | return strings.Join(parts, "_") 21 | } 22 | 23 | //var thriftPublicType = goPublicType 24 | 25 | var thriftTypeConv = typeConv{ 26 | "boolean": "bool", 27 | "number": "double", 28 | "string": "string", 29 | } 30 | 31 | var thriftReservedWords = map[string]string{ 32 | "package": "_package", 33 | } 34 | 35 | // GenThrift generates thrift spec to w. 36 | func GenThrift(w io.Writer, jsonSchemaURL string) error { 37 | list, err := ParseSchema(jsonSchemaURL) 38 | if err != nil { 39 | return err 40 | } 41 | 42 | fmt.Fprintf(w, "// This thrift spec was auto-generated.\n") 43 | fmt.Fprintf(w, "// Command: %s\n\n", commandLine()) 44 | 45 | for _, ns := range strings.Split(*flagThriftNS, ",") { 46 | fmt.Fprintf(w, "namespace %s\n", strings.TrimSpace(ns)) 47 | } 48 | io.WriteString(w, "\n") 49 | 50 | for _, structType := range list { 51 | //structName := thriftPublicType(structType.Name) 52 | structName := goPublicType(structType.Name) 53 | fmt.Fprintf(w, "// %s was auto-generated.\n", structName) 54 | if structType.Desc != "" { 55 | if !strings.HasSuffix(structType.Desc, ".") { 56 | structType.Desc += "." 57 | } 58 | fmt.Fprintf(w, "// %s\n", structType.Desc) 59 | } 60 | if structType.File != "" { 61 | fmt.Fprintf(w, "// Source: %s\n", structType.File) 62 | } 63 | fmt.Fprintf(w, "struct %s {\n", structName) 64 | 65 | fields := make(map[string]string) 66 | 67 | for _, structField := range structType.Fields { 68 | if structField.Type == "null" { 69 | continue 70 | } 71 | 72 | var t string 73 | if structField.IsStruct { 74 | //t = thriftPublicType(structField.Type) 75 | t = goPublicType(structField.Type) 76 | } else { 77 | t = thriftTypeConv.Get(structField.Type) 78 | } 79 | 80 | var line strings.Builder 81 | 82 | if _, required := structType.Required[structField.Name]; required { 83 | io.WriteString(&line, "required ") 84 | } else { 85 | io.WriteString(&line, "optional ") 86 | } 87 | 88 | if structField.IsSlice { 89 | fmt.Fprintf(&line, "list<%s>", t) 90 | } else { 91 | io.WriteString(&line, t) 92 | } 93 | 94 | name := thriftPublicType(structField.Name) 95 | if v, exists := thriftReservedWords[name]; exists { 96 | name = v 97 | } 98 | fmt.Fprintf(&line, " %s;", name) 99 | 100 | fields[name] = line.String() 101 | } 102 | 103 | keys := make([]string, 0, len(fields)) 104 | for key := range fields { 105 | keys = append(keys, key) 106 | } 107 | sort.Strings(keys) 108 | 109 | for i, key := range keys { 110 | fmt.Fprintf(w, " %d: %s\n", i+1, fields[key]) 111 | } 112 | 113 | fmt.Fprintf(w, "}\n\n") 114 | } 115 | 116 | return nil 117 | } 118 | -------------------------------------------------------------------------------- /gen_thrift_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGenThrift(t *testing.T) { 8 | testGenEqualGolden(t, GenThrift, "testdata/thrift.golden") 9 | } 10 | -------------------------------------------------------------------------------- /lint.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Copyright (c) 2013 The Go Authors. All rights reserved. 4 | // 5 | // Use of this source code is governed by a BSD-style 6 | // license that can be found in the LICENSE file or at 7 | // https://developers.google.com/open-source/licenses/bsd. 8 | 9 | // copied from https://github.com/golang/lint/blob/master/lint.go 10 | 11 | // commonInitialisms is a set of common initialisms. 12 | // Only add entries that are highly unlikely to be non-initialisms. 13 | // For instance, "ID" is fine (Freudian code is rare), but "AND" is not. 14 | var commonInitialisms = map[string]bool{ 15 | "ACL": true, 16 | "API": true, 17 | "ASCII": true, 18 | "CPU": true, 19 | "CSS": true, 20 | "DNS": true, 21 | "EOF": true, 22 | "GUID": true, 23 | "HTML": true, 24 | "HTTP": true, 25 | "HTTPS": true, 26 | "ID": true, 27 | "IP": true, 28 | "JSON": true, 29 | "LHS": true, 30 | "QPS": true, 31 | "RAM": true, 32 | "RHS": true, 33 | "RPC": true, 34 | "SLA": true, 35 | "SMTP": true, 36 | "SQL": true, 37 | "SSH": true, 38 | "TCP": true, 39 | "TLS": true, 40 | "TTL": true, 41 | "UDP": true, 42 | "UI": true, 43 | "UID": true, 44 | "UUID": true, 45 | "URI": true, 46 | "URL": true, 47 | "UTF8": true, 48 | "VM": true, 49 | "XML": true, 50 | "XMPP": true, 51 | "XSRF": true, 52 | "XSS": true, 53 | 54 | // jsonschema2go items 55 | "CPE": true, 56 | "CVE": true, 57 | "CVSS": true, 58 | "CVSSV2": true, 59 | "CVSSV3": true, 60 | "CWE": true, 61 | "NVD": true, 62 | } 63 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | flag.Usage = func() { 12 | fmt.Printf("use: %s [flags] schema.json\n", os.Args[0]) 13 | fmt.Printf("The input schema may be a local file or URL.\n") 14 | flag.PrintDefaults() 15 | os.Exit(1) 16 | } 17 | 18 | outputFile := flag.String("o", "-", "set name of output file") 19 | outputType := flag.String("gen", "go", "set output format: go, thrift") 20 | flag.Parse() 21 | 22 | if len(flag.Args()) == 0 { 23 | flag.Usage() 24 | } 25 | 26 | f, err := createFile(*outputFile) 27 | if err != nil { 28 | fmt.Println(err) 29 | os.Exit(1) 30 | } 31 | defer f.Close() 32 | 33 | jsonSchema := flag.Arg(0) 34 | 35 | switch *outputType { 36 | case "go": 37 | err = GenGo(f, jsonSchema) 38 | case "thrift": 39 | err = GenThrift(f, jsonSchema) 40 | default: 41 | err = fmt.Errorf("unsupported output type: %q", *outputType) 42 | } 43 | 44 | if err != nil { 45 | fmt.Println(err) 46 | os.Exit(1) 47 | } 48 | } 49 | 50 | func createFile(name string) (io.WriteCloser, error) { 51 | switch name { 52 | case "", "-": 53 | return os.Stdout, nil 54 | default: 55 | return os.Create(name) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /parser.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "net/url" 9 | "os" 10 | "path" 11 | "path/filepath" 12 | "regexp" 13 | "sort" 14 | "strings" 15 | 16 | "github.com/fiorix/jsonschema2go/schema" 17 | ) 18 | 19 | // ParseSchema open/fetch and parses JSON schema. 20 | func ParseSchema(jsonSchemaURL string) (StructList, error) { 21 | var list StructList 22 | err := fetchAndGenerate(&list, jsonSchemaURL) 23 | if err != nil { 24 | return nil, err 25 | } 26 | return list, nil 27 | } 28 | 29 | // StructList is a list of struct types (JSON objects) from the schema. 30 | type StructList []structType 31 | 32 | type structType struct { 33 | File string 34 | Name string 35 | Desc string 36 | Fields []structField 37 | Required map[string]struct{} 38 | } 39 | 40 | type structField struct { 41 | Name string 42 | Type string 43 | IsStruct bool 44 | IsSlice bool 45 | // TODO: min/max number and array items, enum options 46 | } 47 | 48 | type schema2go struct { 49 | root *schema.Schema 50 | baseURL string 51 | rootType string 52 | typeCache map[string]struct{} 53 | } 54 | 55 | var nameExtRegexp = regexp.MustCompile(`[._]min[.](json|schema)([.]gz)?$`) 56 | 57 | func nameFromFile(file string) string { 58 | idx := nameExtRegexp.FindStringIndex(file) 59 | if len(idx) > 0 { 60 | return strings.Replace(file[0:idx[0]], ".", "", -1) 61 | } 62 | ext := path.Ext(file) 63 | file = strings.Replace(file, ".", "", -1) 64 | if ext == "" { 65 | return file 66 | } 67 | return file[0 : len(file)-len(ext)+1] 68 | } 69 | 70 | func fetchAndGenerate(list *StructList, schemaURL string) error { 71 | root, err := openAndDecodeSchema(schemaURL) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | baseURL, file := filepath.Split(schemaURL) 77 | 78 | g := &schema2go{ 79 | root: root, 80 | baseURL: baseURL, 81 | rootType: nameFromFile(file), 82 | typeCache: make(map[string]struct{}), 83 | } 84 | 85 | return g.genStruct(list, g.rootType, schemaURL, root.Type) 86 | } 87 | 88 | func openAndDecodeSchema(schemaURL string) (*schema.Schema, error) { 89 | f, err := openSourceFile(schemaURL) 90 | if err != nil { 91 | return nil, err 92 | } 93 | defer f.Close() 94 | 95 | var root schema.Schema 96 | err = json.NewDecoder(f).Decode(&root) 97 | if err != nil { 98 | return nil, err 99 | } 100 | 101 | return &root, nil 102 | } 103 | 104 | func openSourceFile(schemaURL string) (io.ReadCloser, error) { 105 | u, err := url.Parse(schemaURL) 106 | if err != nil { 107 | return nil, err 108 | } 109 | 110 | switch { 111 | case u.Host == "" && u.Path != "": 112 | return os.Open(u.Path) 113 | case u.Host != "" && u.Path != "": 114 | resp, err := http.Get(schemaURL) 115 | if err != nil { 116 | return nil, err 117 | } 118 | return resp.Body, nil 119 | default: 120 | return nil, fmt.Errorf("invalid input schema: %q", schemaURL) 121 | } 122 | } 123 | 124 | func (g *schema2go) genStruct(list *StructList, name, file string, t *schema.Type) error { 125 | if _, exists := g.typeCache[name]; exists { 126 | return nil 127 | } 128 | 129 | g.typeCache[name] = struct{}{} 130 | 131 | switch { 132 | case t.Type != "object": 133 | return fmt.Errorf("schema type is not object: %q (root=%v)", name, file != "") 134 | case len(t.Properties) == 0: 135 | return fmt.Errorf("schema type has no properties: %q (root=%v)", name, file != "") 136 | } 137 | 138 | st := structType{ 139 | Name: name, 140 | File: file, 141 | Desc: t.Description, 142 | Required: make(map[string]struct{}), 143 | } 144 | 145 | keys := make([]string, 0, len(t.Properties)) 146 | for prop := range t.Properties { 147 | keys = append(keys, prop) 148 | } 149 | 150 | sort.Strings(keys) 151 | 152 | for _, fieldName := range keys { 153 | fieldProp := t.Properties[fieldName] 154 | field, err := g.genStructField(list, name, fieldName, fieldProp) 155 | if err != nil { 156 | return err 157 | } 158 | field.Name = fieldName 159 | st.Fields = append(st.Fields, *field) 160 | } 161 | 162 | for _, fieldName := range t.Required { 163 | st.Required[fieldName] = struct{}{} 164 | } 165 | 166 | *list = append(*list, st) 167 | 168 | return nil 169 | } 170 | 171 | type typeConv map[string]string 172 | 173 | func (t typeConv) Get(s string) string { 174 | n, ok := t[s] 175 | if !ok { 176 | panic("unsupported type: " + s) 177 | } 178 | return n 179 | } 180 | 181 | func (g *schema2go) genStructField(list *StructList, parent, name string, t *schema.Type) (*structField, error) { 182 | if t.Ref != "" { 183 | return g.genStructFieldFromRef(list, parent, name, t) 184 | } 185 | 186 | switch t.Type { 187 | case "string", "number", "boolean", "null": 188 | // TODO: handle number's min/max, etc 189 | f := &structField{ 190 | Name: name, 191 | Type: t.Type, 192 | } 193 | return f, nil 194 | case "array": 195 | f, err := g.genStructField(list, parent, name, t.Items) 196 | if err != nil { 197 | return nil, err 198 | } 199 | f.IsSlice = true 200 | return f, nil 201 | case "object": 202 | f := &structField{ 203 | Name: name, 204 | Type: path.Join(parent, name), 205 | IsStruct: true, 206 | } 207 | err := g.genStruct(list, f.Type, "", t) 208 | if err != nil { 209 | return nil, err 210 | } 211 | return f, nil 212 | default: 213 | if t.Enum == nil { 214 | return nil, fmt.Errorf("unknown field type for %q: %q", name, t.Type) 215 | } 216 | f := &structField{ 217 | Name: name, 218 | Type: "string", 219 | } 220 | return f, nil // TODO: handle enum properly 221 | } 222 | } 223 | 224 | func (g *schema2go) genStructFieldFromRef(list *StructList, parent, name string, t *schema.Type) (*structField, error) { 225 | u, err := url.Parse(t.Ref) 226 | if err != nil { 227 | return nil, err 228 | } 229 | 230 | switch { 231 | case strings.HasPrefix(u.Fragment, "/definitions/"): 232 | key := u.Fragment[len("/definitions/"):] 233 | def, exists := g.root.Definitions[key] 234 | if !exists { 235 | return nil, fmt.Errorf("unknown reference for %q: %q", name, t.Ref) 236 | } 237 | 238 | if def.Type == "" && len(def.Properties) > 0 { 239 | def.Type = "object" 240 | } 241 | 242 | parent, name = g.rootType, key 243 | f, err := g.genStructField(list, parent, name, def) 244 | if err != nil { 245 | return nil, err 246 | } 247 | f.Name = key 248 | return f, nil 249 | 250 | case u.Path != "": 251 | err := fetchAndGenerate(list, g.genURL(u.Host, u.Path)) 252 | if err != nil { 253 | return nil, err 254 | } 255 | 256 | f := &structField{ 257 | Name: name, 258 | Type: nameFromFile(u.Path), 259 | IsStruct: true, 260 | } 261 | 262 | return f, nil 263 | } 264 | 265 | panic("unsupported $ref: " + t.Ref) 266 | } 267 | 268 | func (g *schema2go) genURL(host, path string) string { 269 | if host == "" { 270 | return g.baseURL + path 271 | } 272 | return host + path 273 | } 274 | 275 | func commandLine() string { 276 | args := make([]string, 0, len(os.Args)) 277 | for _, arg := range os.Args { 278 | if strings.Index(arg, " ") == -1 || arg[0] != '-' { 279 | args = append(args, arg) 280 | continue 281 | } 282 | 283 | pos := strings.Index(arg, "=") 284 | pos++ 285 | arg = arg[0:pos] + fmt.Sprintf("%q", arg[pos:]) 286 | args = append(args, arg) 287 | } 288 | 289 | return strings.Join(args, " ") 290 | } 291 | -------------------------------------------------------------------------------- /parser_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "os" 9 | "os/exec" 10 | "regexp" 11 | "testing" 12 | ) 13 | 14 | const testSchemaFile = "testdata/nvd/nvd_cve_feed_json_1.0.schema" 15 | 16 | func TestParseSchema(t *testing.T) { 17 | _, err := ParseSchema(testSchemaFile) 18 | if err != nil { 19 | t.Fatal(err) 20 | } 21 | } 22 | 23 | type genFunc func(w io.Writer, jsonSchema string) error 24 | 25 | var goldenCmdRegexp = regexp.MustCompile("// Command: .*\n") 26 | 27 | func testGenEqualGolden(t *testing.T, f genFunc, file string) { 28 | var b bytes.Buffer 29 | err := f(&b, testSchemaFile) 30 | if err != nil { 31 | t.Fatal(err) 32 | } 33 | 34 | want, err := ioutil.ReadFile(file) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | 39 | // remove the command from generated code; won't ever match 40 | want = goldenCmdRegexp.ReplaceAll(want, nil) 41 | have := goldenCmdRegexp.ReplaceAll(b.Bytes(), nil) 42 | 43 | if !bytes.Equal(want, have) { 44 | t.Error("golden file (a) != generated file (b)") 45 | err = printDiff("gen", "tmp", want, have) 46 | if err != nil { 47 | t.Fatal(err) 48 | } 49 | } 50 | } 51 | 52 | // printDiff is a helper function used by tests. 53 | func printDiff(prefix, ext string, a, b []byte) error { 54 | files := []struct { 55 | Name string 56 | Data []byte 57 | }{ 58 | {Name: prefix + "-a." + ext, Data: a}, 59 | {Name: prefix + "-b." + ext, Data: b}, 60 | } 61 | for _, f := range files { 62 | defer os.Remove(f.Name) 63 | if err := ioutil.WriteFile(f.Name, f.Data, 0600); err != nil { 64 | return err 65 | } 66 | } 67 | var stdout, stderr bytes.Buffer 68 | cmd := exec.Command("diff", "-u", files[0].Name, files[1].Name) 69 | cmd.Stdout = &stdout 70 | cmd.Stderr = &stderr 71 | err := cmd.Run() 72 | if err != nil { 73 | return fmt.Errorf("%v: %s", err, stdout.String()) 74 | } 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /schema/schema.go: -------------------------------------------------------------------------------- 1 | // Package schema defines JSON schema types. 2 | // 3 | // Code borrowed from https://github.com/alecthomas/jsonschema/ 4 | // 5 | // Copyright (C) 2014 Alec Thomas 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | // this software and associated documentation files (the "Software"), to deal in 9 | // the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to do 12 | // so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | package schema 25 | 26 | import ( 27 | "encoding/json" 28 | ) 29 | 30 | // Schema is the root schema. 31 | // RFC draft-wright-json-schema-00, section 4.5 32 | type Schema struct { 33 | *Type 34 | Definitions Definitions `json:"definitions,omitempty"` 35 | } 36 | 37 | // Definitions hold schema definitions. 38 | // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.26 39 | // RFC draft-wright-json-schema-validation-00, section 5.26 40 | type Definitions map[string]*Type 41 | 42 | // Type represents a JSON Schema object type. 43 | type Type struct { 44 | // RFC draft-wright-json-schema-00 45 | Version string `json:"$schema,omitempty"` // section 6.1 46 | Ref string `json:"$ref,omitempty"` // section 7 47 | // RFC draft-wright-json-schema-validation-00, section 5 48 | MultipleOf int `json:"multipleOf,omitempty"` // section 5.1 49 | Maximum int `json:"maximum,omitempty"` // section 5.2 50 | ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"` // section 5.3 51 | Minimum int `json:"minimum,omitempty"` // section 5.4 52 | ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"` // section 5.5 53 | MaxLength int `json:"maxLength,omitempty"` // section 5.6 54 | MinLength int `json:"minLength,omitempty"` // section 5.7 55 | Pattern string `json:"pattern,omitempty"` // section 5.8 56 | AdditionalItems *Type `json:"additionalItems,omitempty"` // section 5.9 57 | Items *Type `json:"items,omitempty"` // section 5.9 58 | MaxItems int `json:"maxItems,omitempty"` // section 5.10 59 | MinItems int `json:"minItems,omitempty"` // section 5.11 60 | UniqueItems bool `json:"uniqueItems,omitempty"` // section 5.12 61 | MaxProperties int `json:"maxProperties,omitempty"` // section 5.13 62 | MinProperties int `json:"minProperties,omitempty"` // section 5.14 63 | Required []string `json:"required,omitempty"` // section 5.15 64 | Properties map[string]*Type `json:"properties,omitempty"` // section 5.16 65 | PatternProperties map[string]*Type `json:"patternProperties,omitempty"` // section 5.17 66 | AdditionalProperties json.RawMessage `json:"additionalProperties,omitempty"` // section 5.18 67 | Dependencies map[string]*Type `json:"dependencies,omitempty"` // section 5.19 68 | Enum []interface{} `json:"enum,omitempty"` // section 5.20 69 | Type string `json:"type,omitempty"` // section 5.21 70 | AllOf []*Type `json:"allOf,omitempty"` // section 5.22 71 | AnyOf []*Type `json:"anyOf,omitempty"` // section 5.23 72 | OneOf []*Type `json:"oneOf,omitempty"` // section 5.24 73 | Not *Type `json:"not,omitempty"` // section 5.25 74 | Definitions Definitions `json:"definitions,omitempty"` // section 5.26 75 | // RFC draft-wright-json-schema-validation-00, section 6, 7 76 | Title string `json:"title,omitempty"` // section 6.1 77 | Description string `json:"description,omitempty"` // section 6.1 78 | Default interface{} `json:"default,omitempty"` // section 6.2 79 | Format string `json:"format,omitempty"` // section 7 80 | // RFC draft-wright-json-schema-hyperschema-00, section 4 81 | Media *Type `json:"media,omitempty"` // section 4.3 82 | BinaryEncoding string `json:"binaryEncoding,omitempty"` // section 4.3 83 | } 84 | -------------------------------------------------------------------------------- /testdata/go.golden: -------------------------------------------------------------------------------- 1 | // Package schema was auto-generated. 2 | // Command: ./jsonschema2go -gen go testdata/nvd/nvd_cve_feed_json_1.0.schema 3 | package schema 4 | 5 | // NVDCVEFeedJSON10DefCPEName was auto-generated. 6 | // CPE name. 7 | type NVDCVEFeedJSON10DefCPEName struct { 8 | Cpe22Uri string `json:"cpe22Uri,omitempty"` 9 | Cpe23Uri string `json:"cpe23Uri"` 10 | } 11 | 12 | // NVDCVEFeedJSON10DefCPEMatch was auto-generated. 13 | // CPE match string or range. 14 | type NVDCVEFeedJSON10DefCPEMatch struct { 15 | CPEName []NVDCVEFeedJSON10DefCPEName `json:"cpe_name,omitempty"` 16 | Cpe22Uri string `json:"cpe22Uri,omitempty"` 17 | Cpe23Uri string `json:"cpe23Uri"` 18 | VersionEndExcluding string `json:"versionEndExcluding,omitempty"` 19 | VersionEndIncluding string `json:"versionEndIncluding,omitempty"` 20 | VersionStartExcluding string `json:"versionStartExcluding,omitempty"` 21 | VersionStartIncluding string `json:"versionStartIncluding,omitempty"` 22 | Vulnerable bool `json:"vulnerable"` 23 | } 24 | 25 | // NVDCVEFeedJSON10DefNode was auto-generated. 26 | // Defines a node or sub-node in an NVD applicability statement. 27 | type NVDCVEFeedJSON10DefNode struct { 28 | CPEMatch []NVDCVEFeedJSON10DefCPEMatch `json:"cpe_match,omitempty"` 29 | Children []NVDCVEFeedJSON10DefNode `json:"children,omitempty"` 30 | Negate bool `json:"negate,omitempty"` 31 | Operator string `json:"operator,omitempty"` 32 | } 33 | 34 | // NVDCVEFeedJSON10DefConfigurations was auto-generated. 35 | // Defines the set of product configurations for a NVD applicability statement. 36 | type NVDCVEFeedJSON10DefConfigurations struct { 37 | CVEDataVersion string `json:"CVE_data_version"` 38 | Nodes []NVDCVEFeedJSON10DefNode `json:"nodes,omitempty"` 39 | } 40 | 41 | // CVEJSON40CVEDataMeta was auto-generated. 42 | type CVEJSON40CVEDataMeta struct { 43 | ASSIGNER string `json:"ASSIGNER"` 44 | ID string `json:"ID"` 45 | STATE string `json:"STATE,omitempty"` 46 | } 47 | 48 | // CVEJSON40ProductVersionVersionData was auto-generated. 49 | type CVEJSON40ProductVersionVersionData struct { 50 | VersionAffected string `json:"version_affected,omitempty"` 51 | VersionValue string `json:"version_value"` 52 | } 53 | 54 | // CVEJSON40ProductVersion was auto-generated. 55 | type CVEJSON40ProductVersion struct { 56 | VersionData []CVEJSON40ProductVersionVersionData `json:"version_data"` 57 | } 58 | 59 | // CVEJSON40Product was auto-generated. 60 | type CVEJSON40Product struct { 61 | ProductName string `json:"product_name"` 62 | Version CVEJSON40ProductVersion `json:"version"` 63 | } 64 | 65 | // CVEJSON40AffectsVendorVendorDataProduct was auto-generated. 66 | type CVEJSON40AffectsVendorVendorDataProduct struct { 67 | ProductData []CVEJSON40Product `json:"product_data"` 68 | } 69 | 70 | // CVEJSON40AffectsVendorVendorData was auto-generated. 71 | type CVEJSON40AffectsVendorVendorData struct { 72 | Product CVEJSON40AffectsVendorVendorDataProduct `json:"product"` 73 | VendorName string `json:"vendor_name"` 74 | } 75 | 76 | // CVEJSON40AffectsVendor was auto-generated. 77 | type CVEJSON40AffectsVendor struct { 78 | VendorData []CVEJSON40AffectsVendorVendorData `json:"vendor_data"` 79 | } 80 | 81 | // CVEJSON40Affects was auto-generated. 82 | type CVEJSON40Affects struct { 83 | Vendor CVEJSON40AffectsVendor `json:"vendor"` 84 | } 85 | 86 | // CVEJSON40LangString was auto-generated. 87 | type CVEJSON40LangString struct { 88 | Lang string `json:"lang"` 89 | Value string `json:"value"` 90 | } 91 | 92 | // CVEJSON40Description was auto-generated. 93 | type CVEJSON40Description struct { 94 | DescriptionData []CVEJSON40LangString `json:"description_data"` 95 | } 96 | 97 | // CVEJSON40ProblemtypeProblemtypeData was auto-generated. 98 | type CVEJSON40ProblemtypeProblemtypeData struct { 99 | Description []CVEJSON40LangString `json:"description"` 100 | } 101 | 102 | // CVEJSON40Problemtype was auto-generated. 103 | type CVEJSON40Problemtype struct { 104 | ProblemtypeData []CVEJSON40ProblemtypeProblemtypeData `json:"problemtype_data"` 105 | } 106 | 107 | // CVEJSON40Reference was auto-generated. 108 | type CVEJSON40Reference struct { 109 | Name string `json:"name,omitempty"` 110 | Refsource string `json:"refsource,omitempty"` 111 | Tags []string `json:"tags,omitempty"` 112 | URL string `json:"url"` 113 | } 114 | 115 | // CVEJSON40References was auto-generated. 116 | type CVEJSON40References struct { 117 | ReferenceData []CVEJSON40Reference `json:"reference_data"` 118 | } 119 | 120 | // CVEJSON40 was auto-generated. 121 | // Source: testdata/nvd/CVE_JSON_4.0_min.schema 122 | type CVEJSON40 struct { 123 | Affects CVEJSON40Affects `json:"affects"` 124 | CVEDataMeta CVEJSON40CVEDataMeta `json:"CVE_data_meta"` 125 | DataFormat string `json:"data_format"` 126 | DataType string `json:"data_type"` 127 | DataVersion string `json:"data_version"` 128 | Description CVEJSON40Description `json:"description"` 129 | Problemtype CVEJSON40Problemtype `json:"problemtype"` 130 | References CVEJSON40References `json:"references"` 131 | } 132 | 133 | // CVSSV20 was auto-generated. 134 | // Source: testdata/nvd/cvss-v2.0.json 135 | type CVSSV20 struct { 136 | AccessComplexity string `json:"accessComplexity,omitempty"` 137 | AccessVector string `json:"accessVector,omitempty"` 138 | Authentication string `json:"authentication,omitempty"` 139 | AvailabilityImpact string `json:"availabilityImpact,omitempty"` 140 | AvailabilityRequirement string `json:"availabilityRequirement,omitempty"` 141 | BaseScore float64 `json:"baseScore"` 142 | CollateralDamagePotential string `json:"collateralDamagePotential,omitempty"` 143 | ConfidentialityImpact string `json:"confidentialityImpact,omitempty"` 144 | ConfidentialityRequirement string `json:"confidentialityRequirement,omitempty"` 145 | EnvironmentalScore float64 `json:"environmentalScore,omitempty"` 146 | Exploitability string `json:"exploitability,omitempty"` 147 | IntegrityImpact string `json:"integrityImpact,omitempty"` 148 | IntegrityRequirement string `json:"integrityRequirement,omitempty"` 149 | RemediationLevel string `json:"remediationLevel,omitempty"` 150 | ReportConfidence string `json:"reportConfidence,omitempty"` 151 | TargetDistribution string `json:"targetDistribution,omitempty"` 152 | TemporalScore float64 `json:"temporalScore,omitempty"` 153 | VectorString string `json:"vectorString"` 154 | Version string `json:"version"` 155 | } 156 | 157 | // NVDCVEFeedJSON10DefImpactBaseMetricV2 was auto-generated. 158 | // CVSS V2.0 score. 159 | type NVDCVEFeedJSON10DefImpactBaseMetricV2 struct { 160 | AcInsufInfo bool `json:"acInsufInfo,omitempty"` 161 | CVSSV2 CVSSV20 `json:"cvssV2,omitempty"` 162 | ExploitabilityScore float64 `json:"exploitabilityScore,omitempty"` 163 | ImpactScore float64 `json:"impactScore,omitempty"` 164 | ObtainAllPrivilege bool `json:"obtainAllPrivilege,omitempty"` 165 | ObtainOtherPrivilege bool `json:"obtainOtherPrivilege,omitempty"` 166 | ObtainUserPrivilege bool `json:"obtainUserPrivilege,omitempty"` 167 | Severity string `json:"severity,omitempty"` 168 | UserInteractionRequired bool `json:"userInteractionRequired,omitempty"` 169 | } 170 | 171 | // CVSSV30 was auto-generated. 172 | // Source: testdata/nvd/cvss-v3.0.json 173 | type CVSSV30 struct { 174 | AttackComplexity string `json:"attackComplexity,omitempty"` 175 | AttackVector string `json:"attackVector,omitempty"` 176 | AvailabilityImpact string `json:"availabilityImpact,omitempty"` 177 | AvailabilityRequirement string `json:"availabilityRequirement,omitempty"` 178 | BaseScore float64 `json:"baseScore"` 179 | BaseSeverity string `json:"baseSeverity"` 180 | ConfidentialityImpact string `json:"confidentialityImpact,omitempty"` 181 | ConfidentialityRequirement string `json:"confidentialityRequirement,omitempty"` 182 | EnvironmentalScore float64 `json:"environmentalScore,omitempty"` 183 | EnvironmentalSeverity string `json:"environmentalSeverity,omitempty"` 184 | ExploitCodeMaturity string `json:"exploitCodeMaturity,omitempty"` 185 | IntegrityImpact string `json:"integrityImpact,omitempty"` 186 | IntegrityRequirement string `json:"integrityRequirement,omitempty"` 187 | ModifiedAttackComplexity string `json:"modifiedAttackComplexity,omitempty"` 188 | ModifiedAttackVector string `json:"modifiedAttackVector,omitempty"` 189 | ModifiedAvailabilityImpact string `json:"modifiedAvailabilityImpact,omitempty"` 190 | ModifiedConfidentialityImpact string `json:"modifiedConfidentialityImpact,omitempty"` 191 | ModifiedIntegrityImpact string `json:"modifiedIntegrityImpact,omitempty"` 192 | ModifiedPrivilegesRequired string `json:"modifiedPrivilegesRequired,omitempty"` 193 | ModifiedScope string `json:"modifiedScope,omitempty"` 194 | ModifiedUserInteraction string `json:"modifiedUserInteraction,omitempty"` 195 | PrivilegesRequired string `json:"privilegesRequired,omitempty"` 196 | RemediationLevel string `json:"remediationLevel,omitempty"` 197 | ReportConfidence string `json:"reportConfidence,omitempty"` 198 | Scope string `json:"scope,omitempty"` 199 | TemporalScore float64 `json:"temporalScore,omitempty"` 200 | TemporalSeverity string `json:"temporalSeverity,omitempty"` 201 | UserInteraction string `json:"userInteraction,omitempty"` 202 | VectorString string `json:"vectorString"` 203 | Version string `json:"version"` 204 | } 205 | 206 | // NVDCVEFeedJSON10DefImpactBaseMetricV3 was auto-generated. 207 | // CVSS V3.0 score. 208 | type NVDCVEFeedJSON10DefImpactBaseMetricV3 struct { 209 | CVSSV3 CVSSV30 `json:"cvssV3,omitempty"` 210 | ExploitabilityScore float64 `json:"exploitabilityScore,omitempty"` 211 | ImpactScore float64 `json:"impactScore,omitempty"` 212 | } 213 | 214 | // NVDCVEFeedJSON10DefImpact was auto-generated. 215 | // Impact scores for a vulnerability as found on NVD. 216 | type NVDCVEFeedJSON10DefImpact struct { 217 | BaseMetricV2 NVDCVEFeedJSON10DefImpactBaseMetricV2 `json:"baseMetricV2,omitempty"` 218 | BaseMetricV3 NVDCVEFeedJSON10DefImpactBaseMetricV3 `json:"baseMetricV3,omitempty"` 219 | } 220 | 221 | // NVDCVEFeedJSON10DefCVEItem was auto-generated. 222 | // Defines a vulnerability in the NVD data feed. 223 | type NVDCVEFeedJSON10DefCVEItem struct { 224 | CVE CVEJSON40 `json:"cve"` 225 | Configurations NVDCVEFeedJSON10DefConfigurations `json:"configurations,omitempty"` 226 | Impact NVDCVEFeedJSON10DefImpact `json:"impact,omitempty"` 227 | LastModifiedDate string `json:"lastModifiedDate,omitempty"` 228 | PublishedDate string `json:"publishedDate,omitempty"` 229 | } 230 | 231 | // NVDCVEFeedJSON10 was auto-generated. 232 | // Source: testdata/nvd/nvd_cve_feed_json_1.0.schema 233 | type NVDCVEFeedJSON10 struct { 234 | CVEDataFormat string `json:"CVE_data_format"` 235 | CVEDataNumberOfCVEs string `json:"CVE_data_numberOfCVEs,omitempty"` 236 | CVEDataTimestamp string `json:"CVE_data_timestamp,omitempty"` 237 | CVEDataType string `json:"CVE_data_type"` 238 | CVEDataVersion string `json:"CVE_data_version"` 239 | CVEItems []NVDCVEFeedJSON10DefCVEItem `json:"CVE_Items"` 240 | } 241 | 242 | -------------------------------------------------------------------------------- /testdata/nvd/CVE_JSON_4.0_min.schema: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "copyright": "Copyright (c) 2017, Forum of Incident Response and Security Teams, Inc. All rights reserved.", 4 | 5 | "definitions": { 6 | "cve_id": { 7 | "type": "string", 8 | "pattern": "^CVE-[0-9]{4}-[0-9]{4,}$" 9 | }, 10 | "email_address": { 11 | "type": "string", 12 | "pattern": "^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$" 13 | }, 14 | "state_id": { 15 | "type": "string" 16 | }, 17 | "product": { 18 | "type": "object", 19 | "required": [ "product_name", "version" ], 20 | "properties": { 21 | "product_name": { "type": "string" }, 22 | "version": { 23 | "type": "object", 24 | "required": [ "version_data" ], 25 | "properties": { 26 | "version_data": { 27 | "type": "array", 28 | "minItems": 1, 29 | "items": { 30 | "type": "object", 31 | "required": [ "version_value" ], 32 | "properties": { 33 | "version_value": { "type": "string" }, 34 | "version_affected": { "type": "string" } 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | }, 42 | "reference": { 43 | "type": "object", 44 | "required": [ "url" ], 45 | "properties": { 46 | "url": { 47 | "maxLength": 500, 48 | "type": "string", 49 | "pattern": "^(ftp|http)s?://\\S+$" 50 | }, 51 | "name": {"type": "string"}, 52 | "refsource": {"type": "string"}, 53 | "tags":{ 54 | "type": "array", 55 | "items": { 56 | "type": "string" 57 | } 58 | } 59 | } 60 | }, 61 | "lang_string": { 62 | "type": "object", 63 | "required": [ "lang", "value" ], 64 | "properties": { 65 | "lang": { "type": "string" }, 66 | "value": { "type": "string", "maxLength": 3999 } 67 | } 68 | } 69 | }, 70 | 71 | "type": "object", 72 | "required": [ "data_type", "data_format", "data_version", "CVE_data_meta", "affects", "problemtype", "references", "description" ], 73 | "properties": { 74 | "data_type": { "enum": [ "CVE" ] }, 75 | "data_format": { "enum": [ "MITRE" ] }, 76 | "data_version": { "enum": [ "4.0" ] }, 77 | "CVE_data_meta": { 78 | "type":"object", 79 | "required": [ "ID", "ASSIGNER" ], 80 | "properties": { 81 | "ID": { "$ref": "#/definitions/cve_id" }, 82 | "ASSIGNER": { "$ref": "#/definitions/email_address" }, 83 | "STATE": { "$ref": "#/definitions/state_id" } 84 | } 85 | }, 86 | "affects": { 87 | "type": "object", 88 | "required": [ "vendor" ], 89 | "properties": { 90 | "vendor": { 91 | "type": "object", 92 | "required": [ "vendor_data" ], 93 | "properties": { 94 | "vendor_data": { 95 | "type": "array", 96 | "minItems": 1, 97 | "items": { 98 | "type": "object", 99 | "required": [ "vendor_name", "product" ], 100 | "properties": { 101 | "vendor_name": { "type": "string" }, 102 | "product": { 103 | "type": "object", 104 | "required": [ "product_data" ], 105 | "properties": { 106 | "product_data": { 107 | "type": "array", 108 | "minItems": 1, 109 | "items": { "$ref": "#/definitions/product" } 110 | } 111 | } 112 | } 113 | } 114 | } 115 | } 116 | } 117 | } 118 | } 119 | }, 120 | "problemtype": { 121 | "type": "object", 122 | "required": [ "problemtype_data" ], 123 | "properties": { 124 | "problemtype_data": { 125 | "type": "array", 126 | "minItems": 1, 127 | "items": { 128 | "type": "object", 129 | "required": [ "description" ], 130 | "properties": { 131 | "description": { 132 | "type": "array", 133 | "minItems": 1, 134 | "items": { "$ref": "#/definitions/lang_string" } 135 | } 136 | } 137 | } 138 | } 139 | } 140 | }, 141 | "references": { 142 | "type": "object", 143 | "required": [ "reference_data" ], 144 | "properties": { 145 | "reference_data": { 146 | "type": "array", 147 | "maxItems": 500, 148 | "minItems": 1, 149 | "items": { "$ref": "#/definitions/reference" } 150 | } 151 | } 152 | }, 153 | "description": { 154 | "type": "object", 155 | "required": [ "description_data" ], 156 | "properties": { 157 | "description_data": { 158 | "type": "array", 159 | "minItems": 1, 160 | "items": { "$ref": "#/definitions/lang_string" } 161 | } 162 | } 163 | } 164 | } 165 | } 166 | 167 | -------------------------------------------------------------------------------- /testdata/nvd/cvss-v2.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "JSON Schema for Common Vulnerability Scoring System version 2.0", 4 | "copyright": "Copyright (c) 2017, Forum of Incident Response and Security Teams, Inc. All rights reserved.", 5 | "id": "https://www.first.org/cvss/cvss-v2.0.json?20170531", 6 | "type": "object", 7 | "definitions": { 8 | "accessVectorType": { 9 | "type": "string", 10 | "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL" ] 11 | }, 12 | "accessComplexityType": { 13 | "type": "string", 14 | "enum": [ "HIGH", "MEDIUM", "LOW" ] 15 | }, 16 | "authenticationType": { 17 | "type": "string", 18 | "enum": [ "MULTIPLE", "SINGLE", "NONE" ] 19 | }, 20 | "ciaType": { 21 | "type": "string", 22 | "enum": [ "NONE", "PARTIAL", "COMPLETE" ] 23 | }, 24 | "exploitabilityType": { 25 | "type": "string", 26 | "enum": [ "UNPROVEN", "PROOF_OF_CONCEPT", "FUNCTIONAL", "HIGH", "NOT_DEFINED" ] 27 | }, 28 | "remediationLevelType": { 29 | "type": "string", 30 | "enum": [ "OFFICIAL_FIX", "TEMPORARY_FIX", "WORKAROUND", "UNAVAILABLE", "NOT_DEFINED" ] 31 | }, 32 | "reportConfidenceType": { 33 | "type": "string", 34 | "enum": [ "UNCONFIRMED", "UNCORROBORATED", "CONFIRMED", "NOT_DEFINED" ] 35 | }, 36 | "collateralDamagePotentialType": { 37 | "type": "string", 38 | "enum": [ "NONE", "LOW", "LOW_MEDIUM", "MEDIUM_HIGH", "HIGH", "NOT_DEFINED" ] 39 | }, 40 | "targetDistributionType": { 41 | "type": "string", 42 | "enum": [ "NONE", "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] 43 | }, 44 | "ciaRequirementType": { 45 | "type": "string", 46 | "enum": [ "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] 47 | }, 48 | "scoreType": { 49 | "type": "number", 50 | "minimum": 0, 51 | "maximum": 10 52 | } 53 | }, 54 | "properties": { 55 | "version": { 56 | "description": "CVSS Version", 57 | "type": "string", 58 | "enum": [ "2.0" ] 59 | }, 60 | "vectorString": { 61 | "type": "string", 62 | "pattern": "^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$" 63 | }, 64 | "accessVector": { "$ref": "#/definitions/accessVectorType" }, 65 | "accessComplexity": { "$ref": "#/definitions/accessComplexityType" }, 66 | "authentication": { "$ref": "#/definitions/authenticationType" }, 67 | "confidentialityImpact": { "$ref": "#/definitions/ciaType" }, 68 | "integrityImpact": { "$ref": "#/definitions/ciaType" }, 69 | "availabilityImpact": { "$ref": "#/definitions/ciaType" }, 70 | "baseScore": { "$ref": "#/definitions/scoreType" }, 71 | "exploitability": { "$ref": "#/definitions/exploitabilityType" }, 72 | "remediationLevel": { "$ref": "#/definitions/remediationLevelType" }, 73 | "reportConfidence": { "$ref": "#/definitions/reportConfidenceType" }, 74 | "temporalScore": { "$ref": "#/definitions/scoreType" }, 75 | "collateralDamagePotential": { "$ref": "#/definitions/collateralDamagePotentialType" }, 76 | "targetDistribution": { "$ref": "#/definitions/targetDistributionType" }, 77 | "confidentialityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 78 | "integrityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 79 | "availabilityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 80 | "environmentalScore": { "$ref": "#/definitions/scoreType" } 81 | }, 82 | "required": [ "version", "vectorString", "baseScore" ] 83 | } 84 | -------------------------------------------------------------------------------- /testdata/nvd/cvss-v3.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": [ 3 | "Copyright (c) 2017, FIRST.ORG, INC.", 4 | "All rights reserved.", 5 | "", 6 | "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the ", 7 | "following conditions are met:", 8 | "1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following ", 9 | " disclaimer.", 10 | "2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the ", 11 | " following disclaimer in the documentation and/or other materials provided with the distribution.", 12 | "3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote ", 13 | " products derived from this software without specific prior written permission.", 14 | "", 15 | "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, ", 16 | "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ", 17 | "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ", 18 | "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ", 19 | "SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ", 20 | "WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ", 21 | "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 22 | ], 23 | 24 | "$schema": "http://json-schema.org/draft-04/schema#", 25 | "title": "JSON Schema for Common Vulnerability Scoring System version 3.0", 26 | "id": "https://www.first.org/cvss/cvss-v3.0.json?20170531", 27 | "type": "object", 28 | "definitions": { 29 | "attackVectorType": { 30 | "type": "string", 31 | "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL", "PHYSICAL" ] 32 | }, 33 | "modifiedAttackVectorType": { 34 | "type": "string", 35 | "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL", "PHYSICAL", "NOT_DEFINED" ] 36 | }, 37 | "attackComplexityType": { 38 | "type": "string", 39 | "enum": [ "HIGH", "LOW" ] 40 | }, 41 | "modifiedAttackComplexityType": { 42 | "type": "string", 43 | "enum": [ "HIGH", "LOW", "NOT_DEFINED" ] 44 | }, 45 | "privilegesRequiredType": { 46 | "type": "string", 47 | "enum": [ "HIGH", "LOW", "NONE" ] 48 | }, 49 | "modifiedPrivilegesRequiredType": { 50 | "type": "string", 51 | "enum": [ "HIGH", "LOW", "NONE", "NOT_DEFINED" ] 52 | }, 53 | "userInteractionType": { 54 | "type": "string", 55 | "enum": [ "NONE", "REQUIRED" ] 56 | }, 57 | "modifiedUserInteractionType": { 58 | "type": "string", 59 | "enum": [ "NONE", "REQUIRED", "NOT_DEFINED" ] 60 | }, 61 | "scopeType": { 62 | "type": "string", 63 | "enum": [ "UNCHANGED", "CHANGED" ] 64 | }, 65 | "modifiedScopeType": { 66 | "type": "string", 67 | "enum": [ "UNCHANGED", "CHANGED", "NOT_DEFINED" ] 68 | }, 69 | "ciaType": { 70 | "type": "string", 71 | "enum": [ "NONE", "LOW", "HIGH" ] 72 | }, 73 | "modifiedCiaType": { 74 | "type": "string", 75 | "enum": [ "NONE", "LOW", "HIGH", "NOT_DEFINED" ] 76 | }, 77 | "exploitCodeMaturityType": { 78 | "type": "string", 79 | "enum": [ "UNPROVEN", "PROOF_OF_CONCEPT", "FUNCTIONAL", "HIGH", "NOT_DEFINED" ] 80 | }, 81 | "remediationLevelType": { 82 | "type": "string", 83 | "enum": [ "OFFICIAL_FIX", "TEMPORARY_FIX", "WORKAROUND", "UNAVAILABLE", "NOT_DEFINED" ] 84 | }, 85 | "confidenceType": { 86 | "type": "string", 87 | "enum": [ "UNKNOWN", "REASONABLE", "CONFIRMED", "NOT_DEFINED" ] 88 | }, 89 | "ciaRequirementType": { 90 | "type": "string", 91 | "enum": [ "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] 92 | }, 93 | "scoreType": { 94 | "type": "number", 95 | "minimum": 0, 96 | "maximum": 10 97 | }, 98 | "severityType": { 99 | "type": "string", 100 | "enum": [ "NONE", "LOW", "MEDIUM", "HIGH", "CRITICAL" ] 101 | } 102 | }, 103 | "properties": { 104 | "version": { 105 | "description": "CVSS Version", 106 | "type": "string", 107 | "enum": [ "3.0" ] 108 | }, 109 | "vectorString": { 110 | "type": "string", 111 | "pattern": "^CVSS:3.0/((AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$" 112 | }, 113 | "attackVector": { "$ref": "#/definitions/attackVectorType" }, 114 | "attackComplexity": { "$ref": "#/definitions/attackComplexityType" }, 115 | "privilegesRequired": { "$ref": "#/definitions/privilegesRequiredType" }, 116 | "userInteraction": { "$ref": "#/definitions/userInteractionType" }, 117 | "scope": { "$ref": "#/definitions/scopeType" }, 118 | "confidentialityImpact": { "$ref": "#/definitions/ciaType" }, 119 | "integrityImpact": { "$ref": "#/definitions/ciaType" }, 120 | "availabilityImpact": { "$ref": "#/definitions/ciaType" }, 121 | "baseScore": { "$ref": "#/definitions/scoreType" }, 122 | "baseSeverity": { "$ref": "#/definitions/severityType" }, 123 | "exploitCodeMaturity": { "$ref": "#/definitions/exploitCodeMaturityType" }, 124 | "remediationLevel": { "$ref": "#/definitions/remediationLevelType" }, 125 | "reportConfidence": { "$ref": "#/definitions/confidenceType" }, 126 | "temporalScore": { "$ref": "#/definitions/scoreType" }, 127 | "temporalSeverity": { "$ref": "#/definitions/severityType" }, 128 | "confidentialityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 129 | "integrityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 130 | "availabilityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 131 | "modifiedAttackVector": { "$ref": "#/definitions/modifiedAttackVectorType" }, 132 | "modifiedAttackComplexity": { "$ref": "#/definitions/modifiedAttackComplexityType" }, 133 | "modifiedPrivilegesRequired": { "$ref": "#/definitions/modifiedPrivilegesRequiredType" }, 134 | "modifiedUserInteraction": { "$ref": "#/definitions/modifiedUserInteractionType" }, 135 | "modifiedScope": { "$ref": "#/definitions/modifiedScopeType" }, 136 | "modifiedConfidentialityImpact": { "$ref": "#/definitions/modifiedCiaType" }, 137 | "modifiedIntegrityImpact": { "$ref": "#/definitions/modifiedCiaType" }, 138 | "modifiedAvailabilityImpact": { "$ref": "#/definitions/modifiedCiaType" }, 139 | "environmentalScore": { "$ref": "#/definitions/scoreType" }, 140 | "environmentalSeverity": { "$ref": "#/definitions/severityType" } 141 | }, 142 | "required": [ "version", "vectorString", "baseScore", "baseSeverity" ] 143 | } -------------------------------------------------------------------------------- /testdata/nvd/nvd_cve_feed_json_1.0.schema: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "JSON Schema for NVD Vulnerability Data Feed version 1.0", 4 | "id": "https://scap.nist.gov/schema/nvd/feed/1.0/nvd_cve_feed_json_1.0.schema", 5 | "definitions": { 6 | "def_cpe_name": { 7 | "description": "CPE name", 8 | "type": "object", 9 | "properties": { 10 | "cpe22Uri": { 11 | "type": "string" 12 | }, 13 | "cpe23Uri": { 14 | "type": "string" 15 | } 16 | }, 17 | "required": [ 18 | "cpe23Uri" 19 | ] 20 | }, 21 | "def_cpe_match": { 22 | "description": "CPE match string or range", 23 | "type": "object", 24 | "properties": { 25 | "vulnerable": { 26 | "type": "boolean" 27 | }, 28 | "cpe22Uri": { 29 | "type": "string" 30 | }, 31 | "cpe23Uri": { 32 | "type": "string" 33 | }, 34 | "versionStartExcluding": { 35 | "type": "string" 36 | }, 37 | "versionStartIncluding": { 38 | "type": "string" 39 | }, 40 | "versionEndExcluding": { 41 | "type": "string" 42 | }, 43 | "versionEndIncluding": { 44 | "type": "string" 45 | }, 46 | "cpe_name": { 47 | "type": "array", 48 | "items": { 49 | "$ref": "#/definitions/def_cpe_name" 50 | } 51 | } 52 | }, 53 | "required": [ 54 | "vulnerable", 55 | "cpe23Uri" 56 | ] 57 | }, 58 | "def_node": { 59 | "description": "Defines a node or sub-node in an NVD applicability statement.", 60 | "properties": { 61 | "operator": {"type": "string"}, 62 | "negate": {"type": "boolean"}, 63 | "children": { 64 | "type": "array", 65 | "items": {"$ref": "#/definitions/def_node"} 66 | }, 67 | "cpe_match": { 68 | "type": "array", 69 | "items": {"$ref": "#/definitions/def_cpe_match"} 70 | } 71 | } 72 | }, 73 | "def_configurations": { 74 | "description": "Defines the set of product configurations for a NVD applicability statement.", 75 | "properties": { 76 | "CVE_data_version": {"type": "string"}, 77 | "nodes": { 78 | "type": "array", 79 | "items": {"$ref": "#/definitions/def_node"} 80 | } 81 | }, 82 | "required": [ 83 | "CVE_data_version" 84 | ] 85 | }, 86 | "def_subscore": { 87 | "description": "CVSS subscore.", 88 | "type": "number", 89 | "minimum": 0, 90 | "maximum": 10 91 | }, 92 | "def_impact": { 93 | "description": "Impact scores for a vulnerability as found on NVD.", 94 | "type": "object", 95 | "properties": { 96 | "baseMetricV3": { 97 | "description": "CVSS V3.0 score.", 98 | "type": "object", 99 | "properties": { 100 | "cvssV3": {"$ref": "cvss-v3.0.json"}, 101 | "exploitabilityScore": {"$ref": "#/definitions/def_subscore"}, 102 | "impactScore": {"$ref": "#/definitions/def_subscore"} 103 | } 104 | }, 105 | "baseMetricV2": { 106 | "description": "CVSS V2.0 score.", 107 | "type": "object", 108 | "properties": { 109 | "cvssV2": {"$ref": "cvss-v2.0.json"}, 110 | "severity": {"type": "string"}, 111 | "exploitabilityScore": {"$ref": "#/definitions/def_subscore"}, 112 | "impactScore": {"$ref": "#/definitions/def_subscore"}, 113 | "acInsufInfo": {"type": "boolean"}, 114 | "obtainAllPrivilege": {"type": "boolean"}, 115 | "obtainUserPrivilege": {"type": "boolean"}, 116 | "obtainOtherPrivilege": {"type": "boolean"}, 117 | "userInteractionRequired": {"type": "boolean"} 118 | } 119 | } 120 | } 121 | }, 122 | "def_cve_item": { 123 | "description": "Defines a vulnerability in the NVD data feed.", 124 | "properties": { 125 | "cve": {"$ref": "CVE_JSON_4.0_min.schema"}, 126 | "configurations": {"$ref": "#/definitions/def_configurations"}, 127 | "impact": {"$ref": "#/definitions/def_impact"}, 128 | "publishedDate": {"type": "string"}, 129 | "lastModifiedDate": {"type": "string"} 130 | }, 131 | "required": ["cve"] 132 | } 133 | }, 134 | "type": "object", 135 | "properties": { 136 | "CVE_data_type": {"type": "string"}, 137 | "CVE_data_format": {"type": "string"}, 138 | "CVE_data_version": {"type": "string"}, 139 | "CVE_data_numberOfCVEs": { 140 | "description": "NVD adds number of CVE in this feed", 141 | "type": "string" 142 | }, 143 | "CVE_data_timestamp": { 144 | "description": "NVD adds feed date timestamp", 145 | "type": "string" 146 | }, 147 | "CVE_Items": { 148 | "description": "NVD feed array of CVE", 149 | "type": "array", 150 | "items": {"$ref": "#/definitions/def_cve_item"} 151 | } 152 | }, 153 | "required": [ 154 | "CVE_data_type", 155 | "CVE_data_format", 156 | "CVE_data_version", 157 | "CVE_Items" 158 | ] 159 | } -------------------------------------------------------------------------------- /testdata/thrift.golden: -------------------------------------------------------------------------------- 1 | // This thrift spec was auto-generated. 2 | // Command: ./jsonschema2go -gen thrift testdata/nvd/nvd_cve_feed_json_1.0.schema 3 | 4 | namespace go schema 5 | namespace py schema 6 | 7 | // NVDCVEFeedJSON10DefCPEName was auto-generated. 8 | // CPE name. 9 | struct NVDCVEFeedJSON10DefCPEName { 10 | 1: optional string cpe22Uri; 11 | 2: required string cpe23Uri; 12 | } 13 | 14 | // NVDCVEFeedJSON10DefCPEMatch was auto-generated. 15 | // CPE match string or range. 16 | struct NVDCVEFeedJSON10DefCPEMatch { 17 | 1: optional string cpe22Uri; 18 | 2: required string cpe23Uri; 19 | 3: optional list cpe_name; 20 | 4: optional string versionEndExcluding; 21 | 5: optional string versionEndIncluding; 22 | 6: optional string versionStartExcluding; 23 | 7: optional string versionStartIncluding; 24 | 8: required bool vulnerable; 25 | } 26 | 27 | // NVDCVEFeedJSON10DefNode was auto-generated. 28 | // Defines a node or sub-node in an NVD applicability statement. 29 | struct NVDCVEFeedJSON10DefNode { 30 | 1: optional list children; 31 | 2: optional list cpe_match; 32 | 3: optional bool negate; 33 | 4: optional string operator; 34 | } 35 | 36 | // NVDCVEFeedJSON10DefConfigurations was auto-generated. 37 | // Defines the set of product configurations for a NVD applicability statement. 38 | struct NVDCVEFeedJSON10DefConfigurations { 39 | 1: required string CVE_data_version; 40 | 2: optional list nodes; 41 | } 42 | 43 | // CVEJSON40CVEDataMeta was auto-generated. 44 | struct CVEJSON40CVEDataMeta { 45 | 1: required string ASSIGNER; 46 | 2: required string ID; 47 | 3: optional string STATE; 48 | } 49 | 50 | // CVEJSON40ProductVersionVersionData was auto-generated. 51 | struct CVEJSON40ProductVersionVersionData { 52 | 1: optional string version_affected; 53 | 2: required string version_value; 54 | } 55 | 56 | // CVEJSON40ProductVersion was auto-generated. 57 | struct CVEJSON40ProductVersion { 58 | 1: required list version_data; 59 | } 60 | 61 | // CVEJSON40Product was auto-generated. 62 | struct CVEJSON40Product { 63 | 1: required string product_name; 64 | 2: required CVEJSON40ProductVersion version; 65 | } 66 | 67 | // CVEJSON40AffectsVendorVendorDataProduct was auto-generated. 68 | struct CVEJSON40AffectsVendorVendorDataProduct { 69 | 1: required list product_data; 70 | } 71 | 72 | // CVEJSON40AffectsVendorVendorData was auto-generated. 73 | struct CVEJSON40AffectsVendorVendorData { 74 | 1: required CVEJSON40AffectsVendorVendorDataProduct product; 75 | 2: required string vendor_name; 76 | } 77 | 78 | // CVEJSON40AffectsVendor was auto-generated. 79 | struct CVEJSON40AffectsVendor { 80 | 1: required list vendor_data; 81 | } 82 | 83 | // CVEJSON40Affects was auto-generated. 84 | struct CVEJSON40Affects { 85 | 1: required CVEJSON40AffectsVendor vendor; 86 | } 87 | 88 | // CVEJSON40LangString was auto-generated. 89 | struct CVEJSON40LangString { 90 | 1: required string lang; 91 | 2: required string value; 92 | } 93 | 94 | // CVEJSON40Description was auto-generated. 95 | struct CVEJSON40Description { 96 | 1: required list description_data; 97 | } 98 | 99 | // CVEJSON40ProblemtypeProblemtypeData was auto-generated. 100 | struct CVEJSON40ProblemtypeProblemtypeData { 101 | 1: required list description; 102 | } 103 | 104 | // CVEJSON40Problemtype was auto-generated. 105 | struct CVEJSON40Problemtype { 106 | 1: required list problemtype_data; 107 | } 108 | 109 | // CVEJSON40Reference was auto-generated. 110 | struct CVEJSON40Reference { 111 | 1: optional string name; 112 | 2: optional string refsource; 113 | 3: optional list tags; 114 | 4: required string url; 115 | } 116 | 117 | // CVEJSON40References was auto-generated. 118 | struct CVEJSON40References { 119 | 1: required list reference_data; 120 | } 121 | 122 | // CVEJSON40 was auto-generated. 123 | // Source: testdata/nvd/CVE_JSON_4.0_min.schema 124 | struct CVEJSON40 { 125 | 1: required CVEJSON40CVEDataMeta CVE_data_meta; 126 | 2: required CVEJSON40Affects affects; 127 | 3: required string data_format; 128 | 4: required string data_type; 129 | 5: required string data_version; 130 | 6: required CVEJSON40Description description; 131 | 7: required CVEJSON40Problemtype problemtype; 132 | 8: required CVEJSON40References references; 133 | } 134 | 135 | // CVSSV20 was auto-generated. 136 | // Source: testdata/nvd/cvss-v2.0.json 137 | struct CVSSV20 { 138 | 1: optional string accessComplexity; 139 | 2: optional string accessVector; 140 | 3: optional string authentication; 141 | 4: optional string availabilityImpact; 142 | 5: optional string availabilityRequirement; 143 | 6: required double baseScore; 144 | 7: optional string collateralDamagePotential; 145 | 8: optional string confidentialityImpact; 146 | 9: optional string confidentialityRequirement; 147 | 10: optional double environmentalScore; 148 | 11: optional string exploitability; 149 | 12: optional string integrityImpact; 150 | 13: optional string integrityRequirement; 151 | 14: optional string remediationLevel; 152 | 15: optional string reportConfidence; 153 | 16: optional string targetDistribution; 154 | 17: optional double temporalScore; 155 | 18: required string vectorString; 156 | 19: required string version; 157 | } 158 | 159 | // NVDCVEFeedJSON10DefImpactBaseMetricV2 was auto-generated. 160 | // CVSS V2.0 score. 161 | struct NVDCVEFeedJSON10DefImpactBaseMetricV2 { 162 | 1: optional bool acInsufInfo; 163 | 2: optional CVSSV20 cvssV2; 164 | 3: optional double exploitabilityScore; 165 | 4: optional double impactScore; 166 | 5: optional bool obtainAllPrivilege; 167 | 6: optional bool obtainOtherPrivilege; 168 | 7: optional bool obtainUserPrivilege; 169 | 8: optional string severity; 170 | 9: optional bool userInteractionRequired; 171 | } 172 | 173 | // CVSSV30 was auto-generated. 174 | // Source: testdata/nvd/cvss-v3.0.json 175 | struct CVSSV30 { 176 | 1: optional string attackComplexity; 177 | 2: optional string attackVector; 178 | 3: optional string availabilityImpact; 179 | 4: optional string availabilityRequirement; 180 | 5: required double baseScore; 181 | 6: required string baseSeverity; 182 | 7: optional string confidentialityImpact; 183 | 8: optional string confidentialityRequirement; 184 | 9: optional double environmentalScore; 185 | 10: optional string environmentalSeverity; 186 | 11: optional string exploitCodeMaturity; 187 | 12: optional string integrityImpact; 188 | 13: optional string integrityRequirement; 189 | 14: optional string modifiedAttackComplexity; 190 | 15: optional string modifiedAttackVector; 191 | 16: optional string modifiedAvailabilityImpact; 192 | 17: optional string modifiedConfidentialityImpact; 193 | 18: optional string modifiedIntegrityImpact; 194 | 19: optional string modifiedPrivilegesRequired; 195 | 20: optional string modifiedScope; 196 | 21: optional string modifiedUserInteraction; 197 | 22: optional string privilegesRequired; 198 | 23: optional string remediationLevel; 199 | 24: optional string reportConfidence; 200 | 25: optional string scope; 201 | 26: optional double temporalScore; 202 | 27: optional string temporalSeverity; 203 | 28: optional string userInteraction; 204 | 29: required string vectorString; 205 | 30: required string version; 206 | } 207 | 208 | // NVDCVEFeedJSON10DefImpactBaseMetricV3 was auto-generated. 209 | // CVSS V3.0 score. 210 | struct NVDCVEFeedJSON10DefImpactBaseMetricV3 { 211 | 1: optional CVSSV30 cvssV3; 212 | 2: optional double exploitabilityScore; 213 | 3: optional double impactScore; 214 | } 215 | 216 | // NVDCVEFeedJSON10DefImpact was auto-generated. 217 | // Impact scores for a vulnerability as found on NVD. 218 | struct NVDCVEFeedJSON10DefImpact { 219 | 1: optional NVDCVEFeedJSON10DefImpactBaseMetricV2 baseMetricV2; 220 | 2: optional NVDCVEFeedJSON10DefImpactBaseMetricV3 baseMetricV3; 221 | } 222 | 223 | // NVDCVEFeedJSON10DefCVEItem was auto-generated. 224 | // Defines a vulnerability in the NVD data feed. 225 | struct NVDCVEFeedJSON10DefCVEItem { 226 | 1: optional NVDCVEFeedJSON10DefConfigurations configurations; 227 | 2: required CVEJSON40 cve; 228 | 3: optional NVDCVEFeedJSON10DefImpact impact; 229 | 4: optional string lastModifiedDate; 230 | 5: optional string publishedDate; 231 | } 232 | 233 | // NVDCVEFeedJSON10 was auto-generated. 234 | // Source: testdata/nvd/nvd_cve_feed_json_1.0.schema 235 | struct NVDCVEFeedJSON10 { 236 | 1: required list CVE_Items; 237 | 2: required string CVE_data_format; 238 | 3: optional string CVE_data_numberOfCVEs; 239 | 4: optional string CVE_data_timestamp; 240 | 5: required string CVE_data_type; 241 | 6: required string CVE_data_version; 242 | } 243 | 244 | --------------------------------------------------------------------------------