JSON Schema
json-schema.org
json-schema.org
I don't have any relevant json extensions, but VS Code started auto-suggesting values for options (e.g. a drop down for whether the chart type is a 'bar', 'line', etc.) and pointing our mistakes like 'the size should be an integer not a percent'.
This was the lightbulb moment for me - as if by magic, my code editor was double checking my json document was valid and helping me write it. Amazing, and super useful.
It took me a while to work out how it was doing it, but all vega lite examples start with the magic:
"$schema": "https://vega.github.io/schema/vega-lite/v2.json".
Make my tools do the grunt-work for me, thanks, so I can focus on the actual problem domain.
In my experience, those tend to be either json, yml or plain terminal args regardless of the fact that the language is typed or not.
Am I missing something?
I agree, with the caveat that sometimes you need an escape valve.
Basically I want static typing 99% of the time and I don't want guff from the compiler (or fanboys) in that 1%.
They’re supported by all general purpose programming languages because we — as developers — are smarter than the compiler.
2. Not “all general purpose programming languages” support exceptions. To name a few that don’t: C, Rust, Go.
Unfortunately it doesn't perform validation, nor implement all validation annotations - but it definitely helped me get started.
For example this:
{
"title": "Person",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"required": ["firstName", "lastName"]
}
can be expressed like this: interface Person {
firstName: string;
lastName: string;
age?: number; // Age in years
}
I can see that there are additional constraints expressible, such as the fact that age has to be an integer and has a minimum value. However those could all conceivably comprise a superset of TypeScript's interface definitions. JSON Schema just feels to me like XML Schema all over again.Why? It's not a particularly difficult task to write a parser that could convert between the two representations. The TypeScript compiler even provides an API that lets you access its AST.
At my job, we're currently running JS on the back-end and TS on the front-end. JSON-Schema can be used in both. We're also rebuilding our core functionality in Elixir, and guess what, JSON Schema works there, too, out of the box.
- it can do checks at runtime (to validate untrusted input, for example)
- there are libraries for many other programming languages
- it can express constraints on values as well as on types (size of arrays, string regex matching, integer value ranges, ...)
The reason for having the schema are that they are language agnostic and there is wide tool support. For example, vscode supports autocomplete and tooltips when you use json schema.
Additionally, what you've chosen is a very simple example, and even in that case you're having trouble correctly mapping the types to what is expected. What about a slightly more complex one[1]?
{
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"properties": {
"/": {}
},
"patternProperties": {
"^(/[^/]+)+$": {}
},
"additionalProperties": false,
"required": [ "/" ]
}
1: http://json-schema.org/example2.htmlOf course there are use cases that JSON Schema works better for (eg most other replies you got) but I fully agree that TypeScript type definitions are a great way to specify the structure of JSON data.
To make it feel more language-agnostic, you could consider using type aliases instead:
type Person = {
firstName: string,
lastName: string,
age?: number // Age in years
}
This is equivalent to the interface you described, but potentially less confusing to readers who don't know what an "interface" is (eg because they mostly used Ruby or C++). You don't even need to tell people that it's TypeScript - this could be a perfectly sensible schema language for JSON. A bit like what RELAX NG[0] is for XML.At my company we actually use typescript-json-schema[1] so we can specify the structure of our API payloads in TS instead of JSON Schema and still benefit from JSON Schema's better tool support.
Also you can't really hand a third party a typescript interface and tell them to conform with that.
And finally, I would imagine a good schema could enforce more things like the length of identifiers, whether a number can be negative, etc.
That's mostly true, but some projects exist that allow a subset of interfaces to be used at runtime:
- https://github.com/gcanti/io-ts
- https://github.com/fabiandev/ts-runtime
- https://github.com/codemix/flow-runtime
- Or just manual assertions: https://gist.github.com/JohnWeisz/beb7b4dadc512be30ce6c7c1e4...
JSON-schema provides a type assertion system.
Both serve as type documentation systems.
TS says "if you create objects in my world, I will use my type system to verify that you're creating the right kind of objects, and you can look up their definitions to see what's in them". JSON-schema says "if you give me external, un-annotated objects, I can tell you whether they comply with a type definition, and you can look at that definition to see what's in them".
TS has a limited assertion facility, but it's not nearly as capable as JSON-schema. Projects like io-ts (https://github.com/gcanti/io-ts) add more functionality to those assertions, but they're still much less easy to use, in my opinion, than JSON-schema for this purpose. If you're using TS types to assert, though, you can definitely describe more complex constraints, so it may make sense as an alternative to JSON-schema for some people.
As others have pointed out, JSON-schema is also much easier to use on non-TypeScript platforms than TS assertions, which, even if you use an assertion library like io-ts, will still be limited in use to JavaScript (and JS-to-$other_language runtimes).
Would you expand on how dependent type systems are relevant to the differences between TypeScript/JSON-Schema, or how the use of a DTS could help ameliorate the issues people have in those areas?
Json-schema is useful for describing JSON data structures in JSON, so you can bring a codegen and generate corresponding structures in your language, or perform some payload validation at an API gateway; and many higher-level API specs -- like OpenAPI/Swagger -- make use of Json-schema underneath.
However, I'm not sure I fully understand why they branched out into also becoming a hypermedia description language [2] when there's already half a dozen others in this space [3], and reading some of the discussion about this [4] makes my head hurt.
[1] http://json-schema.org/specification.html [2] http://json-schema.org/latest/json-schema-hypermedia.html [3] https://sookocheff.com/post/api/on-choosing-a-hypermedia-for... [4] https://github.com/json-schema-org/json-schema-spec/issues/4...
Anyway, I'm really glad I didn't try to roll my own thing for schema validation. Alpaca is insanely powerful, and it would have taken me weeks or months to build the online forms from scratch.
[2] https://github.com/ruby-json-schema/json-schema
ruby-json-schema has worked out quite well, we added a custom schema reader so that we could generate enums dynamically based on records in the database via custom refs eg. app://schemas/organizations?type_eq=education&tags=one, any of these internal refs are inlined at the API layer.
One issue we did run into with ruby-json-schema, is the schema caching is not thread safe. We opted to clear the cache after each validation, this ended up causing race-condition issues. In the end we had to use a mutex on write and cache the validation result (not ideal, but our app isn't that write heavy).
[1] https://github.com/mozilla-services/react-jsonschema-form
I personally think it's great. The faster the ecosystem is reinvented the sooner we can stop wasting our lives reading it.
This just serves to provide a way to say "yes, we can have strongly typed schemas as well as our nice succinct format" to those who need it.
JSON-schema solves many of the validation issues of JSON in the absence of an XSD-for-JSON solution, to allow message processing and other validation assertions. From that perspective it's 'duplicated effort', but only to the extent that JSON messaging applications are maturing to the point they need the kinds of guarantees that were so clear during the development of XML/SGML. It's a whole different language supporting a range of JSON-powered clients that don't necessarily require transformation support or other guarantees.
This is about JSONs ecosystem maturing to the baseline, not about reinventing the wheel :)
Generate useful docs. Easy to read to get a handle on data structure. Also can be used as runtime contracts. somewhat similar but v. limited compared to Racket Contracts and Clojure spec.
Not to mention super tooling for interacting with schema (like XMLSpy)
In conclusion, having schemas for data structures(especially at boundaries) is absolutely necessary to maintain control & visibility over data.
Data schemas are the first step in powering transformations, which is where most of the Enterprise is bound up.
I could spend time addressing each issue raised here, but that could take some time...
@niftich We've (the new authorship) actually been working on JSON Schema since late 2014!
If you're using JSON Schema, or are interetested in finding out more, we DO now have a slack server; invite link at the bottom of json-schema.org. Come talk with us.
We're looking for companies who are using it in production to weigh in on new developments and releases. Our current release plan means we will have an RC with time for feedback. We want to hear your issues, comments, and suggestions!
One common problem at current is the level of support. Because draf-4 has been around for a LONG time now, it became the defacto standard, and has the most support. Developers come along and use an older library which only supports draft-4, but want to use new functionaltiy found in draft-7. Many implementations support draft-7, and some even implement new functionaltiy before it's finalised. SO remember to check which version of JSON Schema the library you're using supports.
HyperSchema already exsisted at that point, so we inheirted it. It focuses on providing specification for correct HTTP usage and HATEOAS driven APIs, where as other higher level API specification languages allow you to describe any type of API.
It looks like a good number of you have good questions, ideas, or issues. Thanks for all those replying supporting JSON Schema and those showing a balanced viewpoint.
Come chat with us!
It's not particularly friendly to the maintainer compared to switching to a statically typed language, but it would have taken a fair bit more effort to wire that up without this.
In another much more generic customer facing API I instead used a custom schema, as I needed to do other things that would not have been possible in it like embedding the API documentation in the schema so the front-end could display help on-the-fly and use the schema to dynamically generate forms. The advantage was also that being fully in control of the syntax I could create ways to express constraints like field X is valid only in searches, field Y is valid only in PUT/PATCH but not POST, etc. etc.
This said especially for straightforward APIs I feel JSON schemas are quite useful, being able to have a single source of truth on what your messages look like that you can share with front-end, back-end and customers is quite powerful. One thing is though that validation errors are not very user-friendly unfortunately. This was all around draft-04 time IIRC.
1. if/then/else which was added in Draft-07.
2. Custom errors. For Node, I use ajv and ajv-errors.
With the combination of if/then/else and custom errors, I have found that I can always return a single, useful error to the API user regardless of the schema complexity.
The only thing that is counter-productive is the different schema iterations; at the time v3 and v4 have been different in some key areas. Haven't looked into v7 yet, but I hope its not "breaking as much" as v3 vs v4 did.
See also my comment here: https://news.ycombinator.com/item?id=16407707
Incoming data -> is it a valid messages at all? -> if it is a message of type x, hand it over to class X -> if it is a message of type y, hand it over to class Y -> etc
I found that to be a very easy way to setup a general-purpose processing pipeline.
A request comes in and the wrapper checks for a schema. if it is not a GET request and one does not exist it errors out even before the method is called. If one exists, the schema is validated automatically. If the target method is called, you can be safe assuming that the input is valid (in terms of type and does it exist or not).
Same goes for output. Server will error out before it lets incorrect output be returned to the user. Great way to present what the application accepts to a developer. This is what it will accept and return, because this is what we use to validate input and output!
We (reluctantly) went with XML for an external facing B2B API, because JSON schema was stuck in draft and did not seem to be in widespread use. JSON without schemas would have been a nightmare.
I wouldn't say JSON without schemas is necessarily too problematic, I've used that a few years ago. Now I prefer JSON Schema for extra confidence and more convenience in pointing out problems.
The UI is okay; however, we've had two big downsides:
* The UI needs to be able to fetch the JSON schema document from the API; that means that it needs to correctly respond with CORS headers if you host the web interface on a separate domain. (We do, s.t. each API service doesn't need to repeat the mundane task of hosting it and keeping it up to date.)
* The schema needs to be useful. Far too often, people will document an API endpoint as taking "JSON" and returning "JSON"; this is true and correct, but not helpful. What keys exist? What are the valid values for those keys? etc. The author of the schema needs to take the time and thoroughness to document the API, and all too often either they do not (the workmanship is sloppy) or they can not (management provided deadlines that were too tight to get the job done right).
Neither of those are really problems with JSON-schema per se. You also don't need JSON schema to document a JSON API: you can always do so with prose, by using the type system of a language your devs are familiar with and providing a set of rules to map those structures/types to JSON object, etc.
My biggest nit with JSON schema: it's painful for humans to interpret. (And we actually do it in Swagger, which is in YAML, so it's slightly easier to parse and we get comments. But it's considerably verbose compared to most type systems; the upside is that it can encode more information such as descriptions, or valid ranges/values if the raw type like "number" or "string" doesn't suffice.)
Using JSON Schema with Python to validate JSON data:
https://jugad2.blogspot.in/2015/12/using-json-schema-with-py...
You'll love this talk by Robert C. Martin ("The Future Of Programming"): https://www.youtube.com/watch?v=ecIWPzGEbFc
While I agree that tech should reevaluate its sisyphean upgrade treadmill, I'm not sure how that relates here.
Mu. Neither JSON nor XML should be used, because S-expressions are good enough, and more attractive to boot.
my 286 was more responsive and would compile my games faster than most other things on my i7. It is plain insanity.
Did you have other technologies in mind or were you also thinking of xsd?