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

Switch from HashSet to LinkedHashSet for uniqueItems arrays to preserve order #159

Closed
cmaron opened this issue Mar 5, 2014 · 2 comments
Closed
Milestone

Comments

@cmaron
Copy link
Contributor

cmaron commented Mar 5, 2014

Hey there!

I'm not sure if this has come up before, but the use of a HashSet to implement a list of unique items does not guarantee the order is preserved. Unfortunately I believe JS (and in turn JSON) assume the list order should be preserved.

I've run into a case where something I've defined as a unique list of strings has unpredictable order when I try to use the POJOs generated by jsonschema2pojo.

For example, this schema:

{
    "$schema": "http://json-schema.org/draft-04/schema",
    "id": "#address",
    "title": "Address",
    "description": "A basic physical address",
    "javaType": "com.awesome.mq.types.Address",
    "type": "object",
    "properties": {
        "first_name": {"type": "string", "description": "First name of addressee"},
        "middle_name": {"type": "string", "description": "Middle name of addressee"},
        "last_name": {"type": "string", "description": "Last name of addressee"},
        "street_address": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "minItems": 1,
            "uniqueItems": true
        },
        "locality": { "description": "City, Town, Village, etc.", "type": "string" },
        "region": { "description": "State or Province", "type": "string"},
        "postal_code": { "type": "string" },
        "country_code": { "type": "string" },
        "region_code": { "type": "string" },
        "phone": { "type": "string", "format": "phone"}
    },
    "required": ["addressee","street_address", "locality", "region", "postal_code", "country_code"]
}

Can lead to unpredictable ordering in the street_address list. This is not ideal for cases where you might want to print a shipping label, or something else where the order of the street address lines matter.

Obviously, the schema could be modified to have "street_address_1", "street_address_2", etc., but that seems like a hack rather than an ideal solution.

Is there a reason to use a HashSet over a LinkedHashSet? I believe a LinkedHashSet will preserve insertion order and does not incur the same performance hit as a TreeSet.

Am I correct in thinking that a change to jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/rules/DefaultRule.java is enough to make this happen?

Forgive me if this has been asked a million times before.

Thanks!

@joelittlejohn
Copy link
Owner

Thanks for raising this Chad, this is a very good find! I don't think a lot of people use arrays with uniqueItems as I'm surprised this hasn't been reported before now.

I'll definitely look to fix this in the next version (or feel free to modify DefaultRule.java yourself and submit a PR). I don't see any problem with LinkedHashSet and goal here is always (as far as possible) that it should be possible to roundtrip your json through these types and it shouldn't change. Losing the ordering of arrays is definitely a bug in that respect.

Cheers

@joelittlejohn joelittlejohn added this to the 0.4.1 milestone Mar 5, 2014
@cmaron
Copy link
Contributor Author

cmaron commented Mar 5, 2014

Ah ok, glad to know I wasn't totally crazy! I've cloned the repo and made the change. I will submit a pull request in a few. Thanks!

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

No branches or pull requests

2 participants