Contact Us 1-800-596-4880

Reusing Types from a JSON Schema

JSON Schema is a standard that provides a format for the JSON data required for a given application and how to interact with it. Many existing data formats or types are expressed using this standard. In particular, REST APIs described by RAML files are likely to have their types defined in JSON schemas.

To reuse predefined types, you can load the JSON schema into DataWeave to make the types structure available for use in your scripts.

The JSON schema loader parses schemas using the JSON Schema Draft 7ˆ.

Import a Type from a JSON Schema

The following example shows a JSON schema (Person.json) in the resources directory:

JSON Schema (example/schema/Person.json):
{
  "$id": "https://example.com/person.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Person",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string",
      "description": "The person's first name."
    },
    "lastName": {
      "type": "string",
      "description": "The person's last name."
    },
    "age": {
      "description": "Age in years, which must be equal to or greater than zero.",
      "type": "integer",
      "minimum": 0
    }
  },
  "required": ["firstName", "lastName"]
}

The following example shows how to import the type using the JSON schema loader:

DataWeave Script Header:
import * from jsonschema!example::schema::Person

Import Syntax

To import JSON schema types, use the following syntax, where:

  • typeToImport: You can use * alone to import all types defined in the schema or you can import a single type from the schema using, for example, Root. You can also import JSON schema types with a different name, for example, Root as Person, which enables you to reference the type with that name in the script.

  • pathToJsonSchema: To specify the path to the schema file, replace the file separators with :: and remove the .json extension from the file name. For example, if the path to the schema is example/schema/Person.json, use example::schema::Person.

import _typesToImport_ from jsonschema!_pathToJsonSchema_

The following example shows how to import a type:

import * from jsonschema!example::schema::Person

Use Your Types in a DataWeave Script

Including the import directive from the above example in the script header loads all the existing types in the JSON schema. In import * from jsonschema!example::schema::Person, the only existing type is the Root type, specified at the root which describes an Object that can have three properties (firstName, lastName, and age). This is equivalent to declaring the following type in your DataWeave script:

DataWeave Script:
%dw 2.0
type Root = { firstName: String, lastName: String, age?: Number }

Notice that age is the only optional field, as indicated by the ?.

You can use the type to determine if a value follows the structure defined by the JSON schema. The following example outputs the value true because the object contains the required fields, firstName and lastName:

DataWeave Script:
%dw 2.0
import * from jsonschema!jsonschema!example::schema::Person
---
{
 firstName: "John",
 lastName: "Doe"
} is Root
Output:
"true"

The following example outputs the value false because the object doesn’t contain the required fields, firstName and lastName:

DataWeave Script:
%dw 2.0
import * from jsonschema!jsonschema!example::schema::Person
---
{
 firstName: "John",
 age: 20
} is Root
Output:
"false"

Use Definitions inside Schemas

DataWave loads the definitions inside JSON schemas when the module is imported:

JSON Schema (example/schema/Account.json):
{
 "$schema": "http://json-schema.org/draft-04/schema#",
 "definitions": {
   "address": {
     "type": "object",
     "properties": {
       "street_address": {
         "type": "string"
       },
       "city": {
         "type": "string"
       },
       "state": {
         "type": "string"
       }
     },
     "required": [
       "street_address",
       "city",
       "state"
     ]
   },
   "person": {
     "type": "object",
     "properties": {
       "firstName": {
         "type": "string",
         "description": "The person's first name."
       },
       "lastName": {
         "type": "string",
         "description": "The person's last name."
       },
       "age": {
         "description": "Age in years, which must be equal to or greater than zero.",
         "type": "integer",
         "minimum": 0
       }
     },
     "required": [
       "firstName",
       "lastName"
     ]
   }
 },
 "type": "object",
 "properties": {
   "person": {
     "$ref": "#/definitions/person"
   },
   "address": {
     "$ref": "#/definitions/address"
   }
 }
}

You can import the types from that schema with the following directive:

import * from jsonschema!example::schema::Account

The types defined in the schema have the same effect as declaring the following types:

type Root = { address?: address, person?: person }

type address = { street_address: String, city: String, state: String }

type person = { firstName: String, lastName: String, age?: Number }

Use the import directive to import a single type from the schema:

import address from jsonschema!example::schema::Account

To avoid type-name collision, you can use the as keyword to change the imported type name to another name:

import address as Account_Address from jsonschema!example::schema::Account

Facilitate Usage with Pattern Matching

You can use the types imported from the JSON schemas to take a specific action when an input is of a certain type. These imported types are useful for pattern matching.

The following example outputs the value person because the object is importing that type definition:

DataWeave Script:
%dw 2.0
import * from jsonschema!example::schema::Account
---
{
 firstName: "John",
 lastName: "Doe"
} match {
case is person -> "PERSON"
case is address -> "ADDRESS"
else -> "NO TYPE MATCHED"
}
Output:
"PERSON"

The following example outputs the value address because the object is importing that type definition:

DataWeave Script:
%dw 2.0
import * from jsonschema!example::schema::Account
---
{
 street_address: "742 Evergreen Terrace",
 city: "Gotham",
 State: "OH"
} match {
case is person -> "PERSON"
case is address -> "ADDRESS"
else -> "NO TYPE MATCHED"
}
Output:
"ADDRESS"

Built-in JSON Schema Types

DataWeave supports the following JSON schema types transformed into DataWeave types:

JSON Schema Type DataWeave Type

number

Number

integer

Number

string

String

boolean

Boolean

array

Array

enums

Union

null

Null

object

Object

Limitations

  • DataWeave doesn’t support formats on JSON schema string types and transforms these types to String without any validation or restriction.

  • DataWeave doesn’t support restrictions on number types such as maximums or minimums and transforms these types to Number without any validation or restriction.

  • DataWeave doesn’t support patterns.

Object types

DataWeave marks non-required properties in JSON Schema object types as optional properties in the DataWeave Object type.

The following example outputs a DataWeave type:

JSON schema:
{
  "type": "object",
  "properties": {
    "name":      { "type": "string" },
    "email":     { "type": "string" },
    "address":   { "type": "string" },
    "telephone": { "type": "string" }
  },
  "required": ["name", "email"]
}
Output:
%dw 2.0
type Root = { address?: String, name: String, telephone?: String, email: String }

If additional properties are allowed, DataWeave produces an open Object definition.

The following example outputs a DataWeave type:

JSON schema:
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "number":      { "type": "number" },
    "street_name": { "type": "string" },
    "street_type": { "type": "string",
      "enum": ["Street", "Avenue", "Boulevard"]
    }
  },
  "required": ["number"],
  "additionalProperties": true
}
Output:
%dw 2.0
type Root = { number: Number, street_type?: "Street" | "Avenue" | "Boulevard", street_name?: String }

If, on the contrary, additional properties aren’t allowed, DataWeave produces a closed Object definition.

The following example outputs a DataWeave type:

JSON schema:
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "number":      { "type": "number" },
    "street_name": { "type": "string" },
    "street_type": { "type": "string",
      "enum": ["Street", "Avenue", "Boulevard"]
    }
  },
  "required": ["number"],
  "additionalProperties": false
}
Output:
%dw 2.0
type Root = {| number: Number, street_type?: "Street" | "Avenue" | "Boulevard", street_name?: String |}

Built-in JSON Schema Support for Subschema Keywords

Using subschema keywords in JSON schema produces complex types based on the provided subschemas.

JSON Schema Keyword DataWeave Type

allOf

Intersection

anyOf

Union

oneOf

Union

The following example outputs a DataWeave type: .JSON schema:

{
  "anyOf": [
    { "type": "string" },
    { "type": "number" }
  ]
}
Output:
%dw 2.0
type Root = (String | Number)