I’m using JSON Schema and auto generating it using gojsonschema. Unfortunately, it’s getting several of the fields wrong, and I want to fix them.
Here is the schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/filecoin-project/bacalhau/pkg/model/job",
"$ref": "#/$defs/Job",
"$defs": {
"Deal": {
"properties": {
"Concurrency": {
"type": "integer"
},
"Confidence": {
"type": "integer"
},
"MinBids": {
"type": "integer"
}
},
"additionalProperties": false,
"type": "object"
},
"Spec": {
"properties": {
"Engine": {
"type": "integer"
},
"Verifier": {
"type": "integer"
},
},
}
}
}
What I’d like to do is find the path to a given field (in this case "Engine") programatically. This is so I can just list all the objects that need changing (they all need changing in the same way), and loop through them in an array. So something like this (which works today).
func FixJSONSchema() ([]byte, error) {
s := jsonschema.Reflect(&model.Job{})
jsonSchemaData, err := json.MarshalIndent(s, "", " ")
if err != nil {
return nil, fmt.Errorf("error indenting %s", err)
}
// JSON String
jsonString := string(jsonSchemaData)
enumTypes := []struct {
Name string
Path string
}{
{Name: "Engine", Path: "$defs.Spec.properties.Engine.type"},
{Name: "Verifier", Path: "$defs.Spec.properties.Verifier.type"},
}
for _, enumType := range enumTypes {
// Use sjson to find the enum type path in the JSON
jsonString, _ = sjson.Set(jsonString, enumType.Path, "string")
}
return []byte(jsonString), nil
}
I’m using the excellent sjson library to accomplish this. https://github.com/tidwall/sjson
So, in summary, what I’d really prefer to do, is just have an array ["Engine", "Verifier", ...] and use a tool to search the entire structure and return the path (or paths if multiple things match).
>Solution :
Honestly it seems like you are over-complicating the task. Using reflect is
rarely the right solution to any problem, instead you could use something like
Gron. Here it is with PowerShell:
> gron schema.json | Select-String engine
json.$defs.Spec.properties.Engine = {};
json.$defs.Spec.properties.Engine.type = "integer";
or POSIX shell:
gron schema.json | grep engine
https://github.com/tomnomnom/gron