java-json-tools / json-schema-validator

A JSON Schema validation implementation in pure Java, which aims for correctness and performance, in that order
http://json-schema-validator.herokuapp.com/
Other
1.62k stars 399 forks source link

cross-field validation.... #138

Open shan1982 opened 9 years ago

shan1982 commented 9 years ago

Hi Francis,

I need have parent Node (not a root Node) in the validate method. Let me explain with example.

My Sample JSON is...

{ "persons":[ { "value1":1, "value2":2 }, { "value1":3, "value2":4 } ]}

{ "$schema":"http://json-schema.org/draft-04/schema#", "id":"http://jsonschema.net", "type":"object", "properties":{ "persons":{ "id":"http://jsonschema.net/persons", "type":"array", "items":[ { "id":"http://jsonschema.net/persons/0", "type":"object", "properties":{ "value1":{ "id":"http://jsonschema.net/persons/0/value1", "type":"boolean" }, "value2":{ "id":"http://jsonschema.net/persons/0/value2", "type":"integer", "requiredIf" : { "path" : "value1", "value": true } } } } ] } } }

As per the example i have keyword 'requiredIf' with in the property "value2". So the idea is to validate "value2" based on the "value1", My sample has 2 set of persons. So have to validate "value2" with the corresponding "value1"

So whenever the parser encounter the keyword, it calls validate method, that's fine. since the FullData (data) has the control only over "value2", i have to get the base node to retrieve corresponding value for "value1"'. When i use data.getSchema().getBaseNode()', it returns the whole json. Whole Json has 2 set of person, but i need the one corresponding to the current position.. Can you please guide me on this?

fge commented 9 years ago

(why do you put "id"s everywhere? That's not needed)

If I understand what you want to achieve, that would be to make the value of value2 depend on the value of value1?

shan1982 commented 9 years ago

exactly...

but have to same Schema approach..

fge commented 9 years ago

OK, so, first things first, I don't know how you want to specify what values value1 should take, but you can use the dependencies keyword; for instance:

{
    "other": "keywords",
    "dependencies": {
        "value1": { "additional": "schemaIfValue1IsPresent" }
    }
}

For JSON Object instances it will mean that if a member by name value1 is present, then the whole instance has to obey the additional schema.

This however does not seem to really be what you want. It depends on how you want to specify the values of value1 and value2.

Second: .getBaseNode() will return the whole schema, yes; however you can retrieve the schema at the current path with .getNode().

Additionally, I'd say that this seems to be a functional constraint, right? While you can steer the API to do that, it is this really the place to do it?

shan1982 commented 9 years ago

Thank you very much for the updates. Actually approach has been suggested based on our json contract. In-fact initially we came the approach - the one you suggested. So can we have any direct method to retrieve parent node of the current position?

fge commented 9 years ago

Well, I don't remind suggesting that... In fact I wouldn't have.

The problem with your "requiredIf" keyword as currently defined is that it is not attached to the schema of the instance itself.

What I would suggest is the switch keyword I mentioned on the Google group:

{
    "switch": [
        {
            "when": { "properties": { "value1": { "type": "boolean" = } },
            "then": { "required": [ "value2" ], "properties": { "value2": { "schema": "forValue2Here" } } }
        },
        // etc
    ]
}

I have the big problem currently that I am working on other projects so I don't have 100% of my time for json-schema-validator...

prayagupa commented 7 years ago

@fge Does the json-schema-validator support switch statements. Seems it does not.

Something similar to what you guys discussing here, schema stolen from nodejs schema validator

{
  "switch": [
    {
      "when": {
        "properties": {
          "quantity": {
            "minimum": 1000
          }
        }
      },
      "then": {
        "required": [
          "shipToLocation" : ["888"]
        ]
      },
      "continue": true
    },
    {
      "then": {
        "required": [
          "shipByDate"
        ]
      }
    }
  ]
}

I basically need a case,

if quantity == 1000, then shipLocation has to be present and otherwise null is fine,
if shipLocation == 888 then shipByDate has to be present.

screen shot 2017-03-29 at 12 20 38 pm

I tried on heroku-app as well.

screen shot 2017-03-29 at 12 18 28 pm