Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

format: code example #95

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 124 additions & 100 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,61 @@ This library provides Go structures to marshal/unmarshal and reflect [JSON Schem
[Documentation](https://pkg.go.dev/github.com/swaggest/jsonschema-go#Reflector.Reflect).

```go
type MyStruct struct {
Amount float64 `json:"amount" minimum:"10.5" example:"20.6" required:"true"`
Abc string `json:"abc" pattern:"[abc]"`
_ struct{} `additionalProperties:"false"` // Tags of unnamed field are applied to parent schema.
_ struct{} `title:"My Struct" description:"Holds my data."` // Multiple unnamed fields can be used.
}
package main

reflector := jsonschema.Reflector{}
import (
"encoding/json"
"fmt"
"log"

schema, err := reflector.Reflect(MyStruct{})
if err != nil {
log.Fatal(err)
}
"github.com/swaggest/jsonschema-go"
)

j, err := json.MarshalIndent(schema, "", " ")
if err != nil {
log.Fatal(err)
type MyStruct struct {
Amount float64 `json:"amount" minimum:"10.5" example:"20.6" required:"true"`
Abc string `json:"abc" pattern:"[abc]"`
_ struct{} `additionalProperties:"false"` // Tags of unnamed field are applied to parent schema.
_ struct{} `title:"My Struct" description:"Holds my data."` // Multiple unnamed fields can be used.
}

fmt.Println(string(j))

// Output:
// {
// "title": "My Struct",
// "description": "Holds my data.",
// "required": [
// "amount"
// ],
// "additionalProperties": false,
// "properties": {
// "abc": {
// "pattern": "[abc]",
// "type": "string"
// },
// "amount": {
// "examples": [
// 20.6
// ],
// "minimum": 10.5,
// "type": "number"
// }
// },
// "type": "object"
// }
func main() {
reflector := jsonschema.Reflector{}
schema, err := reflector.Reflect(MyStruct{})
if err != nil {
log.Fatal(err)
}

j, err := json.MarshalIndent(schema, "", " ")
if err != nil {
log.Fatal(err)
}

fmt.Println(string(j))

// Output:
// {
// "title": "My Struct",
// "description": "Holds my data.",
// "required": [
// "amount"
// ],
// "additionalProperties": false,
// "properties": {
// "abc": {
// "pattern": "[abc]",
// "type": "string"
// },
// "amount": {
// "examples": [
// 20.6
// ],
// "minimum": 10.5,
// "type": "number"
// }
// },
// "type": "object"
// }
}
```

## Customization
Expand All @@ -71,8 +82,8 @@ It works well for the majority of cases, but if it does not there are rich custo

```go
type MyObj struct {
BoundedNumber int `query:"boundedNumber" minimum:"-100" maximum:"100"`
SpecialString string `json:"specialString" pattern:"^[a-z]{4}$" minLength:"4" maxLength:"4"`
BoundedNumber int `query:"boundedNumber" minimum:"-100" maximum:"100"`
SpecialString string `json:"specialString" pattern:"^[a-z]{4}$" minLength:"4" maxLength:"4"`
}
```

Expand Down Expand Up @@ -111,9 +122,9 @@ Unnamed fields can be used to configure parent schema:

```go
type MyObj struct {
BoundedNumber int `query:"boundedNumber" minimum:"-100" maximum:"100"`
SpecialString string `json:"specialString" pattern:"^[a-z]{4}$" minLength:"4" maxLength:"4"`
_ struct{} `additionalProperties:"false" description:"MyObj is my object."`
BoundedNumber int `query:"boundedNumber" minimum:"-100" maximum:"100"`
SpecialString string `json:"specialString" pattern:"^[a-z]{4}$" minLength:"4" maxLength:"4"`
_ struct{} `additionalProperties:"false" description:"MyObj is my object."`
}
```

Expand All @@ -122,10 +133,10 @@ ReflectContext.UnnamedFieldWithTag option and add matching name tags to structur

```go
type MyObj struct {
BoundedNumber int `query:"boundedNumber" minimum:"-100" maximum:"100"`
SpecialString string `json:"specialString" pattern:"^[a-z]{4}$" minLength:"4" maxLength:"4"`
// These parent schema tags would only be applied to `query` schema reflection (not for `json`).
_ struct{} `query:"_" additionalProperties:"false" description:"MyObj is my object."`
BoundedNumber int `query:"boundedNumber" minimum:"-100" maximum:"100"`
SpecialString string `json:"specialString" pattern:"^[a-z]{4}$" minLength:"4" maxLength:"4"`
// These parent schema tags would only be applied to `query` schema reflection (not for `json`).
_ struct{} `query:"_" additionalProperties:"false" description:"MyObj is my object."`
}
```

Expand Down Expand Up @@ -182,57 +193,70 @@ Yet, you may need to include such fields in JSON schema reflection pipeline.
For any reflected value, standalone or nested, you can define a virtual structure that would be treated as a native Go struct.

```go
s := jsonschema.Struct{}
s.SetTitle("Test title")
s.SetDescription("Test description")
s.DefName = "TestStruct"
s.Nullable = true

s.Fields = append(s.Fields, jsonschema.Field{
Name: "Foo",
Value: "abc",
Tag: `json:"foo" minLength:"3"`,
})

r := jsonschema.Reflector{}
schema, _ := r.Reflect(s)
j, _ := assertjson.MarshalIndentCompact(schema, "", " ", 80)

fmt.Println("Standalone:", string(j))

type MyStruct struct {
jsonschema.Struct // Can be embedded.

Bar int `json:"bar"`

Nested jsonschema.Struct `json:"nested"` // Can be nested.
package main

import (
"fmt"

"github.com/swaggest/assertjson"
"github.com/swaggest/jsonschema-go"
)

func main() {
s := jsonschema.Struct{}
s.SetTitle("Test title")
s.SetDescription("Test description")
s.DefName = "TestStruct"
s.Nullable = true

s.Fields = append(s.Fields, jsonschema.Field{
Name: "Foo",
Value: "abc",
Tag: `json:"foo" minLength:"3"`,
})

r := jsonschema.Reflector{}
schema, _ := r.Reflect(s)
j, _ := assertjson.MarshalIndentCompact(schema, "", " ", 80)

fmt.Println("Standalone:", string(j))

// Output:
// Standalone: {
// "title":"Test title","description":"Test description",
// "properties":{"foo":{"minLength":3,"type":"string"}},"type":"object"
// }

type MyStruct struct {
jsonschema.Struct // Can be embedded.

Bar int `json:"bar"`

Nested jsonschema.Struct `json:"nested"` // Can be nested.
}

ms := MyStruct{}
ms.Nested = s
ms.Struct = s

schema, _ = r.Reflect(ms)
j, _ = assertjson.MarshalIndentCompact(schema, "", " ", 80)

fmt.Println("Nested:", string(j))

// Output:
// Nested: {
// "definitions":{
// "TestStruct":{
// "title":"Test title","description":"Test description",
// "properties":{"foo":{"minLength":3,"type":"string"}},"type":"object"
// }
// },
// "properties":{
// "bar":{"type":"integer"},"foo":{"minLength":3,"type":"string"},
// "nested":{"$ref":"#/definitions/TestStruct"}
// },
// "type":"object"
// }
}

ms := MyStruct{}
ms.Nested = s
ms.Struct = s

schema, _ = r.Reflect(ms)
j, _ = assertjson.MarshalIndentCompact(schema, "", " ", 80)

fmt.Println("Nested:", string(j))

// Output:
// Standalone: {
// "title":"Test title","description":"Test description",
// "properties":{"foo":{"minLength":3,"type":"string"}},"type":"object"
// }
// Nested: {
// "definitions":{
// "TestStruct":{
// "title":"Test title","description":"Test description",
// "properties":{"foo":{"minLength":3,"type":"string"}},"type":"object"
// }
// },
// "properties":{
// "bar":{"type":"integer"},"foo":{"minLength":3,"type":"string"},
// "nested":{"$ref":"#/definitions/TestStruct"}
// },
// "type":"object"
// }
```