Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Searching for a JSON Object in a JSON Schema based on the name and getting the Path

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).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading