{"id":29791180,"url":"https://github.com/dashjoin/jsonata-java","last_synced_at":"2025-07-28T00:15:24.298Z","repository":{"id":184296749,"uuid":"668664370","full_name":"dashjoin/jsonata-java","owner":"dashjoin","description":"JSONata reference ported to Java","archived":false,"fork":false,"pushed_at":"2025-07-24T14:09:14.000Z","size":481,"stargazers_count":78,"open_issues_count":12,"forks_count":11,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-24T17:50:26.541Z","etag":null,"topics":["java","json","jsonata","reference"],"latest_commit_sha":null,"homepage":"https://dashjoin.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dashjoin.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-07-20T10:22:28.000Z","updated_at":"2025-07-24T14:09:18.000Z","dependencies_parsed_at":"2023-07-27T20:54:51.812Z","dependency_job_id":"7637379d-f5bb-4764-a319-3651428afa55","html_url":"https://github.com/dashjoin/jsonata-java","commit_stats":null,"previous_names":["dashjoin/jsonata-java"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/dashjoin/jsonata-java","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjsonata-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjsonata-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjsonata-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjsonata-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dashjoin","download_url":"https://codeload.github.com/dashjoin/jsonata-java/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjsonata-java/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267443120,"owners_count":24087945,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","json","jsonata","reference"],"created_at":"2025-07-28T00:15:19.526Z","updated_at":"2025-07-28T00:15:24.156Z","avatar_url":"https://github.com/dashjoin.png","language":"Java","readme":"# jsonata-java is the JSONata Java reference port\nJSONata reference ported to Java\n\nThis is a 1:1 Java port of the [JSONata reference implementation](https://github.com/jsonata-js/jsonata)\n\n## Features\n* [100% JSONata feature compatibility](https://github.com/dashjoin/jsonata-java/actions/runs/5717119540/job/15490217787)\n    - All JSONata language features supported\n    - [100% reference test coverage](https://github.com/dashjoin/jsonata-java/actions/runs/5717119540/job/15490217787) [with well justified exceptions](https://github.com/dashjoin/jsonata-java/blob/main/test/test-overrides.json)\n* Error messages matching the reference\n    - Even stack traces are comparable\n* Zero dependency and small\n    - Only 160 kB total size\n* [JSON parser agnostic](https://github.com/dashjoin/jsonata-java/blob/main/samples/json-interop.md)\n    - use with Jackson, GSon, ...\n    - comes with integrated vanilla parser\n* Performance optimized \u0026 thread safe\n    - [Native jsonata command line tool](https://github.com/dashjoin/jsonata-cli)\n* Enterprise support\n    - [Premium support available from the original developers](https://dashjoin.com)\n\n## Quick Start\n\nAdd the dependency in pom.xml:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.dashjoin\u003c/groupId\u003e\n    \u003cartifactId\u003ejsonata\u003c/artifactId\u003e\n    \u003cversion\u003e0.9.8\u003c/version\u003e\n\u003c/dependency\u003e\n```\nHere is the [release change log](changelog.md)\n\nMain.java program:\n```Java\nimport java.util.List; import java.util.Map;\nimport static com.dashjoin.jsonata.Jsonata.jsonata;\n\npublic class Main {\n    public static void main(String[] args) {\n\n        var data = Map.of(\"example\",\n            List.of(\n                Map.of(\"value\", 4),\n                Map.of(\"value\", 7),\n                Map.of(\"value\", 13)\n            )\n        );\n        \n        var expression = jsonata(\"$sum(example.value)\");\n        var result = expression.evaluate(data);  // returns 24\n        System.out.println(result);\n    }\n}\n```\n\n### Custom Functions\n\nYou can define custom functions and declare variables via a JSONata frame or \nthe registerFunction method:\n\n```Java\n        var expression = jsonata(\"$sum(example.value) + $sin($PI/2)\");\n\n        // Default JSONata has no $sin function and no $PI, so define it\n        var env = expression.createFrame();\n        env.bind(\"sin\", (Number n) -\u003e Math.sin( n.doubleValue() ) );\n        env.bind(\"PI\", Math.PI);\n\n        var result = expression.evaluate(data, env);  // returns 25\n```\n\nFor more examples, please refer to this [test case](https://github.com/dashjoin/jsonata-java/blob/main/src/test/java/com/dashjoin/jsonata/CustomFunctionTest.java).\n\n## History\nWe needed a high performance and 100% compatible engine for the ETL and data transformations of the [Dashjoin Low Code platform](https://github.com/dashjoin/platform). Being a JSON full stack based on Quarkus/Java, JSONata was a very good fit and is even more today.\n\nIn the beginning we used the original Java port, but quickly got lots of issues due to unsupported features and errors that we could not reproduce easily.\nThe next solution which was running quite well and stable was to use GraalVM's Javascript engine to run the jsonata-js reference implementation in process of the Java backend. This works OK, but there are performance compromises, especially when there are many switches between the Javascript and the Java context (as is the case with ETL and data transformations).\n\n## Design\nWorking with Java since its inception in 1996, we made an experiment to see what it would take to port the existing reference Javascript into working and performant Java. This experiment went so well that we decided to work on a 100% port of the JSONata reference engine - the result which you can see in this repository.\n\n### No generic Java types\nTo get a 1:1 readable port, we decided to not use any generic types (yes, so basically this looks like 20 years old Java code...) -\nbut it has many advantages in this specific case:\n* Java code nearly looks the same as Javascript\n* Patches and fixes coming into the Javascript reference are easily portable\n\nWe lose the type safety and compile time checks Java generics introduced, but since the job is to port Javascript code, we are in an 'un-typed' world anyway.\n\n### No JSON wrapper library\nTo get as near as possible to the Javascript syntax, decision was made to use\n* java.util.Map as Javascript object\n    - which in turn represents a JSON object\n* java.util.List as Javascript array\n    - which in turn represents JSON lists/JSONata sequences\n* String, numbers, and boolean can be used as well\n* [This test case](https://github.com/dashjoin/jsonata-java/blob/main/src/test/java/com/dashjoin/jsonata/TypesTest.java) documents which types are legal and how you can use a JSON library like Jackson to convert Pojos and other types\n\nNo JSON lib like Jackson is being used. This has advantages, but needs careful design w.r.t. how the logic is being ported.\n### The big 'null vs undefined' question\nPorting Javascript code gets ambiguous as soon as there is a boolean expression that might depend on null and/or undefined.\nIn Java there are basically these solutions:\n* use a Holder class that can disambiguate the null/undefined cases\n* Java null means null, use a special value/object for UNDEFINED_VALUE\n* Java null means undefined, use a special value/object for NULL_VALUE\n\nJSON libs will usually use a Holder variant (implemented in some JSONValue implementation).\nAfter review, it turned out that we can stay as near as possible to the original code structure (with as little special code as possible) by using the 3rd variant.\n\n### Numeric Values\n\nCompared to Java, Javascript handles numbers quite differently.\nWhenever a computation is done, the engine tries to \"fit\" the result into an int, long, or double (see com.dashjoin.jsonata.Utils.convertNumber(Number)).\nThis [test case](https://github.com/dashjoin/jsonata-java/blob/main/src/test/java/com/dashjoin/jsonata/NumberTest.java)\nshows this behavior.\n\n## Performance\nWe conducted some experiments to measure performance, but it's not an 'overall benchmark' yet. Your mileage may vary...\n\n|Expression| jsonata-js | JSONata4Java | jsonata-java | speedup factor |\n|----------|------------|--------------|---|---|\n| function-sift 4 | 26.1 / 109.6 | 36.1 / 144.8 | 140.8 / 348.2 | 3.9 / 2.3 |\n| hof-map 0 | 16.4 / 62.2 | 17.7 / 352.8 | 66.2 / 295.2 | 3.7 / 0.8 |\n| hof-zip 2 | 15.4 / 59.2 | 16.7 / exception | 64.2 / 312.6 | 3.8 / ? |\n| hof-zip-map 0 | 16.0 / 57.3 | 12.6 / 227.7 (wrong) | 58.3 / 323.6 | 4.6 / 1.4 |\n| partial-application 2 | 26.1 / 29.1 | parser error | 162.3 / 133.4 | ? / ? |\n| [1..500].($*$)~\u003e$sum | 24.4 / 1.8 | 159.6 / exception | 286.4 / 9.0 | 1.8 / ? |\n\n- Expression denotes the test suite name and case.\n- First figure = parse operations, second figure = evaluate operations.\n- Performance measured in kiloOps/s (thousands of operations per second), higher means faster.\n- Speedup factor compared to JSONata4Java (2.0 means \"twice as fast\").\n\n## Developers: getting started\n\nThe project uses the repository of the reference implementation as a submodule.\nThis allows referencing the current version of the unit tests.\nTo clone this repository, run:\n\n```\ngit clone --recurse-submodules https://github.com/dashjoin/jsonata-java\n```\n\nTo compile, generate / run the unit tests, and create the jar file, run:\n\n```\nmvn compile exec:java -Dexec.classpathScope=test -Dexec.mainClass=com.dashjoin.jsonata.Generate\nmvn install\n```\n\n## Contribute\n\nWe welcome contributions. If you are interested in contributing to Dashjoin, let us know!\nYou'll get to know an open-minded and motivated team working together to build the next generation platform.\n\n* [Join our Slack](https://join.slack.com/t/dashjoin/shared_invite/zt-1274qbzq9-mwxBq4WwSTJsITjrvYV4pA) and say hello\n* [Follow us](https://twitter.com/dashjoin) on Twitter\n* [Submit](https://github.com/dashjoin/jsonata-java/issues) your ideas by opening an issue with the enhancement label\n* [Help out](https://github.com/dashjoin/jsonata-java/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) by fixing \"a good first issue\"\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdashjoin%2Fjsonata-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdashjoin%2Fjsonata-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdashjoin%2Fjsonata-java/lists"}