Skip to content

Commit 6d0f4a6

Browse files
dylanhittEwenQuim
authored andcommitted
feat: add option to pretty print json doc output
1 parent 5564264 commit 6d0f4a6

File tree

4 files changed

+117
-8
lines changed

4 files changed

+117
-8
lines changed

openapi.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func (s *Server) OutputOpenAPISpec() openapi3.T {
5959
}
6060

6161
// Marshal spec to JSON
62-
jsonSpec, err := json.Marshal(s.OpenApiSpec)
62+
jsonSpec, err := s.marshalSpec()
6363
if err != nil {
6464
slog.Error("Error marshalling spec to JSON", "error", err)
6565
}
@@ -78,6 +78,13 @@ func (s *Server) OutputOpenAPISpec() openapi3.T {
7878
return s.OpenApiSpec
7979
}
8080

81+
func (s *Server) marshalSpec() ([]byte, error) {
82+
if s.OpenAPIConfig.PrettyFormatJson {
83+
return json.MarshalIndent(s.OpenApiSpec, "", " ")
84+
}
85+
return json.Marshal(s.OpenApiSpec)
86+
}
87+
8188
func saveOpenAPIToFile(jsonSpecLocalPath string, jsonSpec []byte) error {
8289
jsonFolder := filepath.Dir(jsonSpecLocalPath)
8390

openapi_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package fuego
22

33
import (
4+
"bytes"
45
"fmt"
6+
"io"
57
"net/http/httptest"
68
"os"
79
"testing"
@@ -79,6 +81,106 @@ func TestServer_generateOpenAPI(t *testing.T) {
7981
})
8082
}
8183

84+
func TestServer_OutputOpenApiSpec(t *testing.T) {
85+
docPath := "doc/openapi.json"
86+
t.Run("base", func(t *testing.T) {
87+
s := NewServer(
88+
WithOpenAPIConfig(
89+
OpenAPIConfig{
90+
JsonFilePath: docPath,
91+
},
92+
),
93+
)
94+
Get(s, "/", func(*ContextNoBody) (MyStruct, error) {
95+
return MyStruct{}, nil
96+
})
97+
98+
document := s.OutputOpenAPISpec()
99+
require.NotNil(t, document)
100+
101+
file, err := os.Open(docPath)
102+
require.NoError(t, err)
103+
require.NotNil(t, file)
104+
defer os.Remove(file.Name())
105+
require.Equal(t, 1, lineCounter(t, file))
106+
})
107+
t.Run("do not print file", func(t *testing.T) {
108+
s := NewServer(
109+
WithOpenAPIConfig(
110+
OpenAPIConfig{
111+
JsonFilePath: docPath,
112+
DisableLocalSave: true,
113+
},
114+
),
115+
)
116+
Get(s, "/", func(*ContextNoBody) (MyStruct, error) {
117+
return MyStruct{}, nil
118+
})
119+
120+
document := s.OutputOpenAPISpec()
121+
require.NotNil(t, document)
122+
123+
file, err := os.Open(docPath)
124+
require.Error(t, err)
125+
require.Nil(t, file)
126+
})
127+
t.Run("swagger disabled", func(t *testing.T) {
128+
s := NewServer(
129+
WithOpenAPIConfig(
130+
OpenAPIConfig{
131+
JsonFilePath: docPath,
132+
DisableLocalSave: true,
133+
DisableSwagger: true,
134+
},
135+
),
136+
)
137+
Get(s, "/", func(*ContextNoBody) (MyStruct, error) {
138+
return MyStruct{}, nil
139+
})
140+
141+
document := s.OutputOpenAPISpec()
142+
require.Len(t, document.Paths.Map(), 1)
143+
require.NotNil(t, document)
144+
145+
file, err := os.Open(docPath)
146+
require.Error(t, err)
147+
require.Nil(t, file)
148+
})
149+
t.Run("pretty format json file", func(t *testing.T) {
150+
s := NewServer(
151+
WithOpenAPIConfig(
152+
OpenAPIConfig{
153+
JsonFilePath: docPath,
154+
PrettyFormatJson: true,
155+
},
156+
),
157+
)
158+
Get(s, "/", func(*ContextNoBody) (MyStruct, error) {
159+
return MyStruct{}, nil
160+
})
161+
162+
document := s.OutputOpenAPISpec()
163+
require.NotNil(t, document)
164+
165+
file, err := os.Open(docPath)
166+
require.NoError(t, err)
167+
require.NotNil(t, file)
168+
defer os.Remove(file.Name())
169+
require.Greater(t, lineCounter(t, file), 1)
170+
})
171+
}
172+
173+
func lineCounter(t *testing.T, r io.Reader) int {
174+
buf := make([]byte, 32*1024)
175+
count := 1
176+
lineSep := []byte{'\n'}
177+
178+
c, err := r.Read(buf)
179+
require.NoError(t, err)
180+
count += bytes.Count(buf[:c], lineSep)
181+
return count
182+
}
183+
82184
func BenchmarkRoutesRegistration(b *testing.B) {
83185
for range b.N {
84186
s := NewServer(

options.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type OpenAPIConfig struct {
2323
UIHandler func(specURL string) http.Handler // Handler to serve the openapi ui from spec url
2424
JsonUrl string // URL to serve the openapi json spec
2525
JsonFilePath string // Local path to save the openapi json spec
26+
PrettyFormatJson bool // Pretty prints the open api spec with proper json indentation
2627
}
2728

2829
var defaultOpenAPIConfig = OpenAPIConfig{
@@ -288,13 +289,9 @@ func WithOpenAPIConfig(openapiConfig OpenAPIConfig) func(*Server) {
288289
s.OpenAPIConfig.UIHandler = openapiConfig.UIHandler
289290
}
290291

291-
if openapiConfig.DisableSwagger {
292-
s.OpenAPIConfig.DisableSwagger = true
293-
}
294-
295-
if openapiConfig.DisableLocalSave {
296-
s.OpenAPIConfig.DisableLocalSave = true
297-
}
292+
s.OpenAPIConfig.DisableSwagger = openapiConfig.DisableSwagger
293+
s.OpenAPIConfig.DisableLocalSave = openapiConfig.DisableLocalSave
294+
s.OpenAPIConfig.PrettyFormatJson = openapiConfig.PrettyFormatJson
298295

299296
if !validateJsonSpecLocalPath(s.OpenAPIConfig.JsonFilePath) {
300297
slog.Error("Error writing json spec. Value of 'jsonSpecLocalPath' option is not valid", "file", s.OpenAPIConfig.JsonFilePath)

options_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ func TestWithOpenAPIConfig(t *testing.T) {
7575
require.Equal(t, "/swagger", s.OpenAPIConfig.SwaggerUrl)
7676
require.Equal(t, "/swagger/openapi.json", s.OpenAPIConfig.JsonUrl)
7777
require.Equal(t, "doc/openapi.json", s.OpenAPIConfig.JsonFilePath)
78+
require.False(t, s.OpenAPIConfig.PrettyFormatJson)
7879
})
7980

8081
t.Run("with custom values", func(t *testing.T) {
@@ -85,6 +86,7 @@ func TestWithOpenAPIConfig(t *testing.T) {
8586
JsonFilePath: "openapi.json",
8687
DisableSwagger: true,
8788
DisableLocalSave: true,
89+
PrettyFormatJson: true,
8890
}),
8991
)
9092

@@ -93,6 +95,7 @@ func TestWithOpenAPIConfig(t *testing.T) {
9395
require.Equal(t, "openapi.json", s.OpenAPIConfig.JsonFilePath)
9496
require.True(t, s.OpenAPIConfig.DisableSwagger)
9597
require.True(t, s.OpenAPIConfig.DisableLocalSave)
98+
require.True(t, s.OpenAPIConfig.PrettyFormatJson)
9699
})
97100

98101
t.Run("with invalid local path values", func(t *testing.T) {

0 commit comments

Comments
 (0)