$ref doesn't seem to be working

574 views
Skip to first unread message

Kerzhner, Olia

unread,
Apr 18, 2011, 1:16:48 PM4/18/11
to jsonschema...@googlegroups.com

Hi,

I was very excited to find this library, it looks like exactly what we need!

 

However, there seems to be a bug in how $ref is being processed.   Basically, the property name is being used as the class name, rather than the $ref value. 

 

Below are the two little schemas that make up my test case, I can also add the generated code, but  you can try it for yourself.

 

Anyone knows how to submit an issue?  All I found was this mailing list.

 

Thanks for any help!

OIia

 

 

{

    "title" : "House",

    "id" : "http://testtypes.com/house.json",

    "description" : "house type",

    "type" : "object",

    "properties" : {

        "cat" : {

            "$ref" : "pet.json"

        },

        "dog" : {

            "$ref" : "pet.json"

        }

    },

    "$schema": "http://json-schema.org/draft-03/schema#"

}

 

 

{

    "title" : "Pet",

    "id" : "http://testtypes.com/pet.json",

    "description" : " Pet",

    "type" : "object",

    "properties" : {

        "name" : {

            "type" : "string",

            "required" : false

        },

        "age" : {

            "type" : "integer",

            "minimum" : 1,

            "maximum" : 12,

            "required" : false

        }

    },

    "required" : true,

    "$schema": "http://json-schema.org/draft-03/schema#"

}

 

 

Joe

unread,
Apr 18, 2011, 6:02:39 PM4/18/11
to jsonschema2pojo-users
Hi Olia,

Thanks very much for your post. I see you've found the issue tracker
now (http://code.google.com/p/jsonschema2pojo/issues/list).

jsonschema2pojo tries to use the most convenient name it can find but
this does sometimes produce some undesirable results (particularly
where refs are used). When a file is read, the filename is used as the
class name. When schemas are encountered within the document (either
embedded or referenced) the property name is used.

I think we have a couple of options here. The first is the extension
property 'javaType':

http://code.google.com/p/jsonschema2pojo/wiki/Reference#javaType

If you add this property to your Pet schema, you can be sure that no
matter how/when/where the schema is referenced, it will always
generate the same Java class name (the one that you specify).

We could also rethink how the class name is generated by default, it's
not particularly intelligent at the moment. It's possible that we just
need a configurable option here so that people can choose their own
naming policy, but I'd like to avoid this if possible. The class name
could come from the 'title' property, or possibly be snipped from the
ref URI.

I'm interested to know, when you first ran this, which part of the pet
schema did you expect would be used to name the class? Was it the
title property, the id, the filename or the ref URI? (I know the last
two are the same thing in this case :))

Cheers,,

Joe

Joe

unread,
Apr 18, 2011, 6:04:07 PM4/18/11
to jsonschema2pojo-users
Adding a link to the ticket for reference:
http://code.google.com/p/jsonschema2pojo/issues/detail?id=22

Olia Kerzhner

unread,
Apr 18, 2011, 7:36:02 PM4/18/11
to jsonschema...@googlegroups.com
Hi Jow,
thanks for the quick reply!

I guess I didn't think much about it, just immediately jumped to the conclusion that the URI (from the $ref URI) should be used as the basis for the file name. 

Now that I think about it base on your question, that still sounds like the right way to go to me.  My reasoning is that the "title" property is not required, nor is the "javaType" property, but you do need to have a $ref URI, because that's the only way you could use $ref!  Maybe the ability to override this with a "javaType" property is a nice option to have.  We try to be very consistent with our schema names/uris/titles and make sure they are all the same, so it doesn't so much matter to us.

Having said that, that's just my opinion, and whatever you decide will work fine, I'm just thrilled to have a library that works! 

I spent some time hacking around today trying to get my usecase working, and added a hack that seems to work for me.  I don't fully understand how the code works, so this might not be a good idea, but here it is in case it's at all useful:

in JsonSchemaRule.java, in the apply method:

    public JType apply(String nodeName, JsonNode schemaNode, JClassContainer generatableType,
                    Schema schema) {
        if (schemaNode.has("$ref")) {
            String newNodeName = nodeName;
            String refValue = schemaNode.get("$ref").getTextValue();
            if(!refValue.startsWith( "file:" )) {
                newNodeName = schemaNode.get("$ref").getTextValue();
                newNodeName = newNodeName.replace(".json", "");
            }
                  
            schema = Schema.create(schema, refValue);
            schemaNode = schema.getContent();
              
            if (schema.isGenerated()) {
                return schema.getJavaType();
            } 
 
            return apply(newNodeName, schemaNode, generatableType, schema);
        }
etc...


Thank you,
Olia

Olia Kerzhner

unread,
Apr 19, 2011, 2:43:45 PM4/19/11
to jsonschema...@googlegroups.com
Hi Joe,
I tried out the "javaType" property thing, and that's pretty cool.  I do have a couple of issues though, which might be bugs or might be misunderstanding how things should work.

Would you like me to submit "issues" with test cases, or try and hash it out over email on this list first?

thanks!
Olia

Joe

unread,
Apr 20, 2011, 6:42:29 AM4/20/11
to jsonschema2pojo-users
Hi Olia,

Feel free to give a short description of your problems. I wont waste
your time with creating issues right now - lets do that if it looks
like something really is wrong.

When making a for $ref change here we just have to be careful to
consider all the possible values that $ref can have. The $ref value is
a URI, absolute or relative, and may refer to a complete document
(with or without an file extension) or a fragment. So all these are
valid:

abc
../../abc
abc.json
file://home/jlittlej/schemas/abc
file://home/jlittlej/schemas/abc.json
file://home/jlittlej/schemas/abc.json#parentNode/childNode
http://json-schema.org/address

I guess it's easy to see how some of these would become a class name,
but for others it's not so obvious. I'd like to apply the principle of
least surprise here, which is why I was interested in what your
thoughts were when you first saw this. Do you think the javaType
property will satisfy your needs here?



On Apr 19, 7:43 pm, Olia Kerzhner <olia.kerzh...@gmail.com> wrote:
> Hi Joe,
> I tried out the "javaType" property thing, and that's pretty cool.  I do
> have a couple of issues though, which might be bugs or might be
> misunderstanding how things should work.
>
> Would you like me to submit "issues" with test cases, or try and hash it out
> over email on this list first?
>
> thanks!
> Olia
>

Olia Kerzhner

unread,
Apr 20, 2011, 1:24:14 PM4/20/11
to jsonschema...@googlegroups.com
Hi Joe,
yes, switching to using the JavaType property solves my use case completely.  I must admit I didn't pay much attention to it until you pointed it out, but it works just fine. 

There are a couple of questions I have about it though:
1. It seems that the -p <package> argument is ignored when generating classes that have the JavaType arg set.  Is that intentional?  I was expecting that the package specified by the -p argument would be used as the base for the class path pointed to by JavaType.
Of course, it's not too difficult to work around this behavior.

2. I really like the feature that allows us to use existing classes, rather then always generated them.  However, it looks like that only works if the .java files are in the same directory as the schemas.  I was expecting that it would instead check the path to where the file would actually get generated to, and skip the generation if the file is already there. 
This seems like the incorrect behavior to me, and is more difficult to work around -- we would have to keep our custom .java files in the same directory as our schemas, and then have a separate script that copies them into the right place in the package.

Hope these questions make sense!

thanks again for the help,
Olia

Joe

unread,
Apr 21, 2011, 6:39:20 AM4/21/11
to jsonschema2pojo-users
Olia,

I think both of your points here (1 & 2) are caused by the same
underlying feature. The javaType property is expecting a fully
qualified class name. So, when you specify a javaType, the -p argument
is no longer used.

When you refer to an existing type using the javaType property you
certainly shouldn't have the have that type in the same directory. Are
you using a fully qualified name to refer to your custom type? Again,
my guess is that the behaviour you're seeing is caused by not using a
fully qualified type name, hence jsonschema2pojo thinks you're what
you actually want is a new Java type in the default package.

I don't know if my explanation is clear enough, but hopefully this
will help. If you still think something is wrong here then feel free
to raise a bug.

Cheers

Joe




On Apr 20, 6:24 pm, Olia Kerzhner <olia.kerzh...@gmail.com> wrote:
> Hi Joe,

Olia Kerzhner

unread,
Apr 21, 2011, 1:39:27 PM4/21/11
to jsonschema...@googlegroups.com
Hi Joe,
that does make sense, thanks for the explanation.  It still feels counter-intuitive that the package argument is not used as the basis for the fully-qualified class name, but it's certainly does not present any roadblocks.

Thanks!
Olia
Reply all
Reply to author
Forward
0 new messages