Giter Site home page Giter Site logo

json-skema's Introduction

json-sKema

json-sKema is a Json Schema validator library for the Java Virtual Machine. It implements the draft 2020-12 specification.

Are you new to JSON Schema? Get started with Understanding JSON Schema!

Installation

Maven

Add the following dependency to the <dependencies> section of your project:

<dependency>
    <groupId>com.github.erosb</groupId>
    <artifactId>json-sKema</artifactId>
    <version>0.15.0</version>
</dependency>

Gradle

dependencies {
    implementation("com.github.erosb:json-sKema:0.15.0")
}

Usage

Hello-world

Complete source

// parse the schema JSON as string
JsonValue schemaJson = new JsonParser("""
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"age": {
			"type": "number",
			"minimum": 0
		},
		"name": {
			"type": "string"
		},
		"email": {
			"type": "string",
			"format": "email"
		}
	}
}
""").parse();
// map the raw json to a reusable Schema instance
Schema schema = new SchemaLoader(schemaJson).load();

// create a validator instance for each validation (one-time use object)
Validator validator = Validator.create(schema, new ValidatorConfig(FormatValidationPolicy.ALWAYS));

// parse the input instance to validate against the schema
JsonValue instance = new JsonParser("""
{
	"age": -5,
	"name": null,
	"email": "invalid"
}
""").parse();

// run the validation
ValidationFailure failure = validator.validate(instance);

// print the validation failures (if any)
System.out.println(failure);

Loading a schema file from URL

// HTTP(s) protocol is also supported
Schema schema = SchemaLoader.forURL("classpath:///path/to/your/schema.json").load();

// create a validator instance for each validation (one-time use object) 
Validator validator = Validator.forSchema(schema);
// ...

Pre-registering schemas by URI before schema loading

Complete source

// Creating a SchemaLoader config with a pre-registered schema by URI
SchemaLoaderConfig config = createDefaultConfig(Map.of(
			// When the loader sees this URI,
			new URI("urn:uuid:d652a438-9897-4160-959c-bbdb690c3e0d"),

			// then it will resolve it to this schema json
			"""
			{
				"$defs": {
					"ItemType": {
						"type": "integer",
						"minimum": 0
					}
				}
			}
			"""
	));
// parsing the schema json, with a $ref to the above pre-configured URI
JsonValue schemaJson = new JsonParser("""
		{
			"type": "array",
			"items": {
				"$ref": "urn:uuid:d652a438-9897-4160-959c-bbdb690c3e0d#/$defs/ItemType"
			}
		}
		""").parse();
// loading the schema json into a Schema object
Schema schema = new SchemaLoader(schemaJson, config).load();

// running the validation
ValidationFailure result = Validator.forSchema(schema).validate(new JsonParser("[null]").parse());
System.out.println(result.toJSON());

Validating in Read or Write context

Complete source

If you want to take advantage of the "readOnly" and "writeOnly" keywords of json schema, you can tell the Validator instance if the validation happens in read or write context:

JsonValue schemaJson = new JsonParser("""
{
    "type": "object",
    "properties": {
        "id": {
            "readOnly": true,
            "type": "number"
        },
        "name": {
            "type": "string"
        },
        "password": {
            "type": "string",
            "writeOnly": true
        }
    }
}
""").parse();
// map the raw json to a reusable Schema instance
Schema schema = new SchemaLoader(schemaJson).load();

// creating write-context validator, it will report validation failures
// for read-only properties that are included in the instance
var writeContextValidator = Validator.create(schema, ValidatorConfig.builder()
        .readWriteContext(ReadWriteContext.WRITE)
        .build()
);

// creating the json document which will be validated (first in write context, then in read context)
JsonValue instance = new JsonParser("""
        {
            "id": 1,
            "name": "John Doe",
            "password": "v3ry_s3cur3"
        }
        """).parse();
var writeContextFailure = writeContextValidator.validate(instance);

// prints failure because the read-only property "id" is present in write context
System.out.println(writeContextFailure);

// creating read-context validator, it will report validation failures
// for write-only properties that are included in the instance
var readContextValidator = Validator.create(schema, ValidatorConfig.builder()
        .readWriteContext(ReadWriteContext.READ)
        .build()
);

var readContextFailure = readContextValidator.validate(instance);

// prints failure because the write-only property "password" is present in read context
System.out.println(readContextFailure);

Compatibility notes

The library implements the JSON Schema draft 2020-12 core and validation specifications, with the following notes:

  • $dynamicAnchor and $dynamicRef support is partially implemented

"format" support

The library currently has built-in support for the following "format" values defined in the specification:

"format" Supported? Notes
date Yes
date-time Yes Non-UTC values with leap seconds not supported
time Yes
duration Partially
email Yes IPV6 domain parts not supported
uri Yes
ipv4 Yes
ipv6 Yes
uuid Yes

The following formats are NOT supported: hostname, idn-email, idn-hostname, iri, iri-reference, json-pointer, regex, relative-json-pointer, uri-reference, uri-template .

Support for older JSON Schema drafts

This project is the successor of everit-org/json-schema. If you want to use draft-04, draft-06 or draft-07 versions of JSON Schema, then you can use the everit library.

Contribution guideline

Local environment setup:

Prerequisite: JDK and Maven installed

git clone https://github.com/erosb/json-sKema.git
cd json-sKema
git submodule init
git submodule update

Building the project:

mvn clean package

Building the project and running the official test suite:

Test annotated with @Tag("acceptance") require the test suite to be pulled using:

git submodule update --init --recursive

Then run the tests:

mvn clean verify

Building the project without running the official test suite:

mvn clean package -Dgroups='!acceptance'

json-skema's People

Contributors

big-andy-coates avatar dependabot[bot] avatar erosb avatar jakesmolka avatar rayokota avatar rechvs avatar singingbush avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

json-skema's Issues

How to resolve schemas with URI

Hello , I am exploring json-sKema library for schema validation.
I have below schema , how can i resolve city and state json schema during validation.
On validating schema with below data, i expect it to fail validation. But it pass the validation
"{"firstName":"ABC","lastName":"ABC","age":20,"city":{"city1":{"name":20,"zipCode":"45676"}}}\n"

{

"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "The citizen's first name."
},
"lastName": {
"type": "string",
"description": "The citizen's last name."
},
"age": {
"description": "Age in years which must be equal to or greater than zero.",
"type": "integer",
"minimum": 0
},
"city": {
"type": "object",
"properties": {
"city1": { "$ref": "city.json"},
"state": {"$ref": "state.json"}
}

  }

}
}

city.json {

"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The city's name."
},
"zipCode": {
"type": "integer",
"description": "The zip code.",
"minimum": 0
}
}
}

state.json {

"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The city's name."
},
"zipCode": {
"type": "integer",
"description": "The zip code.",
"minimum": 0
}
}
}

Throw SchemaException when loading fails

Hello,

It would be very useful if a SchemaException (or similar) would be thrown when loading a Schema with errors (such as invalid references, or wrongly used keywords). At the moment, an Error is thrown, which is too generic and also does not provide a JSON pointer (like the previous library).

Thank you for your great work!

Regards,
Florin

Performance and functional comparison

Hi,

I've recently needed to compare the performance and functionality of this and other JVM based JSON validation libraries, and I thought you might like to see how this implementation compares. I've published to the code and the results here: https://github.com/creek-service/json-schema-validation-comparison.

While I've spent time trying to get the best out of each library under test, it's possible that the results for this implementation could be improved if someone with more in-depth knowledge were to look into it. If you feel I'm not showing in its best light, please feel free to raise PRs to fix issues and improve your score.

Please feel free to link to the code and results.

I hope this is of some use to you.

Thanks,

Andy

Validation returns "An operation is not implemented: something went wrong" for complex schema

Hi @erosb ,

While using this library against our test suite, I ran into a validation error on a complex schema. Below is the code that returns the error.

package io.confluent.kafka.schemaregistry.json.schema;

import com.github.erosb.jsonsKema.IJsonValue;
import com.github.erosb.jsonsKema.JsonParseException;
import com.github.erosb.jsonsKema.JsonParser;
import com.github.erosb.jsonsKema.JsonValue;
import com.github.erosb.jsonsKema.Schema;
import com.github.erosb.jsonsKema.SchemaClient;
import com.github.erosb.jsonsKema.SchemaLoader;
import com.github.erosb.jsonsKema.SchemaLoaderConfig;
import com.github.erosb.jsonsKema.SchemaLoadingException;
import com.github.erosb.jsonsKema.Validator;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.Test;

public class ReferenceTest {

  private static final String DUMMY_BASE_URI = "dummy://input/";

  @Test
  public void testReferences() throws Exception {
    String doc = "{\n"
        + "  \"customerName\": \"acme\",\n"
        + "  \"acquireDate\": \"2020-12-12\"\n"
        + "}";
    JsonValue jsonValue = new JsonParser(doc).parse();

    String oneOfSchema = "{\n"
        + "  \"oneOf\": [\n"
        + "    { \"$ref\": \"customer.json\"},\n"
        + "    { \"$ref\": \"user.json\"}\n"
        + "  ]\n"
        + "}";
    String userSchema = "{\n"
        + "  \"type\": \"object\",\n"
        + "  \"additionalProperties\": false,\n"
        + "  \"properties\": {\n"
        + "    \"name\": {\n"
        + "      \"type\": \"string\"\n"
        + "    },\n"
        + "    \"age\": {\n"
        + "      \"type\": \"integer\",\n"
        + "      \"minimum\": 0\n"
        + "    }\n"
        + "  },\n"
        + "  \"required\": [\n"
        + "    \"age\"\n"
        + "  ]\n"
        + "}\n";
    String customerSchema = "{\n"
        + "  \"type\": \"object\",\n"
        + "  \"additionalProperties\": false,\n"
        + "  \"properties\": {\n"
        + "    \"customerName\": {\n"
        + "      \"type\": \"string\"\n"
        + "    },\n"
        + "    \"acquireDate\": {\n"
        + "      \"type\": \"string\"\n"
        + "    }\n"
        + "  }\n"
        + "}\n";

    Map<URI, String> refs = new HashMap<>();
    refs.put(new URI(DUMMY_BASE_URI + "user.json"), userSchema);
    refs.put(new URI(DUMMY_BASE_URI + "customer.json"), customerSchema);

    SchemaLoaderConfig config = new SchemaLoaderConfig(
        new ReferenceSchemaClient(refs), DUMMY_BASE_URI);

    JsonValue schemaJson = new JsonParser(oneOfSchema).parse();

    Schema loadedSchema = new SchemaLoader(schemaJson, config).load();
    Validator validator = Validator.forSchema(loadedSchema);
    validator.validate(jsonValue);
  }

  public static class ReferenceSchemaClient implements SchemaClient {

    private Map<URI, String> references;

    public ReferenceSchemaClient(Map<URI, String> references) {
      this.references = references;
    }

    @Override
    public InputStream get(URI uri) {
      String reference = references.get(uri);
      if (reference == null) {
        throw new UncheckedIOException(new FileNotFoundException(uri.toString()));
      }
      return new ByteArrayInputStream(reference.getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public IJsonValue getParsed(URI uri) {
      BufferedReader reader = new BufferedReader(new InputStreamReader(get(uri)));
      String string = reader.lines().collect(Collectors.joining());
      try {
        return new JsonParser(string, uri).parse();
      } catch (JsonParseException ex) {
        throw new SchemaLoadingException("failed to parse json content returned from $uri", ex);
      }
    }
  }
}

Oddly, if I remove "required": ["age"] from userSchema, then the "something went wrong" error does not appear.

kotlin.NotImplementedError

Hello,

I am receiving for one event validation following error

kotlin.NotImplementedError: An operation is not implemented: something went wrong: com.github.erosb.jsonsKema.MarkableJsonObject@13b61e54 vs {
"feature": "some-val",
"element": "some-val",
"action": "some-val"
}

at com.github.erosb.jsonsKema.AggregatingValidationFailure.join$json_sKema(ValidationFailure.kt:67) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.accumulate(Validator.kt:711) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.accumulate(Validator.kt:156) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.SchemaVisitor.visitCompositeSchema(SchemaVisitor.kt:71) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.access$visitCompositeSchema$s680550253(Validator.kt:156) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator$visitCompositeSchema$2.invoke(Validator.kt:259) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator$visitCompositeSchema$2.invoke(Validator.kt:258) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.withOtherInstance(Validator.kt:352) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.visitCompositeSchema(Validator.kt:258) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.visitCompositeSchema(Validator.kt:156) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.SchemaVisitor.internallyVisitCompositeSchema$json_sKema(SchemaVisitor.kt:55) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.CompositeSchema.accept(Schema.kt:26) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.validate(Validator.kt:249) ~[json-sKema-0.13.0.jar:na]
at com.bonial.tracking.trackingpolicing.service.SchemaValidator.validate(SchemaValidator.java:79) ~[classes/:na]
--> rest i cutted 

Tried to debug through the code and I relly cant find the issue.
Using Java 11, json sKema 0.13.0 and also set the kotlin version to 1.9 in my pom.

Is there anything I can do?

Improper error message for "unevaluatedProperties": false schema always fails

Hi,

I am trying to validate against a schema that does not allow unevaluated properties and I'm getting the following error every single time: false schema always fails. I managed to reproduce the behavior on a smaller schema:

  • Schema: { "$schema": "http://json-schema.org/draft/2020-12/schema#", "type": "object", "properties": { "key2": { "type": "string" } }, "unevaluatedProperties": false }

  • Document to validate: { "key": "val" }

Any thoughts on this?

Thanks in advance,
Florin

Override "message" as well as "toString" in JsonTypeException

Currently JsonTypingException only overrides the toString method, whereas JsonParseException only overrides the message field. Is this intentional?
I’m asking, because imho it makes processing these exceptions more difficult than necessary, because you need separate logic for retrieving the detail message: for JsonTypingException you have to call toString, while for JsonParseException you have to access the message field.

If it helps, I’d be happy to provide a PR.

Extending schemas?

Is it possible to write our own schemas to extend the current definitions? For an example, there is a https://json-schema-faker.js.org/ project that allows users to define "faker" value for their properties. An example of such schema is:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "faker": "name.findName"
    },
    "email": {
      "type": "string",
      "faker": "internet.email"
    }
  },
  "required": [
    "name",
    "email"
  ]
}

json-sKema will parse all properties except "faker" since it is not a registered keyword. I would like to write my own FakerSchema and extend the SchemaVisitor to allow visiting the new schemas.

Is something like this possible with the library?

supports tuple validation mode for items in array object

Hello, your work is very good and has solved many of my problems, especially for error reports, I haven't found a good way to handle them from other jsonschema projects。I hope you can support the tuple mode of array.items. Thank you very much。

Input some json below, it throw error.
json code:
{ "type": "array", "title": "array desc", "items": [ {"type": "object", "title": "some obj"} ] }

cause
Caused by: kotlin.NotImplementedError: An operation is not implemented. at com.github.erosb.jsonsKema.SchemaLoader.doLoadSchema(SchemaLoader.kt:428) at com.github.erosb.jsonsKema.SchemaLoader.loadChild$json_sKema(SchemaLoader.kt:515) at com.github.erosb.jsonsKema.SchemaLoader$createCompositeSchema$1$1$ctx$1.invoke(SchemaLoader.kt:452) at com.github.erosb.jsonsKema.SchemaLoader$createCompositeSchema$1$1$ctx$1.invoke(SchemaLoader.kt:450) at com.github.erosb.jsonsKema.ItemsKt$itemsSchemaLoader$1.invoke(Items.kt:10) at com.github.erosb.jsonsKema.ItemsKt$itemsSchemaLoader$1.invoke(Items.kt:8) at com.github.erosb.jsonsKema.SchemaLoader$createCompositeSchema$1.invoke(SchemaLoader.kt:475) at com.github.erosb.jsonsKema.SchemaLoader$createCompositeSchema$1.invoke(SchemaLoader.kt:447) at com.github.erosb.jsonsKema.SchemaLoader.enterScope(SchemaLoader.kt:176) at com.github.erosb.jsonsKema.SchemaLoader.createCompositeSchema(SchemaLoader.kt:447)

Set up Dependabot to keep dependencies up to date.

Hey @erosb,

I find it generally very useful to make use of GitHub's Dependabot to keep all your project's dependencies up to date. I know this project doesn't have much in the way of release dependencies, but it can't hurt to automate it.

Happy to help if you want.

Error in README due to new version

In Readme:

// create a validator instance for each validation (one-time use object)
Validator validator = Validator.create(schema, new ValidatorConfig(FormatValidationPolicy.ALWAYS));

But in version 0.12.0:
new ValidatorConfig(FormatValidationPolicy.ALWAYS) doesn't exists.

SubSchema internal references are not resolved

Hello,

I have a problem when working with multiple schemas which refer to the internal content.

NOTE: The test cases below are based on RefResolutionTest.kt class.

When working with a root schema referencing its internal variables, the properties are resolved successfully, for instance:

    @Test
    fun `ref definitions`() {
        val root: CompositeSchema = createSchemaLoaderForString(
                """
            {
                "$ref": "#/$defs/ddd",
                "$defs": {
                   "ddd": {
                        "title": "my title",
                        "$anchor": "myAnchor"
                   }
                }
            }
            """.trimIndent()
        )() as CompositeSchema
        val actual = root.accept(TraversingSchemaVisitor<String>("$ref", "title"))!!
        assertThat(actual).isEqualTo("my title")
    }

Here we refer to "ddd" header directly from the schema and it works well, returning the correct value.

If we want to add a simple subSchema and refer it from the root schema, it works well as well:

    @Test
    fun `ref definitions child`() {
        val actual = createSchemaLoaderForString(
                """
                {
                    "$ref": "http://subschema.json#/$defs/ddd"
                }
            """,
                mapOf(
                        Pair(
                                "http://subschema.json",
                                """
                                    {
                                        "$defs": {
                                           "ddd": {
                                                "title": "my title",
                                                "$anchor": "myAnchor"
                                           }
                                        }
                                    }
                                """
                        )
                )
        )() as CompositeSchema

        val referred = (actual.subschemas.iterator().next() as ReferenceSchema).referredSchema as CompositeSchema
        assertThat(referred.title!!.value).isEqualTo("my title")
    }

However, if the subSchema uses internal "$ref" reference, that fails as the application is looking for the referenced object in the root schema, and not within the subSchema.
For instance, if we move the schema from the first example to a be a subschema in the second example, it does not longer work:

    @Test
    fun `ref definitions child self ref`() {
        val actual = createSchemaLoaderForString(
                """
                {
                    "$ref": "http://subschema.json#/$defs/ddd"
                }
            """,
                mapOf(
                        Pair(
                                "http://subschema.json",
                                """
                                    {
                                        "$ref": "#/$defs/ddd",
                                        "$defs": {
                                           "ddd": {
                                                "title": "my title",
                                                "$anchor": "myAnchor"
                                           }
                                        }
                                    }
                                """
                        )
                )
        )() as CompositeSchema
    }

and returns the following error:

java.lang.Error: json pointer evaluation error: could not resolve property $defs in {
  "$ref": "http://subschema.json#/$defs/ddd"
}
	at com.github.erosb.jsonsKema.SchemaLoader$evaluateJsonPointer$lookupNext$1.invoke(SchemaLoader.kt:375)
	at com.github.erosb.jsonsKema.SchemaLoader$evaluateJsonPointer$lookupNext$1.invoke(SchemaLoader.kt:366)
	at com.github.erosb.jsonsKema.SchemaLoader.enterScope(SchemaLoader.kt:176)
	at com.github.erosb.jsonsKema.SchemaLoader.evaluateJsonPointer$lookupNext(SchemaLoader.kt:366)
	at com.github.erosb.jsonsKema.SchemaLoader.access$evaluateJsonPointer$lookupNext(SchemaLoader.kt:107)
	at com.github.erosb.jsonsKema.SchemaLoader$evaluateJsonPointer$1.invoke(SchemaLoader.kt:404)
	at com.github.erosb.jsonsKema.SchemaLoader$evaluateJsonPointer$1.invoke(SchemaLoader.kt:403)
	at com.github.erosb.jsonsKema.SchemaLoader.runWithChangedBaseURI(SchemaLoader.kt:412)
	at com.github.erosb.jsonsKema.SchemaLoader.evaluateJsonPointer(SchemaLoader.kt:403)
	at com.github.erosb.jsonsKema.SchemaLoader.resolve(SchemaLoader.kt:353)
	at com.github.erosb.jsonsKema.SchemaLoader.loadSchema(SchemaLoader.kt:305)
	at com.github.erosb.jsonsKema.SchemaLoader.loadRootSchema(SchemaLoader.kt:290)
	at com.github.erosb.jsonsKema.SchemaLoader.invoke(SchemaLoader.kt:184)

So it looks like it tries to resolve the "ddd" header from the root schema, when it is defined within the subSchema itself.

Would it be possible to fix the issue as it blocks our project from upgrading from everit library?

Thank you!

Best regards,
Aleksandr.

Don't use java.net.URLDecoder.decode(String, Charset) to lower minimum Android API level from 33

When using this library, calls to the static method java.net.URLDecoder.decode(String, Charset) force a minimum Android API level 33[1].

In order to allow using this library on earlier android api versions, code like the following should be replaced throughout the library:

-URLDecoder.decode(s, StandardCharsets.UTF_8)
+URLDecoder.decode(s, StandardCharsets.UTF_8.name())

[1]: https://developer.android.com/reference/java/net/URLDecoder#decode(java.lang.String,%20java.nio.charset.Charset)

Format "date-time" requiring

Create a schema:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "Timestamp Test",
    "type": "object",
    
    "properties": {
	"@timestamp": {
	    "description": "The UTC date and time the event was created",
	    "type": "string",
	    "format": "date-time"
	}
    }
}

Create three test JSON files:

{
    "@timestamp": "2023-07-06T20:20:10.388-02:00"
}
{
    "@timestamp": "2023-07-06T20:20:10.388Z"
}
{
    "@timestamp": "2023-07-06T20:20:10.388"
}

The first two will validate against the schema, the third one does not.

The standard ISO 8601 date/time specification makes the timezone specification optional. Other JSON Schema libraries handle this correctly (e.g., "check-jsonschema").

A list of supported and unsupported (todo) features

Hi

Thanks for providing this library. I am looking to use it in my projects. The "About" section of the library says "(under development)". I am assuming there are some features of 2020-12 which are missing in it right now.

Is there a list detailing supported and unsupported features? Such a list will help in tracking progress and help contributors effectively contribute to this library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.