Skip to content
fge edited this page Jan 19, 2013 · 83 revisions

Note

This page mentions the status of the latest version -- ie, master.

What is supported

All validation aspects of draft v3 and (yet to be adopted) draft v4 are supported, apart from the limitations mentioned below. Supported features include:

  • union types (in type as well as in disallow) (draft v3),
  • full dependencies (ie, property dependencies as well as schema dependencies) (draft v3),
  • "multiple extends" (ie, an array of schemas) (draft v3),
  • tuple/non-tuple validation for arrays,
  • $ref with loop detection,
  • formats (however, see below),
  • enums,
  • $schema detection,
  • draft v3 hyperschema syntax checking support,
  • etc etc.

Limitations

Strict JSON input required

Even though Jackson has the ability to parse many malformed JSON documents, this project asks Jackson to obey the specification to the letter (which is the default behavior anyway):

  • no comments are allowed;
  • strings must be surrounded by double quotes, not single quotes;
  • there is no type inference: "true" is a JSON String, not JSON boolean true; "42" is a string, but 42 is an integer; "null" is... You get the picture.

There is one element differing from the default Jackson behavior: it is asked to use BigDecimal to store decimal numbers instead of double. This is on purpose, see below.

URI dereferencing and id

Natively supported schemes

The API supports extension to allow for any scheme to be registered. Natively, the only supported schemes are resource, http, file, ftp and jar (save for resource, these are all the schemes natively sypported by Java's URL class; support for https has deliberately been omitted).

You can override builtin schemes as well.

id is not trusted by default

This is for security reasons. It is perfectly possible to fetch content at, say, http://foo.bar/baz# and obtain in return a schema which says:

{
    "id": "http://other.site/schema.json"
}

In this kind of situation, the implementation, by default, ignores what id says and takes for granted that the schema's URI is the URI the schema has been fetched from. If you want to trust id nevertheless, you have to tell the implementation to trust it explicitly (by using the .addressingMode() method of JsonSchemaFactory.Builder).

URIs are fetched only once

This can be viewed as a severe limitation, your mileage may vary. At this moment, the implementation caches a URI dereferencing result only once, and keeps the result cached permanently (unless you re-initialize a JsonSchemaFactory).

This limitation is being worked on.

format

This package contains all format attributes defined by draft v3 except for color and style, and all format attributes defined by draft v4.

There are a few extra format attributes which are not in either specification, in a separate project (note: currently lacking behind):

https://github.com/fge/json-schema-formats

Limits on m{in,ax}Length, m{in,ax}Items and m{in,ax}Properties

In a schema, these enforce resp. the minimum/maximum length of a string instance, the minimum/maximum number of items of an array instance, and the minimum/maximum number of members in an object instance. This project is Java, as such the implementation won't accept any values for these which are greater than Integer.MAX_VALUE, that is 2^31 - 1. You don't have JSON documents that big, do you? Well, OK, some modern NoSQL databases may have JSON data as large, if not even larger.

What the draft doesn't say explicitly, but which is implicit, and is implemented

(for some definition of "implicit")

Unknown keywords in schemas

Unknown keywords in schemas are purely and simply ignored. Beware of spelling mistakes!

divisibleBy, exclusiveM{in,ax}imum m{in,ax}imum

Curiously, the draft doesn't say that, for instance, if exclusiveMinimum is present, then minimum MUST also be present. Neither does it say that the number in divisibleBy must not be 0. However, if you have a look at the schema , you see this:

{
    "divisibleBy": {
        "type": "number",
        "minimum": 0,
        "exclusiveMinimum": true,
        "default": 1
    },
    "dependencies": {
        "exclusiveMinimum": "minimum",
        "exclusiveMaximum": "maximum"
    },
    "etc": "etc"
}

Which means what it means. Those are therefore enforced at the syntax checking level.

These ambiguities are lifted in draft v4.

Discussions about some fine points of the draft

Ref resolution failure is a fatal error -- even in disallow

This is an implementation choice. The draft does not say anything about what should happen in the event of a JSON Reference resolution failure: in this implementation, any reference resolution failure is considered a fatal error, and validation stops immediately (and fails).

Numeric instance validation

This applies to integer and number JSON nodes, and therefore to the minimum, maximum and divisibleBy keywords. And especially to the latter.

The first thing to know is that the JSON spec itself does not specify a limit on the precision or scale of numeric instances, and neither does the JSON Schema draft (regardless of the fact that JavaScript limits itself to IEEE 745 floating point numbers -- JSON is not JavaScript).

For this reason, the implementation chooses to use Java's BigDecimal for numeric instance validation, and falls back to long if and only if both the schema keyword value and the instance value fit into this type. For decimal validation however, rounding has to be taken into account... And rounding means rounding errors, which means inaccuracies, which means wreaking havoc to the divisibleBy/multipleOf keyword validations in particular. I don't like inaccuracy, so, for decimal numbers, BigDecimal it is and it will likely remain so for the foreseeable future.

Regex support: ECMA 262, and the real definition of "matching"

The draft is quite clear that regexes should conform to ECMA 262. This rules out java.util.regex entirely (for instance, possessive quantifiers, like in a++, are legal in Java, but are not supported by ECMA 262). The only Java library (that I know of) in existence which is able to process ECMA 262 regexes is Rhino and its Javascript engine. This project uses it for that very reason (and, again, I don't like inaccuracy).

Also, even though the draft only implies it, please note that a regex can match anywhere in the input. Remember this when writing your schemas -- if you want your regex to match the whole input, you must anchor it. This is valid for the pattern keyword, but also for keys in patternProperties. A JSON Schema implementation which doesn't act this way simply does not obey the draft!

Hostname and email validation

These are two of the format specifications defined by the draft (resp. host-name and email).

It is unclear which RFCs are authoritative in describing what is allowed/disallowed. The two RFCs chosen to embody what valid representations are allowed are:

  • host-name: RFC 1034;
  • email: RFC 3522.

RFC 1034 does not require that a domain part exist for a hostname, therefore foo is considered a valid hostname. RC 3522, on the other hand, specifically mentions that an email address should have a domain part after an "at sign" (ie, @). This is my interpretation, and the implementation reflects these choices.

Clone this wiki locally