Q36 of 40 · Karate

Compare Karate's match DSL to JSON Schema. Which is better for what?

KarateSeniorkaratejson-schemacontract-testingmatchcomparison

Short answer

Short answer: Karate's match is concise and co-located with the test — ideal for fast iteration on API-specific contracts. JSON Schema is verbose but portable: the same file validates in Postman, REST Assured, and any schema validator. Use Karate match for co-located API tests; JSON Schema when the contract is published for consumers across multiple tools or teams.

Detail

Karate's match DSL:

* match response == {
    id:     '#uuid',
    name:   '#string',
    age:    '#? _ >= 0 && _ <= 150',
    tags:   '#[] #string',
    status: '#regex (ACTIVE|INACTIVE)'
  }

Advantages:

  • One line per field — extremely concise
  • Inline with the test — no external file to maintain
  • Rich predicates: #? _ > 0, array markers #[], regex
  • No tooling setup — just write it in the feature file

Limitations:

  • Only works in Karate — you can't share this definition with Postman, REST Assured, or OpenAPI tools
  • No support for JSON Schema standard keywords (allOf, oneOf, $ref, format)
  • Schema definition is per-test, not a single source of truth

JSON Schema:

{
  "type": "object",
  "required": ["id", "name", "status"],
  "properties": {
    "id":   { "type": "string", "format": "uuid" },
    "name": { "type": "string", "minLength": 1 },
    "age":  { "type": "integer", "minimum": 0, "maximum": 150 },
    "tags": { "type": "array", "items": { "type": "string" } }
  },
  "additionalProperties": false
}

Advantages:

  • Portable: used in Postman, REST Assured, AJV (JavaScript), any conformant validator
  • Single source of truth for the contract
  • additionalProperties: false strictly prevents unintended fields
  • Integrates with OpenAPI spec generation tools

Rule of thumb: use Karate match for developer-facing API tests with fast iteration; use JSON Schema when the contract is a team/cross-service artifact.

// EXAMPLE

schema-comparison.feature

Feature: Karate match vs JSON Schema comparison

  Scenario: Using Karate's inline schema (no external file)
    * url 'https://api.example.com'
    Given path '/users/1'
    When  method GET
    Then  status 200
    # Inline — fast to write, easy to update, only works in Karate
    * match response == {
        id:        '#uuid',
        name:      '#string',
        email:     '#regex .+@.+',
        age:       '#? _ >= 18',
        roles:     '#[] #string',
        active:    '#boolean',
        createdAt: '#string'
      }

  Scenario: Using JSON Schema file (portable contract)
    * url 'https://api.example.com'
    Given path '/users/1'
    When  method GET
    Then  status 200
    # Read schema from file — same schema used in REST Assured and Postman
    * def schema = read('classpath:schemas/user-schema.json')
    * match response == '#(schema)'

  # Note: Karate uses '#(^schemaVar)' for schema-reference matching
  # where the schema variable contains type markers or nested schemas

// WHAT INTERVIEWERS LOOK FOR

Concrete articulation of portability as JSON Schema's primary advantage, Karate's conciseness and co-location as its advantage, and the rule of thumb for choosing. Knowing '#(^schema)' syntax for Karate schema references is a depth signal.

// COMMON PITFALL

Saying 'use Karate match for everything because it's simpler'. When the API contract is a shared team artefact consumed by multiple tools, Karate match is the wrong choice — portability trumps conciseness.