jsonschema2pojo icon indicating copy to clipboard operation
jsonschema2pojo copied to clipboard

Conditional subschemas

Open sobeos opened this issue 4 years ago • 9 comments
trafficstars

Hi,

looks like conditional subschemas are ignored. If I try to generate POJOs from the examples from the following site https://json-schema.org/understanding-json-schema/reference/conditionals.html the conditional parts get ignored. Any hints on this?

Best regards

Joe

sobeos avatar Dec 23 '20 23:12 sobeos

Hi,

It's a nice case. Would you like to simply generate a POJO or verify it as well?

I'd simplify schema for a generator to put data to fields and back and used a proper JSON Schema validator for the rest. To achieve this, I'd use oneOf instead of if.

eirnym avatar Dec 24 '20 14:12 eirnym

Hi Eirnym,

Would you like to simply generate a POJO or verify it as well?

I do both. For schema validation I use everits's JSON Schema Validator.

I'd simplify schema for a generator to put data to fields and back and used a proper JSON Schema validator for the rest. To achieve this, I'd use oneOf instead of if.

We use the json schema definition as definition of an API between two teams. Target is to generate the JAVA classes without changing the predefined Json Schema.

Is if/then officially not supported?

Best regards

Joe

sobeos avatar Dec 25 '20 22:12 sobeos

No, this new feature isn't supported. Can you give an example of how you want to use it and what Java would would expect to see as a result?

joelittlejohn avatar Dec 25 '20 22:12 joelittlejohn

Example Json:

{ "type": "object", "properties": { "street_address": { "type": "string" }, "country": { "enum": ["United States of America", "Canada", "Netherlands"] } }, "allOf": [ { "if": { "properties": { "country": { "const": "United States of America" } } }, "then": { "properties": { "class1": { "type": "object", ... } } } }, { "if": { "properties": { "country": { "const": "Canada" } } }, "then": { "properties": { "class2": { "type": "object", ... } } } }, { "if": { "properties": { "country": { "const": "Netherlands" } } }, "then": { "properties": { "class3": { "type": "object", ... } } } } ] }

I would expect to get a Java class containing the fields street_address and country and optional member fields for class1, class2 and class3. And all three classes can have different fields and so on.

sobeos avatar Dec 26 '20 00:12 sobeos

@sobeos do I understand correctly, that generator basically should generate all fields?

If same field in different branches has different constraint such as type and other one generated by a generator, the exception will be thrown

Is it correct?

eirnym avatar Dec 26 '20 17:12 eirnym

@eirnym : It would be really great to see this feature!

If same field in different branches has different constraint such as type and other one generated by a generator, the exception will be thrown

I think, it depends on the case. For one field with different possible types I would suggest object as type.

For the beginning it would be great to get allOf, anyOf, oneOf to generate the object structure as member fields. Then it would be nice to get checks if all, any and one is valid. Same for if/then. First it would be super to simply get the object structure generated. Checks for if/then would be the final step.

sobeos avatar Dec 26 '20 21:12 sobeos

I'd +1 this request.

I've a similar problem where I'd like to do something like:

{
  "definitions":{
    "domain": {  //interface or abstract class?
      "properties":{
        "name":{
          "enum": ["science","engineering"]
        },
        "subdomain":{
          "type": "string"
        }
      },
      "require":["name","subdomain"]
    },
    "science":{
      "allOf": [{"$ref":"#/definitions/domain"}],
      "properties": {
        "subdomain": {
          "enum": ["physics", "biology"]
        }
      }
    },
    "engineering":{
      "allOf": [{"$ref":"#/definitions/domain"}],
      "properties": {
        "subdomain": {
          "enum": ["Mechanical", "Electrical"]
        }
      }
    }
  }
}

I've got a conditional where a second field can only be of a select number of values depending on the first field. At present I'm doing this in json schema by using if else statements and just having a schema for the domain. This means the maven plugin still creates a class that isn't just Object.

Lovett1991 avatar Jan 26 '21 10:01 Lovett1991

@sobeos I think that your problem can be solved without conditionals:

"framework-context": {
  "type": "object",
  "oneOf": [ {
      "properties": {
        "kind": { "type": "string","const": "node-package"},
        (...)
      }
    }, {
      "properties": {
        "kind": {"type": "string","const": "script-urls"},
        (...)
      }
  }]
}

The result is similar in terms of validation. My support for oneOf - #1193 - manages to generate all the needed classes and the implied enum class. It doesn't support common properties for all "subclasses" at the root yet, since I didn't need that, it could be added. Let's see what @joelittlejohn would say to the contribution.

piotrtomiak avatar Feb 08 '21 10:02 piotrtomiak

Example Json:

I would expect to get a Java class containing the fields street_address and country and optional member fields for class1, class2 and class3. And all three classes can have different fields and so on.

Adding a formatted version of the schema since the one above is a bit difficult to read:

original example
{
    "type": "object",
    "properties": {
        "street_address": {"type": "string"},
        "country": {
            "enum": [
                "United States of America",
                "Canada",
                "Netherlands"
            ]
        }
    },
    "allOf": [{
        "if": {
            "properties": {
                "country": {"const": "United States of America"}
            }
        },
        "then": {
            "properties": {
                "class1": {"type": "object", "...": "..."}
            }
        }
    },
    {
        "if": {
            "properties": {
                "country": {"const": "Canada"}
            }
        },
        "then": {
            "properties": {
                "class2": {"type": "object", "...": "..."}
            }
        }
    },
    {
        "if": {
            "properties": {
                "country": {"const": "Netherlands"}
            }
        },
        "then": {
            "properties": {
                "class3": {"type": "object", "...": "..."}
            }
        }
    } ]
}

alexanderankin avatar Oct 01 '22 19:10 alexanderankin