Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .JuliaFormatter.toml

This file was deleted.

62 changes: 62 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: CI

on:
push:
branches: [main, master]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main branch doesn't exist

tags: ["*"]
pull_request:
release:

jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version:
- '1' # automatically expands to the latest stable 1.x release of Julia
- 'min'
- 'pre'
os:
- ubuntu-latest
- windows-latest
arch:
- x64
include:
- os: macOS-latest
arch: aarch64
version: 1
- os: ubuntu-latest
arch: x86
version: 1
steps:
- uses: actions/checkout@v6
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v5
with:
files: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
docs:
name: Documentation
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: julia-actions/setup-julia@v2
with:
version: '1'
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-docdeploy@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
45 changes: 45 additions & 0 deletions .github/workflows/CompatHelper.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: CompatHelper
on:
schedule:
- cron: 0 0 * * *
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
CompatHelper:
runs-on: ubuntu-latest
steps:
- name: Check if Julia is already available in the PATH
id: julia_in_path
run: which julia
continue-on-error: true
- name: Install Julia, but only if it is not already available in the PATH
uses: julia-actions/setup-julia@v2
with:
version: '1'
# arch: ${{ runner.arch }}
if: steps.julia_in_path.outcome != 'success'
- name: "Add the General registry via Git"
run: |
import Pkg
ENV["JULIA_PKG_SERVER"] = ""
Pkg.Registry.add("General")
shell: julia --color=yes {0}
- name: "Install CompatHelper"
run: |
import Pkg
name = "CompatHelper"
uuid = "aa819f21-2bde-4658-8897-bab36330d9b7"
version = "3"
Pkg.add(; name, uuid, version)
shell: julia --color=yes {0}
- name: "Run CompatHelper"
run: |
import CompatHelper
CompatHelper.main()
shell: julia --color=yes {0}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }}
# COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }}
3 changes: 2 additions & 1 deletion .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ jobs:
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}
token: ${{ secrets.GITHUB_TOKEN }}
38 changes: 0 additions & 38 deletions .github/workflows/ci.yml

This file was deleted.

31 changes: 0 additions & 31 deletions .github/workflows/format-check.yml

This file was deleted.

6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,9 @@
*.jl.*.cov
*.jl.mem
Manifest.toml
Manifest-*.toml
docs/build/
docs/Manifest.toml
docs/Manifest-*.toml
test/Manifest.toml
test/Manifest-*.toml
4 changes: 2 additions & 2 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The JSONSchema.jl package is licensed under the MIT "Expat" License:

> Copyright (c) 2018: fredo.
> Copyright (c) 2018-2026: fredo, quinnj.
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
Expand All @@ -19,4 +19,4 @@ The JSONSchema.jl package is licensed under the MIT "Expat" License:
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
>

16 changes: 6 additions & 10 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
name = "JSONSchema"
uuid = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
version = "1.5.0"
version = "2.0.0"

[deps]
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
StructUtils = "ec057cc2-7a8d-4b58-b3b3-92acb9f63b42"
URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"

[weakdeps]
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"

[extensions]
JSONSchemaJSON3Ext = "JSON3"

[compat]
JSON = "0.21, 1"
JSON3 = "1"
Downloads = "1"
JSON = "1"
StructUtils = "2"
URIs = "1"
julia = "1.9"
julia = "1.10"
115 changes: 56 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,82 +1,79 @@
# JSONSchema.jl

[![Build Status](https://github.com/fredo-dedup/JSONSchema.jl/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/fredo-dedup/JSONSchema.jl/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/fredo-dedup/JSONSchema.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/fredo-dedup/JSONSchema.jl)
[![CI](https://github.com/JuliaServices/JSONSchema.jl/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/JuliaServices/JSONSchema.jl/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/JuliaServices/JSONSchema.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaServices/JSONSchema.jl)
[![Docs](https://img.shields.io/badge/docs-stable-blue.svg)](https://juliaservices.github.io/JSONSchema.jl/stable)

## Overview

[JSONSchema.jl](https://github.com/fredo-dedup/JSONSchema.jl) is a JSON
validation package for the [Julia](https://julialang.org/) programming language.
Given a [validation schema](http://json-schema.org/specification.html), this
package can verify if a JSON instance meets all the assertions that define a
valid document.
JSONSchema.jl generates JSON Schema (draft-07) from Julia types and validates
instances against those schemas. It also supports validating data against
hand-written JSON Schema objects. Field-level validation rules are provided via
`StructUtils` tags.

This package has been tested with the
> **Upgrading from v1.x?** See the [v2.0 Migration Guide](https://juliaservices.github.io/JSONSchema.jl/stable/migration/) for breaking changes and upgrade instructions.

The test harness is wired to the
[JSON Schema Test Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite)
for draft v4 and v6.
for draft4, draft6, and draft7.

## API
## Installation

Create a `Schema` object by passing a string:
```julia
julia> my_schema = Schema("""{
"properties": {
"foo": {},
"bar": {}
},
"required": ["foo"]
}""")
```
passing a dictionary with the same structure as a schema:
```julia
julia> my_schema = Schema(
Dict(
"properties" => Dict(
"foo" => Dict(),
"bar" => Dict()
),
"required" => ["foo"]
)
)
```
or by passing a parsed JSON file containing the schema:
```julia
julia> my_schema = Schema(JSON.parsefile(filename))
using Pkg
Pkg.add("JSONSchema")
```

Check the validity of a parsed JSON instance by calling `validate` with the JSON
instance `x` to be tested and the `schema`.
## Usage

### Generate a schema from a Julia type

If the validation succeeds, `validate` returns `nothing`:
```julia
julia> document = """{"foo": true}""";
using JSONSchema, StructUtils

julia> data_pass = JSON.parse(document)
Dict{String,Bool} with 1 entry:
"foo" => true
@defaults struct User
id::Int = 0 &(json=(minimum=1,),)
name::String = "" &(json=(minLength=1,),)
email::String = "" &(json=(format="email",),)
end

julia> validate(my_schema, data_pass)
schema = JSONSchema.schema(User)
user = User(1, "Alice", "alice@example.com")
result = JSONSchema.validate(schema, user)

result.is_valid # true
```

If the validation fails, a struct is returned that, when printed, explains the
reason for the failure:
### Validate JSON data against a schema object

```julia
julia> data_fail = Dict("bar" => 12.5)
Dict{String,Float64} with 1 entry:
"bar" => 12.5

julia> validate(my_schema, data_fail)
Validation failed:
path: top-level
instance: Dict("bar"=>12.5)
schema key: required
schema value: ["foo"]
using JSON, JSONSchema

schema = JSONSchema.Schema(JSON.parse("""
{
"type": "object",
"properties": {"foo": {"type": "integer"}},
"required": ["foo"]
}
"""))

data = JSON.parse("""{"foo": 1}""")
JSONSchema.isvalid(schema, data) # true
```

As a short-hand for `validate(schema, x) === nothing`, use
`Base.isvalid(schema, x)`
## Features

- **Schema Generation**: Automatically generate JSON Schema from Julia struct definitions
- **Type-Safe Validation**: Validate Julia instances against generated schemas
- **StructUtils Integration**: Use field tags for validation rules (min/max, patterns, formats, etc.)
- **Composition Support**: `oneOf`, `anyOf`, `allOf`, `not` combinators
- **Reference Support**: `$ref` with `definitions` for complex/recursive types
- **Format Validation**: Built-in validators for `email`, `uri`, `uuid`, `date-time`

## Documentation

Note that if `x` is a `String` in JSON format, you must use `JSON.parse(x)`
before passing to `validate`, that is, JSONSchema operates on the parsed
representation, not on the underlying `String` representation of the JSON data.
See the [documentation](https://juliaservices.github.io/JSONSchema.jl/stable) for:
- Complete API reference
- Validation rules and field tags
- Type mapping reference
- Advanced usage with `$ref` and composition
6 changes: 6 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
JSONSchema = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"

[compat]
Documenter = "1"
Loading
Loading