From e689e3d34f6410f48e68f6312d6b2701f8a7a60d Mon Sep 17 00:00:00 2001 From: Michael Mior Date: Tue, 27 Aug 2024 13:11:15 -0400 Subject: [PATCH 1/3] Use multiple instances in ajv implementation --- Makefile | 6 +-- implementations/ajv/{main.js => main.mjs} | 28 ++++++++++---- schemas/example/instance.json | 46 ----------------------- schemas/example/instances.json | 1 + 4 files changed, 24 insertions(+), 57 deletions(-) rename implementations/ajv/{main.js => main.mjs} (54%) delete mode 100644 schemas/example/instance.json create mode 100644 schemas/example/instances.json diff --git a/Makefile b/Makefile index 3d81362..46a269b 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ dist/results/jsontoolkit/%: \ implementations/jsontoolkit/CMakeLists.txt \ implementations/jsontoolkit/main.cc \ schemas/%/schema.json \ - schemas/%/instance.json \ + schemas/%/instances.json \ | dist/results/jsontoolkit dist/temp/jsontoolkit [ -d $(word 2,$|)/repo ] && git -C $(word 2,$|)/repo pull || git clone https://github.com/sourcemeta/jsontoolkit $(word 2,$|)/repo cmake -S $(dir $<) -B $(word 2,$|)/build -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_SHARED_LIBS:BOOL=OFF @@ -34,9 +34,9 @@ dist/results/jsontoolkit/%: \ # AJV dist/results/ajv/%: \ - implementations/ajv/main.js \ + implementations/ajv/main.mjs \ schemas/%/schema.json \ - schemas/%/instance.json \ + schemas/%/instances.json \ node_modules \ | dist/results/ajv node $< $(word 2,$^) $(word 3,$^) > $@ diff --git a/implementations/ajv/main.js b/implementations/ajv/main.mjs similarity index 54% rename from implementations/ajv/main.js rename to implementations/ajv/main.mjs index aa29fad..fbf9ddb 100644 --- a/implementations/ajv/main.js +++ b/implementations/ajv/main.mjs @@ -1,7 +1,8 @@ -const Ajv = require('ajv'); -const draft4schema = require('ajv/lib/refs/json-schema-draft-04.json'); -const fs = require('fs'); -const { performance } = require('perf_hooks'); +import Ajv from 'ajv'; +import draft4schema from 'ajv/lib/refs/json-schema-draft-04.json' assert { type: 'json' }; +import fs from 'fs'; +import readline from 'readline'; +import { performance } from 'perf_hooks'; function readJSONFile(filePath) { try { @@ -12,7 +13,16 @@ function readJSONFile(filePath) { } } -function validateSchema(schemaPath, instancePath) { +async function* readJSONLines(filePath) { + const rl = readline.createInterface({ + input: fs.createReadStream(filePath), + }); + for await (const line of rl) { + yield JSON.parse(line); + } +} + +async function validateSchema(schemaPath, instancePath) { const schema = readJSONFile(schemaPath); const instance = readJSONFile(instancePath); @@ -26,8 +36,10 @@ function validateSchema(schemaPath, instancePath) { const validate = ajv.compile(schema); const startTime = performance.now(); - if (!validate(instance)) { - process.exit(1); + for await (const instance of readJSONLines(instancePath)) { + if (!validate(instance)) { + process.exit(1); + } } const endTime = performance.now(); @@ -43,4 +55,4 @@ if (process.argv.length !== 4) { const schemaPath = process.argv[2]; const instancePath = process.argv[3]; -validateSchema(schemaPath, instancePath); +await validateSchema(schemaPath, instancePath); diff --git a/schemas/example/instance.json b/schemas/example/instance.json deleted file mode 100644 index 6f452cb..0000000 --- a/schemas/example/instance.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "storeName": "TechGadgets Online", - "lastUpdated": "2024-08-27T14:30:00Z", - "categories": ["Electronics", "Accessories", "Smart Home"], - "products": [ - { - "id": "PRD-EL-000001", - "name": "SuperSound Wireless Headphones", - "description": "High-quality wireless headphones with noise-cancelling technology.", - "price": 129.99, - "category": "Electronics", - "tags": ["audio", "wireless", "headphones"], - "inStock": true, - "rating": { - "average": 4.7, - "count": 253 - } - }, - { - "id": "PRD-AC-000015", - "name": "DuraPro Phone Case", - "description": "Rugged phone case for ultimate protection.", - "price": 24.95, - "category": "Accessories", - "tags": ["phone", "protection"], - "inStock": true, - "rating": { - "average": 4.2, - "count": 187 - } - }, - { - "id": "PRD-SH-000008", - "name": "SmartHome Hub", - "description": "Central control unit for your smart home devices.", - "price": 79.99, - "category": "Smart Home", - "tags": ["iot", "control", "automation"], - "inStock": false, - "rating": { - "average": 4.5, - "count": 42 - } - } - ] -} diff --git a/schemas/example/instances.json b/schemas/example/instances.json new file mode 100644 index 0000000..a754a84 --- /dev/null +++ b/schemas/example/instances.json @@ -0,0 +1 @@ +{"storeName":"TechGadgets Online","lastUpdated":"2024-08-27T14:30:00Z","categories":["Electronics","Accessories","Smart Home"],"products":[{"id":"PRD-EL-000001","name":"SuperSound Wireless Headphones","description":"High-quality wireless headphones with noise-cancelling technology.","price":129.99,"category":"Electronics","tags":["audio","wireless","headphones"],"inStock":true,"rating":{"average":4.7,"count":253}},{"id":"PRD-AC-000015","name":"DuraPro Phone Case","description":"Rugged phone case for ultimate protection.","price":24.95,"category":"Accessories","tags":["phone","protection"],"inStock":true,"rating":{"average":4.2,"count":187}},{"id":"PRD-SH-000008","name":"SmartHome Hub","description":"Central control unit for your smart home devices.","price":79.99,"category":"Smart Home","tags":["iot","control","automation"],"inStock":false,"rating":{"average":4.5,"count":42}}]} From 213543e0f0c38afbdf9435d5c5bcefd0bca4eecc Mon Sep 17 00:00:00 2001 From: Michael Mior Date: Tue, 27 Aug 2024 13:32:05 -0400 Subject: [PATCH 2/3] Rename instances.json to instances.jsonl --- Makefile | 4 ++-- implementations/jsontoolkit/main.cc | 2 +- schemas/example/{instances.json => instances.jsonl} | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename schemas/example/{instances.json => instances.jsonl} (100%) diff --git a/Makefile b/Makefile index 46a269b..dd79d73 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ dist/results/jsontoolkit/%: \ implementations/jsontoolkit/CMakeLists.txt \ implementations/jsontoolkit/main.cc \ schemas/%/schema.json \ - schemas/%/instances.json \ + schemas/%/instances.jsonl \ | dist/results/jsontoolkit dist/temp/jsontoolkit [ -d $(word 2,$|)/repo ] && git -C $(word 2,$|)/repo pull || git clone https://github.com/sourcemeta/jsontoolkit $(word 2,$|)/repo cmake -S $(dir $<) -B $(word 2,$|)/build -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_SHARED_LIBS:BOOL=OFF @@ -36,7 +36,7 @@ dist/results/jsontoolkit/%: \ dist/results/ajv/%: \ implementations/ajv/main.mjs \ schemas/%/schema.json \ - schemas/%/instances.json \ + schemas/%/instances.jsonl \ node_modules \ | dist/results/ajv node $< $(word 2,$^) $(word 3,$^) > $@ diff --git a/implementations/jsontoolkit/main.cc b/implementations/jsontoolkit/main.cc index ce95c70..d6f4158 100644 --- a/implementations/jsontoolkit/main.cc +++ b/implementations/jsontoolkit/main.cc @@ -13,7 +13,7 @@ int main(int argc, char **argv) { const std::filesystem::path example{argv[1]}; const auto schema{sourcemeta::jsontoolkit::from_file(example / "schema.json")}; - const auto instance{sourcemeta::jsontoolkit::from_file(example / "instance.json")}; + const auto instance{sourcemeta::jsontoolkit::from_file(example / "instances.jsonl")}; const auto schema_template{sourcemeta::jsontoolkit::compile( schema, sourcemeta::jsontoolkit::default_schema_walker, diff --git a/schemas/example/instances.json b/schemas/example/instances.jsonl similarity index 100% rename from schemas/example/instances.json rename to schemas/example/instances.jsonl From b2502db0acdf0439d286bec6d548ff4eb0e3924c Mon Sep 17 00:00:00 2001 From: Michael Mior Date: Tue, 27 Aug 2024 13:33:35 -0400 Subject: [PATCH 3/3] Collect instances into an array in the ajv implementation before validating --- implementations/ajv/main.mjs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/implementations/ajv/main.mjs b/implementations/ajv/main.mjs index fbf9ddb..0adffed 100644 --- a/implementations/ajv/main.mjs +++ b/implementations/ajv/main.mjs @@ -35,8 +35,12 @@ async function validateSchema(schemaPath, instancePath) { ajv.addMetaSchema(draft4schema); const validate = ajv.compile(schema); - const startTime = performance.now(); + const instances = []; for await (const instance of readJSONLines(instancePath)) { + instances.push(instance); + } + const startTime = performance.now(); + for (const instance of instances) { if (!validate(instance)) { process.exit(1); }