@@ -17,7 +17,7 @@ func TestDefinition_MarshalJSON(t *testing.T) {
1717 {
1818 name : "Test with empty Definition" ,
1919 def : jsonschema.Definition {},
20- want : `{"properties":{} }` ,
20+ want : `{}` ,
2121 },
2222 {
2323 name : "Test with Definition properties set" ,
@@ -31,15 +31,14 @@ func TestDefinition_MarshalJSON(t *testing.T) {
3131 },
3232 },
3333 want : `{
34- "type":"string",
35- "description":"A string type",
36- "properties":{
37- "name":{
38- "type":"string",
39- "properties":{}
40- }
41- }
42- }` ,
34+ "type":"string",
35+ "description":"A string type",
36+ "properties":{
37+ "name":{
38+ "type":"string"
39+ }
40+ }
41+ }` ,
4342 },
4443 {
4544 name : "Test with nested Definition properties" ,
@@ -60,23 +59,21 @@ func TestDefinition_MarshalJSON(t *testing.T) {
6059 },
6160 },
6261 want : `{
63- "type":"object",
64- "properties":{
65- "user":{
66- "type":"object",
67- "properties":{
68- "name":{
69- "type":"string",
70- "properties":{}
71- },
72- "age":{
73- "type":"integer",
74- "properties":{}
75- }
76- }
77- }
78- }
79- }` ,
62+ "type":"object",
63+ "properties":{
64+ "user":{
65+ "type":"object",
66+ "properties":{
67+ "name":{
68+ "type":"string"
69+ },
70+ "age":{
71+ "type":"integer"
72+ }
73+ }
74+ }
75+ }
76+ }` ,
8077 },
8178 {
8279 name : "Test with complex nested Definition" ,
@@ -108,36 +105,32 @@ func TestDefinition_MarshalJSON(t *testing.T) {
108105 },
109106 },
110107 want : `{
111- "type":"object",
112- "properties":{
113- "user":{
114- "type":"object",
115- "properties":{
116- "name":{
117- "type":"string",
118- "properties":{}
119- },
120- "age":{
121- "type":"integer",
122- "properties":{}
123- },
124- "address":{
125- "type":"object",
126- "properties":{
127- "city":{
128- "type":"string",
129- "properties":{}
130- },
131- "country":{
132- "type":"string",
133- "properties":{}
134- }
135- }
136- }
137- }
138- }
139- }
140- }` ,
108+ "type":"object",
109+ "properties":{
110+ "user":{
111+ "type":"object",
112+ "properties":{
113+ "name":{
114+ "type":"string"
115+ },
116+ "age":{
117+ "type":"integer"
118+ },
119+ "address":{
120+ "type":"object",
121+ "properties":{
122+ "city":{
123+ "type":"string"
124+ },
125+ "country":{
126+ "type":"string"
127+ }
128+ }
129+ }
130+ }
131+ }
132+ }
133+ }` ,
141134 },
142135 {
143136 name : "Test with Array type Definition" ,
@@ -153,20 +146,16 @@ func TestDefinition_MarshalJSON(t *testing.T) {
153146 },
154147 },
155148 want : `{
156- "type":"array",
157- "items":{
158- "type":"string",
159- "properties":{
160-
161- }
162- },
163- "properties":{
164- "name":{
165- "type":"string",
166- "properties":{}
167- }
168- }
169- }` ,
149+ "type":"array",
150+ "items":{
151+ "type":"string"
152+ },
153+ "properties":{
154+ "name":{
155+ "type":"string"
156+ }
157+ }
158+ }` ,
170159 },
171160 }
172161
@@ -193,6 +182,185 @@ func TestDefinition_MarshalJSON(t *testing.T) {
193182 }
194183}
195184
185+ func TestStructToSchema (t * testing.T ) {
186+ tests := []struct {
187+ name string
188+ in any
189+ want string
190+ }{
191+ {
192+ name : "Test with empty struct" ,
193+ in : struct {}{},
194+ want : `{
195+ "type":"object",
196+ "additionalProperties":false
197+ }` ,
198+ },
199+ {
200+ name : "Test with struct containing many fields" ,
201+ in : struct {
202+ Name string `json:"name"`
203+ Age int `json:"age"`
204+ Active bool `json:"active"`
205+ Height float64 `json:"height"`
206+ Cities []struct {
207+ Name string `json:"name"`
208+ State string `json:"state"`
209+ } `json:"cities"`
210+ }{
211+ Name : "John Doe" ,
212+ Age : 30 ,
213+ Cities : []struct {
214+ Name string `json:"name"`
215+ State string `json:"state"`
216+ }{
217+ {Name : "New York" , State : "NY" },
218+ {Name : "Los Angeles" , State : "CA" },
219+ },
220+ },
221+ want : `{
222+ "type":"object",
223+ "properties":{
224+ "name":{
225+ "type":"string"
226+ },
227+ "age":{
228+ "type":"integer"
229+ },
230+ "active":{
231+ "type":"boolean"
232+ },
233+ "height":{
234+ "type":"number"
235+ },
236+ "cities":{
237+ "type":"array",
238+ "items":{
239+ "additionalProperties":false,
240+ "type":"object",
241+ "properties":{
242+ "name":{
243+ "type":"string"
244+ },
245+ "state":{
246+ "type":"string"
247+ }
248+ },
249+ "required":["name","state"]
250+ }
251+ }
252+ },
253+ "required":["name","age","active","height","cities"],
254+ "additionalProperties":false
255+ }` ,
256+ },
257+ {
258+ name : "Test with description tag" ,
259+ in : struct {
260+ Name string `json:"name" description:"The name of the person"`
261+ }{
262+ Name : "John Doe" ,
263+ },
264+ want : `{
265+ "type":"object",
266+ "properties":{
267+ "name":{
268+ "type":"string",
269+ "description":"The name of the person"
270+ }
271+ },
272+ "required":["name"],
273+ "additionalProperties":false
274+ }` ,
275+ },
276+ {
277+ name : "Test with required tag" ,
278+ in : struct {
279+ Name string `json:"name" required:"false"`
280+ }{
281+ Name : "John Doe" ,
282+ },
283+ want : `{
284+ "type":"object",
285+ "properties":{
286+ "name":{
287+ "type":"string"
288+ }
289+ },
290+ "additionalProperties":false
291+ }` ,
292+ },
293+ {
294+ name : "Test with enum tag" ,
295+ in : struct {
296+ Color string `json:"color" enum:"red,green,blue"`
297+ }{
298+ Color : "red" ,
299+ },
300+ want : `{
301+ "type":"object",
302+ "properties":{
303+ "color":{
304+ "type":"string",
305+ "enum":["red","green","blue"]
306+ }
307+ },
308+ "required":["color"],
309+ "additionalProperties":false
310+ }` ,
311+ },
312+ {
313+ name : "Test with nullable tag" ,
314+ in : struct {
315+ Name * string `json:"name" nullable:"true"`
316+ }{
317+ Name : nil ,
318+ },
319+ want : `{
320+
321+ "type":"object",
322+ "properties":{
323+ "name":{
324+ "type":"string",
325+ "nullable":true
326+ }
327+ },
328+ "required":["name"],
329+ "additionalProperties":false
330+ }` ,
331+ },
332+ }
333+
334+ for _ , tt := range tests {
335+ t .Run (tt .name , func (t * testing.T ) {
336+ wantBytes := []byte (tt .want )
337+
338+ schema , err := jsonschema .GenerateSchemaForType (tt .in )
339+ if err != nil {
340+ t .Errorf ("Failed to generate schema: error = %v" , err )
341+ return
342+ }
343+
344+ var want map [string ]interface {}
345+ err = json .Unmarshal (wantBytes , & want )
346+ if err != nil {
347+ t .Errorf ("Failed to Unmarshal JSON: error = %v" , err )
348+ return
349+ }
350+
351+ got := structToMap (t , schema )
352+ gotPtr := structToMap (t , & schema )
353+
354+ if ! reflect .DeepEqual (got , want ) {
355+ t .Errorf ("MarshalJSON() got = %v, want %v" , got , want )
356+ }
357+ if ! reflect .DeepEqual (gotPtr , want ) {
358+ t .Errorf ("MarshalJSON() gotPtr = %v, want %v" , gotPtr , want )
359+ }
360+ })
361+ }
362+ }
363+
196364func structToMap (t * testing.T , v any ) map [string ]any {
197365 t .Helper ()
198366 gotBytes , err := json .Marshal (v )
0 commit comments