Skip to content

Commit

Permalink
Merge branch 'schema'
Browse files Browse the repository at this point in the history
  • Loading branch information
mtmorgan committed Apr 9, 2024
2 parents 0cc9603 + f5af012 commit 3b3a042
Show file tree
Hide file tree
Showing 178 changed files with 11,864 additions and 5,247 deletions.
8 changes: 4 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: rjsoncons
Title: 'C++' Header-Only 'jsoncons' Library for 'JSON' Queries
Version: 1.2.0.9704
Version: 1.2.0.9800
Authors@R: c(
person(
"Martin", "Morgan", role = c("aut", "cre"),
Expand All @@ -25,9 +25,9 @@ Description: The 'jsoncons'
object-of-arrays, for easy import into 'R') 'JSON' or 'NDJSON'
strings or files using 'JSONpointer', 'JSONpath' or 'JMESpath'
expressions. The package also supports 'JSON' patch for
conveniently editing JSON documents. The 'jsoncons' library is
easily linked to other packages for direct access to 'C++'
functionality.
conveniently editing JSON documents, and 'JSON' schema for
validation. The 'jsoncons' library is easily linked to other
packages for direct access to 'C++' functionality.
Imports: cli
Suggests: jsonlite, tibble, tinytest, BiocStyle, knitr, rmarkdown
LinkingTo: cpp11, cli
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export(j_patch_op)
export(j_path_type)
export(j_pivot)
export(j_query)
export(j_schema_is_valid)
export(j_schema_validate)
export(jmespath)
export(jsonpath)
export(jsonpointer)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# rjsoncons 1.3.0

- (1.2.0.9800) add JSON schema support with `j_schema_is_valid()`,
`j_schema_validate()`.
- (1.2.0.9704) add key and value search with `j_flatten()`,
`j_find_*()` supporting JSONpointer and JSONpath.
- (1.2.0.9602) compile on Ubuntu 18.04
Expand Down
8 changes: 8 additions & 0 deletions R/cpp11.R
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,11 @@ cpp_j_pivot <- function(data, data_type, object_names, as, path, path_type) {
cpp_j_pivot_con <- function(con, data_type, object_names, as, path, path_type, n_records, verbose) {
.Call(`_rjsoncons_cpp_j_pivot_con`, con, data_type, object_names, as, path, path_type, n_records, verbose)
}

cpp_j_schema_is_valid <- function(data, schema) {
.Call(`_rjsoncons_cpp_j_schema_is_valid`, data, schema)
}

cpp_j_schema_validate <- function(data, schema, as) {
.Call(`_rjsoncons_cpp_j_schema_validate`, data, schema, as)
}
2 changes: 1 addition & 1 deletion R/rquerypivot.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#' files.
#'
#' @param data_type character(1) type of `data`; one of `"json"`,
#' `"ndjson"`. Inferred from `data` using `j_data_type()`.
#' `"ndjson"`, or a value returned by `j_data_type()`.
#'
#' @param path_type character(1) type of `path`; one of
#' `"JSONpointer"`, `"JSONpath"`, `"JMESpath"`. Inferred from
Expand Down
121 changes: 121 additions & 0 deletions R/schema.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
do_j_schema <-
function(fun, data, schema, ..., data_type, schema_type)
{
if (.is_j_data_type_connection(data_type)) {
data <- .as_unopened_connection(data, data_type)
open(data, "rb")
on.exit(close(data))
}
if (.is_j_data_type_connection(schema_type)) {
schema <- .as_unopened_connection(schema, schema_type)
open(schema, "rb")
on.exit(close(schema))
}
fun(data, schema, ...)
}

#' @rdname schema
#'
#' @title Validate JSON documents against JSON Schema
#'
#' @description `j_schema_is_vaild()` uses JSON Schema
#' <https://json-schema.org/> to validate JSON 'data' according to
#' 'schema'.
#'
#' @param data JSON character vector, file, or URL defining document
#' to be valdiated. NDJSON data and schema are not supported.
#'
#' @param schema JSON character vector, file, or URL defining the
#' schema aganist which `data` will be validated.
#'
#' @param ... passed to `jsonlite::toJSON` when `data` is not
#' character-valued.
#'
#' @param data_type character(1) type of `data`; one of `"json"` or a
#' value returned by `j_data_type()`; schema validation does not
#' support `"ndjson"` data.
#'
#' @param schema_type character(1) type of `schema`; see `data_type`.
#'
#' @examples
#' ## Allowable `data_type=` and `schema_type` -- excludes 'ndjson'
#' j_data_type() |>
#' Filter(\(type) !"ndjson" %in% type, x = _) |>
#' str()
#' ## compare JSON patch to specification. 'op' key should have value
#' ## 'add'; 'paths' key should be key 'path'
#' ## schema <- "https://json.schemastore.org/json-patch.json"
#' schema <- system.file(package = "rjsoncons", "extdata", "json-patch.json")
#' op <- '[{
#' "op": "adds", "paths": "/biscuits/1",
#' "value": { "name": "Ginger Nut" }
#' }]'
#' j_schema_is_valid(op, schema)
#'
#' @export

j_schema_is_valid <-
function(
data, schema, ...,
data_type = j_data_type(data), schema_type = j_data_type(schema)
)
{
stopifnot(
## don't support ndjson (yet?)
data_type[[1]] %in% c("json", "R"),
schema_type[[1]] %in% c("json", "R")
)

data <- .as_json_string(data, data_type, ...)
schema <- .as_json_string(schema, schema_type, ...)
do_j_schema(
cpp_j_schema_is_valid, data, schema,
data_type = data_type, schema_type = schema_type
)
}

#' @rdname schema
#'
#' @description `j_schema_validate()` returns a JSON or *R* object,
#' data.frame, or tibble, describing how `data` does not conform
#' to `schema`. See the "Using 'jsoncons' in R" vignette for help
#' interpreting validation results.
#'
#' @param as for `j_schema_validate()`, one of `"string"`, `"R"`,
#' `"data.frame"`, `"tibble"`, or `"details"`, to determine the
#' representation of the return value.
#'
#' @examples
#' j_schema_validate(op, schema, as = "details")
#'
#' @export
j_schema_validate <-
function(
data, schema, as = "string", ...,
data_type = j_data_type(data), schema_type = j_data_type(schema)
)
{
stopifnot(
## don't support ndjson (yet?)
data_type[[1]] %in% c("json", "R"),
schema_type[[1]] %in% c("json", "R"),
as %in% c("string", "R", "data.frame", "tibble", "details")
)

data <- .as_json_string(data, data_type, ...)
schema <- .as_json_string(schema, schema_type, ...)
as0 <- ifelse(identical(as, "R"), "R", "string")
result <- do_j_schema(
cpp_j_schema_validate, data, schema, as = as0,
data_type = data_type, schema_type = schema_type
)

switch(
as,
string = result,
R = result,
data.frame =,
tibble = j_pivot(result, as = as),
details = j_pivot(result, "[].details[]", as = "tibble")
)
}
7 changes: 5 additions & 2 deletions R/version.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ NULL
#' library in use.
#'
#' @return `version()` returns a character(1) major.minor.patch
#' version string .
#' version string, possibly with git hash for between-release
#' version.
#'
#' @examples
#' version()
#'
#' @export
version <- cpp_version
version <- function() {
paste(cpp_version(), "[+57967655d]")
}
65 changes: 65 additions & 0 deletions inst/extdata/json-patch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"path": {
"description": "A JSON Pointer path.",
"type": "string"
}
},
"id": "https://json.schemastore.org/json-patch.json",
"items": {
"oneOf": [
{
"additionalProperties": false,
"required": ["value", "op", "path"],
"properties": {
"path": {
"$ref": "#/definitions/path"
},
"op": {
"description": "The operation to perform.",
"type": "string",
"enum": ["add", "replace", "test"]
},
"value": {
"description": "The value to add, replace or test."
}
}
},
{
"additionalProperties": false,
"required": ["op", "path"],
"properties": {
"path": {
"$ref": "#/definitions/path"
},
"op": {
"description": "The operation to perform.",
"type": "string",
"enum": ["remove"]
}
}
},
{
"additionalProperties": false,
"required": ["from", "op", "path"],
"properties": {
"path": {
"$ref": "#/definitions/path"
},
"op": {
"description": "The operation to perform.",
"type": "string",
"enum": ["move", "copy"]
},
"from": {
"$ref": "#/definitions/path",
"description": "A JSON Pointer path pointing to the location to move/copy from."
}
}
}
]
},
"title": "JSON schema for JSONPatch files",
"type": "array"
}
2 changes: 1 addition & 1 deletion inst/include/jsoncons/allocator_holder.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013-2023 Daniel Parker
// Copyright 2013-2024 Daniel Parker
// Distributed under the Boost license, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Expand Down
2 changes: 1 addition & 1 deletion inst/include/jsoncons/allocator_set.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013-2023 Daniel Parker
// Copyright 2013-2024 Daniel Parker
// Distributed under the Boost license, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Expand Down
Loading

0 comments on commit 3b3a042

Please sign in to comment.