Skip to content

Commit c69f9f8

Browse files
committed
(go-sdk): pathc swagger to correctly generate types
1 parent 94a8e7a commit c69f9f8

3 files changed

Lines changed: 143 additions & 2 deletions

File tree

.github/workflows/go-release.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,19 @@ jobs:
103103
with:
104104
go-version: ${{ matrix.go-version }}
105105

106+
- name: Patch OpenAPI spec for Go codegen
107+
run: |
108+
cd openmetadata-sdk/openmetadata-go-client && go run scripts/patch_swagger.go \
109+
${{ github.workspace }}/open-metadata/openmetadata-service/target/classes/assets/swagger.json \
110+
/tmp/swagger_patched.json
111+
106112
- name: Generate Go models from OpenAPI spec
107113
run: |
108114
cd openmetadata-sdk/openmetadata-go-client && go tool oapi-codegen \
109115
-generate types \
110116
-package ometa \
111117
-o pkg/ometa/models.go \
112-
${{ github.workspace }}/open-metadata/openmetadata-service/target/classes/assets/swagger.json
118+
/tmp/swagger_patched.json
113119
114120
- name: Run golangci-lint
115121
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0

.github/workflows/go-tests.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,19 @@ jobs:
8989
uses: actions/setup-go@v4
9090
with:
9191
go-version: ${{ matrix.go-version }}
92+
- name: Patch OpenAPI spec for Go codegen
93+
run: |
94+
cd openmetadata-sdk/openmetadata-go-client && go run scripts/patch_swagger.go \
95+
${{ github.workspace }}/open-metadata/openmetadata-service/target/classes/assets/swagger.json \
96+
/tmp/swagger_patched.json
97+
9298
- name: Generate models from OpenAPI spec
9399
run: |
94100
cd openmetadata-sdk/openmetadata-go-client && go tool oapi-codegen \
95101
-generate types \
96102
-package ometa \
97103
-o pkg/ometa/models.go \
98-
${{ github.workspace }}/open-metadata/openmetadata-service/target/classes/assets/swagger.json
104+
/tmp/swagger_patched.json
99105
- name: Validate service coverage against swagger
100106
run: |
101107
cd openmetadata-sdk/openmetadata-go-client && go test ./pkg/ometa/ \
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// patch_swagger.go patches the OpenMetadata swagger.json before Go code generation.
2+
//
3+
// oapi-codegen maps {"type": "object"} (bare object with no properties) to
4+
// map[string]interface{}, but the OpenMetadata API returns arbitrary JSON
5+
// values (strings, bools, arrays, numbers) for many of these fields.
6+
//
7+
// This script removes the "type": "object" constraint from such fields so
8+
// oapi-codegen generates interface{} (any) instead, which correctly accepts
9+
// all JSON value types.
10+
//
11+
// Usage:
12+
//
13+
// go run scripts/patch_swagger.go <input.json> <output.json>
14+
package main
15+
16+
import (
17+
"encoding/json"
18+
"fmt"
19+
"os"
20+
)
21+
22+
func main() {
23+
if len(os.Args) != 3 {
24+
fmt.Fprintf(os.Stderr, "Usage: %s <input.json> <output.json>\n", os.Args[0])
25+
os.Exit(1)
26+
}
27+
28+
inputPath, outputPath := os.Args[1], os.Args[2]
29+
30+
data, err := os.ReadFile(inputPath)
31+
if err != nil {
32+
fmt.Fprintf(os.Stderr, "failed to read %s: %v\n", inputPath, err)
33+
os.Exit(1)
34+
}
35+
36+
var spec map[string]interface{}
37+
if err := json.Unmarshal(data, &spec); err != nil {
38+
fmt.Fprintf(os.Stderr, "failed to parse JSON: %v\n", err)
39+
os.Exit(1)
40+
}
41+
42+
schemas := findSchemas(spec)
43+
if schemas == nil {
44+
fmt.Fprintln(os.Stderr, "no definitions or components/schemas found in spec")
45+
os.Exit(1)
46+
}
47+
48+
count := patchBareObjects(schemas)
49+
fmt.Printf("Patched %d bare-object fields in swagger spec\n", count)
50+
51+
out, err := json.MarshalIndent(spec, "", " ")
52+
if err != nil {
53+
fmt.Fprintf(os.Stderr, "failed to marshal JSON: %v\n", err)
54+
os.Exit(1)
55+
}
56+
57+
if err := os.WriteFile(outputPath, out, 0644); err != nil {
58+
fmt.Fprintf(os.Stderr, "failed to write %s: %v\n", outputPath, err)
59+
os.Exit(1)
60+
}
61+
}
62+
63+
// findSchemas returns the schema definitions map from either
64+
// OpenAPI 2.x ("definitions") or 3.x ("components.schemas").
65+
func findSchemas(spec map[string]interface{}) map[string]interface{} {
66+
if defs, ok := spec["definitions"].(map[string]interface{}); ok {
67+
return defs
68+
}
69+
if components, ok := spec["components"].(map[string]interface{}); ok {
70+
if schemas, ok := components["schemas"].(map[string]interface{}); ok {
71+
return schemas
72+
}
73+
}
74+
return nil
75+
}
76+
77+
// isBareObject returns true if the value is {"type": "object"} with no other keys.
78+
func isBareObject(v interface{}) bool {
79+
m, ok := v.(map[string]interface{})
80+
if !ok || len(m) != 1 {
81+
return false
82+
}
83+
t, ok := m["type"].(string)
84+
return ok && t == "object"
85+
}
86+
87+
// patchBareObjects removes "type": "object" from properties that are bare objects
88+
// (no "properties", "$ref", "additionalProperties", etc.). These represent free-form
89+
// values in the OpenMetadata API.
90+
//
91+
// For array properties whose items are bare objects, the items are patched the same way.
92+
func patchBareObjects(schemas map[string]interface{}) int {
93+
count := 0
94+
95+
for _, schemaDef := range schemas {
96+
schemaMap, ok := schemaDef.(map[string]interface{})
97+
if !ok {
98+
continue
99+
}
100+
properties, ok := schemaMap["properties"].(map[string]interface{})
101+
if !ok {
102+
continue
103+
}
104+
105+
for propName, propValue := range properties {
106+
propMap, ok := propValue.(map[string]interface{})
107+
if !ok {
108+
continue
109+
}
110+
111+
// Case 1: property is exactly {"type": "object"}
112+
if isBareObject(propValue) {
113+
properties[propName] = map[string]interface{}{}
114+
count++
115+
continue
116+
}
117+
118+
// Case 2: property is {"type": "array", "items": {"type": "object"}}
119+
if t, _ := propMap["type"].(string); t == "array" {
120+
if isBareObject(propMap["items"]) {
121+
propMap["items"] = map[string]interface{}{}
122+
count++
123+
}
124+
}
125+
}
126+
}
127+
128+
return count
129+
}

0 commit comments

Comments
 (0)