A JSONSchema validator that uses code generation to be extremely fast

Overview

is-my-json-valid

A JSONSchema validator that uses code generation to be extremely fast.

It passes the entire JSONSchema v4 test suite except for remoteRefs and maxLength/minLength when using unicode surrogate pairs.

build status

Installation

npm install --save is-my-json-valid

Usage

Simply pass a schema to compile it

var validator = require('is-my-json-valid')

var validate = validator({
  required: true,
  type: 'object',
  properties: {
    hello: {
      required: true,
      type: 'string'
    }
  }
})

console.log('should be valid', validate({hello: 'world'}))
console.log('should not be valid', validate({}))

// get the last list of errors by checking validate.errors
// the following will print [{field: 'data.hello', message: 'is required'}]
console.log(validate.errors)

You can also pass the schema as a string

var validate = validator('{"type": ... }')

Optionally you can use the require submodule to load a schema from __dirname

var validator = require('is-my-json-valid/require')
var validate = validator('my-schema.json')

Custom formats

is-my-json-valid supports the formats specified in JSON schema v4 (such as date-time). If you want to add your own custom formats pass them as the formats options to the validator

var validate = validator({
  type: 'string',
  required: true,
  format: 'only-a'
}, {
  formats: {
    'only-a': /^a+$/
  }
})

console.log(validate('aa')) // true
console.log(validate('ab')) // false

External schemas

You can pass in external schemas that you reference using the $ref attribute as the schemas option

var ext = {
  required: true,
  type: 'string'
}

var schema = {
  $ref: '#ext' // references another schema called ext
}

// pass the external schemas as an option
var validate = validator(schema, {schemas: {ext: ext}})

validate('hello') // returns true
validate(42) // return false

Filtering away additional properties

is-my-json-valid supports filtering away properties not in the schema

var filter = validator.filter({
  required: true,
  type: 'object',
  properties: {
    hello: {type: 'string', required: true}
  },
  additionalProperties: false
})

var doc = {hello: 'world', notInSchema: true}
console.log(filter(doc)) // {hello: 'world'}

Verbose mode shows more information about the source of the error

When the verbose options is set to true, is-my-json-valid also outputs:

  • value: The data value that caused the error
  • schemaPath: an array of keys indicating which sub-schema failed
var schema = {
  required: true,
  type: 'object',
  properties: {
    hello: {
      required: true,
      type: 'string'
    }
  }
}
var validate = validator(schema, {
  verbose: true
})

validate({hello: 100});
console.log(validate.errors)
// [ { field: 'data.hello',
//     message: 'is the wrong type',
//     value: 100,
//     type: 'string',
//     schemaPath: [ 'properties', 'hello' ] } ]

Many popular libraries make it easy to retrieve the failing rule with the schemaPath:

var schemaPath = validate.errors[0].schemaPath
var R = require('ramda')

console.log( 'All evaluate to the same thing: ', R.equals(
  schema.properties.hello,
  { required: true, type: 'string' },
  R.path(schemaPath, schema),
  require('lodash').get(schema, schemaPath),
  require('jsonpointer').get(schema, [""].concat(schemaPath))
))
// All evaluate to the same thing: true

Greedy mode tries to validate as much as possible

By default is-my-json-valid bails on first validation error but when greedy is set to true it tries to validate as much as possible:

var validate = validator({
  type: 'object',
  properties: {
    x: {
      type: 'number'
    }
  },
  required: ['x', 'y']
}, {
  greedy: true
});

validate({x: 'string'});
console.log(validate.errors) // [{field: 'data.y', message: 'is required'},
                             //  {field: 'data.x', message: 'is the wrong type'}]

Error messages

Here is a list of possible message values for errors:

  • is required
  • is the wrong type
  • has additional items
  • must be FORMAT format (FORMAT is the format property from the schema)
  • must be unique
  • must be an enum value
  • dependencies not set
  • has additional properties
  • referenced schema does not match
  • negative schema matches
  • pattern mismatch
  • no schemas match
  • no (or more than one) schemas match
  • has a remainder
  • has more properties than allowed
  • has less properties than allowed
  • has more items than allowed
  • has less items than allowed
  • has longer length than allowed
  • has less length than allowed
  • is less than minimum
  • is more than maximum

Performance

is-my-json-valid uses code generation to turn your JSON schema into basic javascript code that is easily optimizeable by v8.

At the time of writing, is-my-json-valid is the fastest validator when running

If you know any other relevant benchmarks open a PR and I'll add them.

TypeScript support

This library ships with TypeScript typings. They are still early on and not perfect at the moment, but should hopefully handle the most common cases. If you find anything that doesn't work, please open an issue and we'll try to solve it.

The typings are using unknown and thus require TypeScript 3.0 or later.

Here is a quick sample of usage together with express:

import createError = require('http-errors')
import createValidator = require('is-my-json-valid')
import { Request, Response, NextFunction } from 'express'

const personValidator = createValidator({
  type: 'object',
  properties: {
    name: { type: 'string' },
    age: { type: 'number' },
  },
  required: [
    'name'
  ]
})

export function post (req: Request, res: Response, next: NextFunction) {
  // Here req.body is typed as: any

  if (!personValidator(req.body)) {
    throw createError(400, { errors: personValidator.errors })
  }

  // Here req.body is typed as: { name: string, age: number | undefined }
}

As you can see, the typings for is-my-json-valid will contruct an interface from the schema passed in. This allows you to work with your incoming json body in a type safe way.

License

MIT

Comments
  • v2.17.0 introduces a regression

    v2.17.0 introduces a regression

    I do not use this package directly, but xo does.

    After you released 2.17.0 xo doesn't run anymore with this error:

    If you break retro-compatibility, you are supposed to to a major version bump.

    /builds/***/node_modules/is-my-json-valid/index.js:366
          visit(name+'['+i+']', node.items, reporter, filter, schemaPath.concat('items'))
                                                                         ^
    
    TypeError: Cannot read property 'concat' of undefined
        at visit (/builds/***/node_modules/is-my-json-valid/index.js:366:70)
        at /build/***/node_modules/is-my-json-valid/index.js:416:9
        at Array.forEach (<anonymous>)
        at visit (/builds/***/node_modules/is-my-json-valid/index.js:409:18)
        at /builds/***/node_modules/is-my-json-valid/index.js:543:9
        at Array.forEach (<anonymous>)
        at visit (/builds/***/node_modules/is-my-json-valid/index.js:540:31)
        at compile (/builds/***/node_modules/is-my-json-valid/index.js:565:3)
        at visit (/builds/***/node_modules/is-my-json-valid/index.js:340:16)
        at /builds/***/node_modules/is-my-json-valid/index.js:416:9
    opened by rpadovani 41
  • Loading a schema in is-my-json-valid has side effects

    Loading a schema in is-my-json-valid has side effects

    The schema:

    {
                    "items": [
                            {}
                    ],
                    "additionalItems": {
                            "type": "integer"
                    }
    }
    

    gets turned into

     {
                    "items": [
                            {}
                    ],
                    "additionalItems": {
                            "type": "integer"
                    },
                    "properties": {
                            "0": {}
                    },
                    "type": "array",
                    "tuple": true
    }
    

    I don't think loading a schema should have side-effects on the original schema.

    opened by ebdrup 15
  • Add

    Add "schemaPath" to verbose output, showing which subschema triggered each error.

    This PR adds a 'schemaPath' to the verbose output that can be used to get back to the failed rule in the schema in order to associate metadata with failures.

    This provides a solution to https://github.com/mafintosh/is-my-json-valid/issues/102 and https://github.com/mafintosh/is-my-json-valid/issues/122 by making it possible to pull the appropriate additionalProperties or enum out of the schema.

    For example, given this schema:

    {	"id": "birds",
    	"allOf": [
    		{ 	"metadata": "ravens_are_black",
    		 	"not": {
    				"properties": {
    					"animal": { "enum": [ "raven" ] },
    					"color": {
    						"not": {
    							"enum": [ "black" ] } } } } },
    		{	"metadata": "nested_string",
    			"properties": {
    				"outer": {
    					"properties": {
    						"inner": {
    							"metatdata": "deep",
    							"type": "string" } } } } },
    		{	"metadata": "doves_are_white",
    			"not": {
    				"properties": {
    					"animal": { "enum": [ "dove" ] },
    					"color": {
    						"not": {
    							"enum": [ "white" ] } } } } } ] }
    

    You can validate trace back failures to the and this test program:

    const validator = require( './index.js' );
    const birdsSchema = require('./bird-schema.json');
    
    const badRaven = { animal: 'raven', color: 'rainbow', outer: { inner: 12 } };
    const badDove = { animal: 'dove', color: 'pink' };
    
    const validate = validator( birdsSchema, { greedy: true, verbose: true } );
    const get = require( 'lodash/get' );
    
    function printError( error ) {
    	console.log( 'error:', JSON.stringify(error) );
    	const failedRule = get( birdsSchema, error.schemaPath );
    	console.log( 'failedRule:', JSON.stringify( failedRule ) );
    	console.log();
    }
    
    validate( badRaven );
    console.log('badRaven:');
    validate.errors.map( printError );
    
    console.log();
    
    validate( badDove );
    console.log("badDove:");
    validate.errors.map( printError );
    

    We can get the correct rule and it's metadata back out of the schema:

    badRaven:
    error: {"field":"data","message":"negative schema matches","value":{"animal":"raven","color":"rainbow","outer":{"inner":12}},"schemaPath":["allOf",0]}
    failedRule: {"metadata":"ravens_are_black","not":{"properties":{"animal":{"enum":["raven"]},"color":{"not":{"enum":["black"]}}}}}
    
    error: {"field":"data.outer.inner","message":"is the wrong type","value":12,"type":"string","schemaPath":["allOf",1,"properties","outer","properties","inner"]}
    failedRule: {"metatdata":"deep","type":"string"}
    
    
    badDove:
    error: {"field":"data","message":"negative schema matches","value":{"animal":"dove","color":"pink"},"schemaPath":["allOf",2]}
    failedRule: {"metadata":"doves_are_white","not":{"properties":{"animal":{"enum":["dove"]},"color":{"not":{"enum":["white"]}}}}}
    

    The patch adds only the extra static string to the generated validation functions, so it should have virtually no effect on performance. (There's a very modest amount of extra work being done at compile time).

    I added paths for anyOf and oneOf, but then I pulled it out again. I think it doesn't make sense to dive into them.

    I've added paths to every call to visit, but I haven't exercised any of it, so they're probably wrong right now and need some tests.

    opened by deBhal 12
  • undefined bypasses validation

    undefined bypasses validation

    const assert = require('assert')
    
    const validate = require('is-my-json-valid')({
      type: 'string'
    })
    
    // Works.
    assert(validate(''))
    assert(!validate(null))
    assert(!validate({}))
    
    // Does not work.
    assert(!validate(undefined))
    
    opened by julien-f 10
  • Request to expose error location-line and column

    Request to expose error location-line and column

    Hi, I would like to have additional information on every error, describing WHERE is the text in the tested JSON file/string which failed validation. The location info should include: line number (most important), column number (column is were the failed text token started), number of characters of error text token (this parameter is nice-to-have)

    enhancement 
    opened by erezfz 8
  • Nested External Schema Reference doesn't work

    Nested External Schema Reference doesn't work

    When using this library, the ref to an external schema just doesn't work, but when using others such as tv4, it works perfectly fine.

    The Schema

    {
      "type": "object",
      "properties": {
         "body":  "$ref": "#oauth"
      }
    }
    

    And the defs schema

    {
      "definitions": {
        "oauth": { ... }
      }
    }
    

    when doing

    validate = validator(schema, { "schemas": defs.definitions }); validate(req);

    The error l get is: reference schema does not match

    question 
    opened by OllieJennings 8
  • Fix a ReDoS in 'style' format

    Fix a ReDoS in 'style' format

    Filing a public PR as requested.

    As there are no ^ or $ anchors in the regex, this should be equivalent. Patch deliberately does not change the behavior.

    If the intent was to include ^ and $ and those were missed due to an unrelated mistake, I can probably propose another safe regex for that (but that would change the behavior).

    Please recheck that this regex is correct.

    opened by ChALkeR 5
  • Added possibility to supply custom error messages, which are either ...

    Added possibility to supply custom error messages, which are either ...

    Added possibility to supply custom error messages, which are either strings or functions. In case a function is provided, it will be called with some error specific parameters. The first parameter is always the name of the field that is validated. At the moment, only the type and format have a second parameter (for format this the format specifier and for type, it is the type specifier). When verbose is set to true however, the value that is also added to the error object will be provided as a third parameter.

    In case this functionality is not used, the default messages are used.

    Example:

    var customErrMsgs = {
        'required': function(field)         { return "The " + field + " field is required"; },
        'type':     function(field, type)   { return "The " + field + " field has the wrong type ("+type+")"; },
        'format':   function(field, format) { return "The " + field + " field needs to be a valid "+format; }
    };
    
    var validator = validator(someJsonSchema, {errMsgs: customErrMsgs});
    
    opened by rcijvat 5
  • fix undefined schema-path

    fix undefined schema-path

    this fixes the xo package. i will try to come up with a test next.

     ∴  xo
    /Users/julian/dev/X/node_modules/is-my-json-valid/index.js:366
          visit(name+'['+i+']', node.items, reporter, filter, schemaPath.concat('items'))
                                                                         ^
    
    TypeError: Cannot read property 'concat' of undefined
        at visit (/Users/julian/dev/X/node_modules/is-my-json-valid/index.js:366:70)
        at /Users/julian/dev/X/node_modules/is-my-json-valid/index.js:416:9
        at Array.forEach (<anonymous>)
        at visit (/Users/julian/dev/X/node_modules/is-my-json-valid/index.js:409:18)
        at /Users/julian/dev/X/node_modules/is-my-json-valid/index.js:543:9
        at Array.forEach (<anonymous>)
        at visit (/Users/julian/dev/X/node_modules/is-my-json-valid/index.js:540:31)
        at compile (/Users/julian/dev/X/node_modules/is-my-json-valid/index.js:565:3)
        at visit (/Users/julian/dev/X/node_modules/is-my-json-valid/index.js:340:16)
        at /Users/julian/dev/X/node_modules/is-my-json-valid/index.js:416:9
    
    opened by juliangruber 4
  • Allow null to pass on any type

    Allow null to pass on any type

    In some cases it might be useful to allow null to pass given any check for type.

    For example given the following JSON:

    {
      "a": 1234,
      "b": null,
      "c": {
        "d": 4321,
        "e": true
      }
    }
    

    We may construct our rules like this:

    {
      "required": true,
      "type": "object",
      "properties": {
        "a": {
          "required": true,
          "type": "number"
        },
        "b": {
          "required": true,
          "type": "null"
        },
        "c": {
          "required": true,
          "type": "object",
          "properties": {
            "d": {
              "required": true,
              "type": "number"
            },
            "e": {
              "required": true,
              "type": "boolean"
            }
          }
        },
    }
    

    Now say we want to allow b to be a boolean when it is defined but also allow it be null.

    We can update our rules to look like this:

    {
      "required": true,
      "type": "object",
      "properties": {
        "a": {
          "required": true,
          "type": "number"
        },
        "b": {
          "required": true,
          "type": "null" || "boolean"
        },
        "c": {
          "required": true,
          "type": "object",
          "properties": {
            "d": {
              "required": true,
              "type": "number"
            },
            "e": {
              "required": true,
              "type": "boolean"
            }
          }
        },
    }
    

    But if we cant d to be a nested object like originally shown or null using the same trick for b (see rule below) that will error because if is d is in fact null it will try to read a property that doesn't exist

    {
      "required": true,
      "type": "object",
      "properties": {
        "a": {
          "required": true,
          "type": "number"
        },
        "b": {
          "required": true,
          "type": "null" || "boolean"
        },
        "c": {
          "required": true,
          "type": "null" || "object",
          "properties": {
            "d": {
              "required": true,
              "type": "number"
            },
            "e": {
              "required": true,
              "type": "boolean"
            }
          }
        },
    }
    

    I'm not even sure if the || is valid but it does work in the case when the type isn't object but it would be nice to have something like allowNull key.

    So the rules could like something like this:

    {
      "required": true,
      "type": "object",
      "properties": {
        "a": {
          "required": true,
          "type": "number"
        },
        "b": {
          "required": true,
          "type": "boolean",
          "allowNull": true
        },
        "c": {
          "required": true,
          "type": "object",
          "allowNull": true,
          "properties": {
            "d": {
              "required": true,
              "type": "number"
            },
            "e": {
              "required": true,
              "type": "boolean"
            }
          }
        },
    }
    
    opened by alallier 4
  • Bump jsonpointer version

    Bump jsonpointer version

    Braking change in 3.x:

    • Drop node 0.6 and 0.8 support

    Breaking changes in 4.x:

    • When setting a null value, it now gets set as actual value. Previously we've deleted the property.
    • When getting a non-existent value, we previously returned null. We've now changed that to undefined.

    I don't think that any of these changes affects this package.

    opened by LinusU 4
  • Fixed PR #192 (multipleOf decimal with big integer value)

    Fixed PR #192 (multipleOf decimal with big integer value)

    https://github.com/mafintosh/is-my-json-valid/pull/192

    The issue seemed to be that number | 0 !== number to detect integers doesn't work for big numbers. I replaced it with the Number.isInteger function, which seems to handle all test cases quite well

    Also inverted the ternary operator to avoid the negation. I also suggest replacing multipleOf.toString().split('.').pop().length with a named function

    const getDecimalPart = (num) => num.toString().split(".").pop(); const getNumberOfDecimals = (num) => getDecimalPart(num).length;

    var factor = Number.isInteger(multipleOf) ? 1 : Math.pow(10, getNumberOfDecimals(multipleOf))

    opened by linco95 1
  • add test for false negative on multipleOf

    add test for false negative on multipleOf

    Using multipleOf 0.01 fails to validate a big number that does not contain a decimal part.

    1658529657949.05 is valid, as it should be. 165 is valid, as it should be. 1658529657949 is not valid, but should be valid.

    NOTICE: This PR adds a failing test, but it does not contain a proper solution. Do not merge this without a fix.

    opened by pubkey 0
  • Heads up: 2.20.6 breaks semver

    Heads up: 2.20.6 breaks semver

    The upgrade of jsonpointer from 4.x to 5.x in the last patch release bumps the node version requirement as it makes use of the const and of keywords. I appreciate that this only applies to long dead versions of node, but worth being aware of none the less. 🙂

    Discovered as the azure-storage module ~~has~~ had (~2.0.0) an indirect dependency on this module, and now tanks on previously supported versions of node. The dependency chain also includes several deprecated modules along the way.

    [...]/node_modules/azure-storage/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/jsonpointer.js:55
        for (const part of pointer) {
                        ^^
    SyntaxError: Unexpected identifier
    

    This probably isn't anything that requires action, everything involved upstream is already shaky and the node versions impacted have long since been EoL. Just a heads up in case anyone else ends up here.

    opened by mal 1
  • Required field in schema gets type 'string | undefined'

    Required field in schema gets type 'string | undefined'

    I'm trying to validate an input and assign it to a variable of a type that I've defined. All fields are required in the validator. However, when I try to assign the validated input I get this error:

    Type 'ObjectFromSchema<{ prop1: { type: "string"; required: true; }; }, never>' is not assignable to type 'Body'.
      Types of property 'prop1' are incompatible.
        Type 'string | undefined' is not assignable to type 'string'.
          Type 'undefined' is not assignable to type 'string'.ts(2322)
    

    Since the attribute prop1 is required, why is it showing as possibly undefined?

    Demonstration code (the error is at the line which says const validBody: Body = body;):

    import validator from 'is-my-json-valid';
    
    type Body = { prop1: string };
    
    function validateBody(body: any): Body {
        const bodyValidator = validator({
            type: 'object',
            required: true,
            properties: {
                prop1: {
                    type: 'string',
                    required: true as true
                }
            }
        });
    
        if (!bodyValidator(body)) {
            throw new Error('Invalid format: ' + bodyValidator.errors);
        }
    
        const validBody: Body = body;
        return validBody;
    }
    

    This is with is-my-json-valid version 2.20.5 and Typescript version 4.3.5, with "strict": true

    opened by jwasnoggin 6
  • undefined array items bypasses validation

    undefined array items bypasses validation

    This is the same scenario as https://github.com/mafintosh/is-my-json-valid/issues/116 / https://github.com/mafintosh/is-my-json-valid/commit/9721fe31e362d5be5da9c7a0047c8e5c888aee88

    but for array items

    opened by jimmybergman 0
Owner
Mathias Buus
Rød grød med fløde
Mathias Buus
This is the code repository of the official mun testnet validator node source code.

How to join Munchain network Infrastructure **Recommended configuration:** - Number of CPUs: 4 - Memory: 16GB - OS: Ubuntu 22.04 LTS - Allow all incom

MUN Blockchain 16 Dec 15, 2022
Super Fast Complex Object Validator for Javascript(& Typescript).

Super Fast Object Validator for Javascript(& Typescript). Safen supports the syntax similar to the type script interface. This makes it easy to create

Changwan Jun 31 Nov 25, 2022
Fast, compiled, eval-free data validator/transformer

spectypes Fast, compiled, eval-free data validator/transformer Features really fast, can be even faster than ajv detailed errors, failure will result

null 65 Dec 29, 2022
Jquery-anyimagecomparisonslider-plugin - The any Image Comparison Slider is an extremely versatile yet slim slider for comparing images. You have a lot of options to configure the slider and it works just about everywhere.

any Image Comparison Slider (jquery-anyimagecomparisonslider-plugin ) Description The any Image Comparison Slider is an extremely versatile yet slim s

Niklas 6 Sep 12, 2022
The fastest JSON schema Validator. Supports JSON Schema draft-04/06/07/2019-09/2020-12 and JSON Type Definition (RFC8927)

Ajv JSON schema validator The fastest JSON validator for Node.js and browser. Supports JSON Schema draft-06/07/2019-09/2020-12 (draft-04 is supported

Ajv JSON schema validator 12k Jan 4, 2023
ForgJs is a javascript lightweight object validator. Go check the Quick start section and start coding with love

Hey every one im really happy that this repo reached this many stars ?? ,but this repo needs your contibution I started to better document the code th

Hamdaoui Oussama 1.7k Dec 21, 2022
Tiny Validator for JSON Schema v4

Tiny Validator (for v4 JSON Schema) Use json-schema draft v4 to validate simple values and complex objects using a rich validation vocabulary (example

Geraint 1.2k Dec 21, 2022
Simple validator for Steuerliche Identifikationsnummer (German personal tax number) according to the official docs (see readme).

simple-de-taxid-validator Important Code of this validator is taken (with small changes like optimization or removing not needed elements) from THIS R

Wojciech 3 Feb 24, 2022
Easy HTML Form Validator

Easy HTML Form Validator

Ali Nazari 314 Dec 26, 2022
A simple environment variables validator for Node.js and web browsers

A simple environment variables validator for Node.js and web browsers

Mathieu Acthernoene 25 Jul 20, 2022
Facile is an HTML form validator that is inspired by Laravel's validation style and is designed for simplicity of use.

Facile is an HTML form validator that is inspired by Laravel's validation style and is designed for simplicity of use.

upjs 314 Dec 26, 2022
Simple password validator made with Javascript 💛

Password Validator Simple password validator made with Javascript ?? Branch history base-code: a complex logic to password validator. In next branches

Lais Frigério 8 Jul 25, 2022
What does the Cosmos Hub validator set looks like without ICF delegations?

This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn dev Open http://

Made in Block 2 Sep 2, 2022
[DISCONTINUED] jQuery plugin that makes it easy to validate user input while keeping your HTML markup clean from javascript code.

jQuery Form Validator [DISCONTINUED] Validation framework that let's you configure, rather than code, your validation logic. I started writing this pl

Victor Jonsson 976 Dec 30, 2022
Vue-input-validator - 🛡️ Highly extensible & customizable input validator for Vue 2

??️ Vue-input-validator demo! What is this package all about? By using this package, you can create input validators only with the help of a single di

null 14 May 26, 2022
typescript-to-jsonschema generates JSON Schema files from your Typescript sources.

fast-typescript-to-jsonschema English | 简体中文 a tool generate json schema from typescript. Feature compile Typescript to get all type information conve

yunfly 21 Nov 28, 2022
:fire: An extremely fast, React-like JavaScript library for building modern user interfaces

Inferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server. Description The main obje

Inferno 15.6k Dec 31, 2022
:fire: An extremely fast, React-like JavaScript library for building modern user interfaces

Inferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server. Description The main obje

Inferno 15.6k Jan 3, 2023
⚡ Extremely fast online playground for every programming language.

Riju Riju is a very fast online playground for every programming language. In less than a second, you can start playing with a Python interpreter or c

Radon Rosborough 845 Dec 28, 2022