Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add @Valid on all collections, not just those with items type "object" #158

Closed
akushe opened this issue Mar 4, 2014 · 10 comments
Closed
Milestone

Comments

@akushe
Copy link

akushe commented Mar 4, 2014

I have a list of objects which internally hold types of either A,B or C .It has been declared in the following fashion

        "types" : {
            "type": "array",
            "minitems":0,
            "items": {
                "anyOf": [
                    { "$ref": "A.json" },
                    { "$ref": "B.json" },
                    { "$ref": "C.json" }
                ]
            },
        "required" : false
        }

This generates a Pojo without the @Valid object

     @JsonProperty("experiences")
    private List<Object> types = new ArrayList<Object>();

Question is would it be possible to add @Valid annotation on the list ?

@joelittlejohn
Copy link
Owner

"anyOf" is draft04 syntax, it's not currently supported.

@joelittlejohn
Copy link
Owner

To elaborate further, the equivalent syntax in draft03 is a union type. jsonschema2pojo doesn't support types of this kind as they cannot accurately be described, in a general way, in Java's type system. This kind of highly dynamic schema is not a good fit for binding to static types and you may find Jackson's tree API more effective.

@akushe
Copy link
Author

akushe commented Mar 4, 2014

Yeah we found a way to get around the anyOf .We many validate whether the objects are of types A, B or C but because the @Valid annotation the objects which of type A,B or C are not validated.Do you think the union type will take care of it ?

@joelittlejohn
Copy link
Owner

try this:

"items": {
    "type" : "object",
    "anyOf" : ...

@Valid is only used when the items are of type object or array (if they're primitive then @Valid is not used). In your case, using "type" : "object" will cause a new type to be generated (which I guess you don't want). You could specify "javaType":"java.lang.Object " to work around this but I think we should definitely make a fix that would cause @Valid to be applied whenever the final, resolved type is not primitive.

By omitting a type to get java.lang.Object values you are basically hacking the system and causing it to use a fall-back type. This is why the @Valid rule wouldn't expect to accommodate this case.

@joelittlejohn joelittlejohn reopened this Mar 5, 2014
@akushe
Copy link
Author

akushe commented Mar 5, 2014

I tried using "javaType":"java.lang.Object " but I still don't see a @Valid annotation being added on the List .Another odd behavior I say is that the "minitems":0 does not translate to @SiZe(min = 0)

@joelittlejohn
Copy link
Owner

You need "type" : "object", the @SiZe annotation is only added when array items are of type object or array. Here's the code:

https://github.com/joelittlejohn/jsonschema2pojo/blob/jsonschema2pojo-0.4.0/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/PropertyRule.java#L118

The reason I suggested you might also want to use "javaType":"java.lang.Object" is that I am guessing you do not want a new type generated (I assume you want to use java.lang.Object as part of your workaround for anyOf?).

@akushe
Copy link
Author

akushe commented Mar 5, 2014

So you are saying the "javaType":"java.lang.Object" will not generate the @Valid annotation ?
Is there any other way I could make this to work .I tried declaring it in this fashion but still I don't get the @Valid annotation

  "types" : {
            "type": "array",
            "minitems":0,
            "items": 
                 [
                    { "$ref": "A.json" },
                    { "$ref": "B.json" },
                    { "$ref": "C.json" }
                ]
            ,
        "required" : false
        } 

Looking at the PropertyRule code I realize the type of the objects inside items must either be an object or an Array.The type of the A.json, B.json and C.json is an object

@joelittlejohn
Copy link
Owner

Yes, exactly, adding "javaType":"java.lang.Object" is not enough to produce @Valid because of the code I linked to above. When you omit the items "type" : "object" as a hack to create List<Object> you are using a fallback mechanism and the rules for @Valid aren't applied. Only schemas with json schema items type "object" or "array" produce the @Valid annotation, javaType is currently irrelevant but I think we should fix this.

This library doesn't support union types:

To elaborate further, the equivalent syntax in draft03 is a union type. jsonschema2pojo doesn't
support types of this kind...

Sorry if I'm not making myself clear enough. Here's the exact code that I am suggesting you could use:

    "types" : {
        "type": "array",
        "minitems":0,
        "items": {
            "type" : "object",
            "javaType" : "java.lang.Object"
        },
        "required" : false
    }

@akushe
Copy link
Author

akushe commented Mar 5, 2014

Thanks the last piece does work. But there is one last problem I am facing.
When we try to deserialize a json document we get a LinkedHashMap instead of a subType of A,B or C.Do you have any idea how this should be solved ?

@joelittlejohn
Copy link
Owner

I'm afraid there is no way to use this library by support union types and polymorphic deserialization. Your schema and types currently have no indication of how/when A, B anc C should be used, how could Jackson know which one to create?

If you have data like this, I suggest it may be more appropriate to hand code these types. You should look into Jackson's polymorphic deserialization. You'll certainly need to add something to your data to indicate the java type that should be used (the documentation suggests using a property in the data called @class).

One simple solution you can use here is to merge A, B and C together (assuming this is possible). Of course your types would accept potentially invalid data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants