Describing JSON Schema in Dhall


#1

Hi all!

I’d like describing a json schema in Dhall. E.g, instead of the following error prone YAML:

type: object
additionalProperties: false
properties:
  foo: 
    type: string   
  bar: 
    type: int   
required:
  - foo

I could write something like (which would be more “type safe”):

object 
  [ { required = True , name ="foo", schema = string }
  , { required = False, name = "bar", schema = int } 
  ]

I know there are some topics discussing about generating Dhall from JSON Schema (or reverse) but this is not what I want. It seems what I want is way more simple and can live entirely in Dhall code.

Is there any lib for describing a json schema in Dhall?


#2

I don’t know of a library. But this is essentially what I did as part an internal project, though I’ve only added functions to produce the parts of a JSON schema that we need.

e.g. here’s the dhall for producing the type part of a schema:

{-|
Defines the available JSON schema [type keywords](https://json-schema.org/understanding-json-schema/reference/type.html#type).
-}
let JSONSchemaType =
      < array | boolean | integer | null | number | object | string >

let type = { type : Text }

let makeJSONSchema =
      λ(x : JSONSchemaType) →
        merge
          { object = { type = "object" } : type
          , array = { type = "array" } : type
          , string = { type = "string" } : type
          , boolean = { type = "boolean" } : type
          , null = { type = "null" } : type
          , number = { type = "number" } : type
          , integer = { type = "integer" } : type
          }
          x

let example0 =
      assert : makeJSONSchema JSONSchemaType.string ≡ { type = "string" }

in  { Type = JSONSchemaType
    , SchemaType = type
    , array = makeJSONSchema JSONSchemaType.array
    , boolean = makeJSONSchema JSONSchemaType.boolean
    , integer = makeJSONSchema JSONSchemaType.integer
    , null = makeJSONSchema JSONSchemaType.null
    , number = makeJSONSchema JSONSchemaType.number
    , object = makeJSONSchema JSONSchemaType.object
    , string = makeJSONSchema JSONSchemaType.string
    }

Here’s the code for oneOf:

{-|
Defines the JSON schema [oneOf](https://json-schema.org/understanding-json-schema/reference/combining.html#oneof)
object and a function for producing valid one of objects.
-}
let jsonType = ./jsonType.dhall

let OneOf = { oneOf : List jsonType.SchemaType }

in  { SchemaType = OneOf
    , makeJSONSchema = λ(x : List jsonType.SchemaType) → { oneOf = x } : OneOf
    }

And so on for various schema components we needed. A schema can be stitched together from these pieces. I don’t think this approach is ideal, but it works for now.


#3

Thanks for the answer.

How do you deal with array items and object properties? What would be the code for describing:

{  "foo" : { "bar": [1,2,3] } }

Seems like we need some recursive type (feasible, but if I can avoid the pain… :smile: )


#4

Since a JSON schema is itself JSON, you could use Prelude.JSON.Type as the recursive type for building one


#5

Seems like we need some recursive type (feasible, but if I can avoid the pain… :smile: )

I was able to avoid that since the schema we’re describing is relatively simple.

But I did the early stages, I thought we might need such recursion and my thought was the same as @Gabriel439’s suggestion.