Skip to content

Commit eacc85f

Browse files
committed
Add examples and update docs and README
1 parent 37fa70a commit eacc85f

File tree

5 files changed

+142
-3
lines changed

5 files changed

+142
-3
lines changed

README.md

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,53 @@
11
# JSON typedef infer
22

3-
This is a port of [`json-typedef-infer`][jtd-infer] from Rust to Go. The reason
4-
for porting this is that I was in need of JTD inference from code and not as a
5-
CLI tool so I ported this straight from Rust.
3+
This is a port of [`json-typedef-infer`][jtd-infer] Go. The reason for porting
4+
this is that I was in need of JTD inference from code and not as a CLI tool.
5+
6+
For more information about JSON Typedef and its RFC and how to use different
7+
kind of hints see [`json-typedef-infer`][jtd-infer]
8+
9+
## Usage
10+
11+
See [examples] directory for runnable examples and how to infer JTD.
12+
13+
```go
14+
schema := NewInferrer(WithoutHints()).
15+
Infer("my-string").
16+
IntoSchema(WithoutHints())
17+
// {
18+
// "type": "string"
19+
// }
20+
```
21+
22+
If you have multiple rows of objects or lists as strings you can pass them to
23+
the shorthand function `InferStrings`.
24+
25+
```go
26+
rows := []string{
27+
`{"name":"Joe", "age": 52, "something_optional": true, "something_nullable": 1.1}`,
28+
`{"name":"Jane", "age": 48, "something_nullable": null}`,
29+
}
30+
schema := InferStrings(rows, WithoutHints()).IntoSchema(WithoutHints())
31+
// {
32+
// "properties": {
33+
// "age": {
34+
// "type": "uint8"
35+
// },
36+
// "name": {
37+
// "type": "string"
38+
// },
39+
// "something_nullable": {
40+
// "nullable": true,
41+
// "type": "float64"
42+
// }
43+
// },
44+
// "optionalProperties": {
45+
// "something_optional": {
46+
// "type": "boolean"
47+
// }
48+
// }
49+
// }
50+
```
651

752
[jtd-infer]: https://github.com/jsontypedef/json-typedef-infer/
53+
[examples]: examples
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
6+
"github.com/bombsimon/jtdinfer"
7+
)
8+
9+
func main() {
10+
rows := []string{
11+
`{"name":"Joe", "age": 52, "something_optional": true, "something_nullable": 1.1}`,
12+
`{"name":"Jane", "age": 48, "something_nullable": null}`,
13+
}
14+
schema := jtdinfer.
15+
InferStrings(rows, jtdinfer.WithoutHints()).
16+
IntoSchema(jtdinfer.WithoutHints())
17+
18+
j, _ := json.MarshalIndent(schema, "", " ")
19+
print(string(j))
20+
}

examples/infer_simple_value.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
6+
"github.com/bombsimon/jtdinfer"
7+
)
8+
9+
func main() {
10+
schema := jtdinfer.
11+
NewInferrer(jtdinfer.WithoutHints()).
12+
Infer("my-string").
13+
IntoSchema(jtdinfer.WithoutHints())
14+
15+
j, _ := json.MarshalIndent(schema, "", " ")
16+
print(string(j))
17+
}

examples/infer_with_hints.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
6+
"github.com/bombsimon/jtdinfer"
7+
)
8+
9+
func main() {
10+
rows := []string{
11+
`{
12+
"name":"Joe",
13+
"age":52,
14+
"work":{"department": "sales"},
15+
"values":{"x": [1, 2, 3], "y": [4, 5, 6], "z": [7, 8, 9]},
16+
"discriminator":[{"type":"s", "value":"foo"},{"type":"n", "value":3.14}]
17+
}`,
18+
`{
19+
"name":"Jane",
20+
"age":48,
21+
"work":{"department": "engineering"},
22+
"values":{"x": [1, 2, 3], "y": [4, 5, 6], "z": [7, 8, -2000]},
23+
"discriminator":[{"type":"s", "value":"foo"},{"type":"n", "value":3.14}]
24+
}`,
25+
}
26+
hints := jtdinfer.Hints{
27+
DefaultNumType: jtdinfer.NumTypeUint32,
28+
Enums: jtdinfer.NewHintSet().Add([]string{"work", "department"}),
29+
Values: jtdinfer.NewHintSet().Add([]string{"values"}),
30+
Discriminator: jtdinfer.NewHintSet().Add([]string{"discriminator", "-", "type"}),
31+
}
32+
33+
schema := jtdinfer.InferStrings(rows, hints).IntoSchema(hints)
34+
j, _ := json.MarshalIndent(schema, "", " ")
35+
print(string(j))
36+
}

hints.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
package jtdinfer
22

3+
// Wildcard represents the character that matches any value for hints.
34
const Wildcard = "-"
45

6+
// Hints contains the default number type to use and all the hints for enums,
7+
// values and discriminators.
58
type Hints struct {
69
DefaultNumType NumType
710
Enums HintSet
811
Values HintSet
912
Discriminator HintSet
1013
}
1114

15+
func WithoutHints() Hints {
16+
return Hints{}
17+
}
18+
19+
// SubHint will return the sub hints for all hint sets for the passed key.
1220
func (h Hints) SubHints(key string) Hints {
1321
return Hints{
1422
DefaultNumType: h.DefaultNumType,
@@ -18,33 +26,42 @@ func (h Hints) SubHints(key string) Hints {
1826
}
1927
}
2028

29+
// IsEnumActive checks if the enum hint set is active.
2130
func (h Hints) IsEnumActive() bool {
2231
return h.Enums.IsActive()
2332
}
2433

34+
// IsValuesActive checks if the values hint set is active.
2535
func (h Hints) IsValuesActive() bool {
2636
return h.Values.IsActive()
2737
}
2838

39+
// PeekActiveDiscriminator will peek the currently active discriminator, if any.
40+
// The returned boolean tells if there is an active discriminator.
2941
func (h Hints) PeekActiveDiscriminator() (string, bool) {
3042
return h.Discriminator.PeekActive()
3143
}
3244

45+
// HintSet represents a list of paths (lists) to match for hints.
3346
type HintSet struct {
3447
Values [][]string
3548
}
3649

50+
// NewHintSet creates a new empty `HintSet`.
3751
func NewHintSet() HintSet {
3852
return HintSet{
3953
Values: [][]string{},
4054
}
4155
}
4256

57+
// Add will add a path (slice) to the `HintSet`.
4358
func (h HintSet) Add(v []string) HintSet {
4459
h.Values = append(h.Values, v)
4560
return h
4661
}
4762

63+
// SubHint will filter all the current sets and keep those who's first element
64+
// matches the passed key or wildcard.
4865
func (h HintSet) SubHints(key string) HintSet {
4966
filteredValues := [][]string{}
5067

@@ -64,6 +81,7 @@ func (h HintSet) SubHints(key string) HintSet {
6481
}
6582
}
6683

84+
// IsActive returns true if any set in the hint set his active.
6785
func (h HintSet) IsActive() bool {
6886
for _, valueList := range h.Values {
6987
if len(valueList) == 0 {
@@ -74,6 +92,8 @@ func (h HintSet) IsActive() bool {
7492
return false
7593
}
7694

95+
// PeekActive returns the currently active value if any. The returned boolean
96+
// tells if a value was found.
7797
func (h HintSet) PeekActive() (string, bool) {
7898
for _, values := range h.Values {
7999
if len(values) != 1 {

0 commit comments

Comments
 (0)