{"id":21031493,"url":"https://github.com/slaveofcode/jkt","last_synced_at":"2025-05-15T11:33:39.419Z","repository":{"id":29241505,"uuid":"118779935","full_name":"slaveofcode/jkt","owner":"slaveofcode","description":"Simple helper to parse JSON based on independent schema","archived":false,"fork":false,"pushed_at":"2022-12-30T20:14:07.000Z","size":285,"stargazers_count":24,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-10T16:47:58.293Z","etag":null,"topics":["enum","javascript","jkt","json","json-enum","json-struct","json-structure","json-types","parser","parsing","struct"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slaveofcode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-24T14:57:26.000Z","updated_at":"2024-05-31T15:55:09.000Z","dependencies_parsed_at":"2023-01-14T14:28:32.919Z","dependency_job_id":null,"html_url":"https://github.com/slaveofcode/jkt","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveofcode%2Fjkt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveofcode%2Fjkt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveofcode%2Fjkt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaveofcode%2Fjkt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slaveofcode","download_url":"https://codeload.github.com/slaveofcode/jkt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225349242,"owners_count":17460341,"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","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":["enum","javascript","jkt","json","json-enum","json-struct","json-structure","json-types","parser","parsing","struct"],"created_at":"2024-11-19T12:28:58.869Z","updated_at":"2024-11-19T12:28:59.613Z","avatar_url":"https://github.com/slaveofcode.png","language":"JavaScript","readme":"\u003cimg src=\"https://raw.github.com/slaveofcode/jkt/master/logos/jkt400.png\" align=\"right\" /\u003e\n\n# JKT Parser\n\nSimple helper to parse your JSON.\n\n**UPDATE:** Take a look at `Podeng` a similar parser like JKT with richer features, go [visit the project here](https://github.com/slaveofcode/podeng) \n\u003c!-- TOC --\u003e\n\n* [JKT Parser](#jkt-parser)\n  * [Background](#background)\n    * [Requirements](#requirements)\n    * [Installing](#installing)\n  * [Running the tests](#running-the-tests)\n  * [API References](#api-references)\n    * [Struct](#struct)\n    * [Available Types](#available-types)\n    * [Instance of Struct](#instance-of-struct)\n    * [One Line vs Multi Line](#one-line-vs-multi-line)\n    * [Custom Predefined Value](#custom-predefined-value)\n    * [Extending Struct](#extending-struct)\n    * [Removing Parent Property](#removing-parent-property)\n    * [Check The Instance and Child](#check-the-instance-and-child)\n    * [Strict Types](#strict-types)\n    * [ENUM Value](#enum-value)\n    * [Nested Struct](#nested-struct)\n    * [Array Container](#array-container)\n    * [Custom Value Translator](#custom-value-translator)\n    * [Arrow Mapping Key -\u003e Values](#arrow-mapping-key---values)\n    * [Struct \u0026 Instance References](#struct--instance-references)\n    * [Struct Property \u0026 Function](#struct-property--function)\n    * [Instance Function](#instance-function)\n  * [Author](#author)\n  * [License](#license)\n  * [Acknowledgments](#acknowledgments)\n\n\u003c!-- /TOC --\u003e\n\n## Background\n\nAt the first time I wonder how could I make my JSON to be more manageable. So confusing when every time I checking up the right parameters to my function, make sure the produced JSON data are valid and parsing all over the JSON properties to follow my rules (types).\n\nThen I do research and no one module is available to fit in with my case, so I built this one.\n\n**JKT** is a simple **Javascript** module to create a structure for your JSON. It's basically just a simple parser to handle property types, the structure and provide a small helper to handle the data.\n\n### Requirements\n\nTo use JKT you need a NodeJS version `6.4.0` and up. Basically JKT really depends on ES6 style which using template literal in practice.\n\n```\nconst jkt = require('jkt') // CommonJs\n\nconst Person = jkt`\n  name: String\n  age: Number\n  birthday: Date\n  hobbies: Array\n`\n```\n\n### Installing\n\nAs described before, you need NodeJs with version `6.4.0` and up before using this module. After that installing JKT is just simply as.\n\n\u003e Using NPM\n\n```\nnpm i jkt --save\n```\n\n\u003e Using Yarn\n\n```\nyarn add jkt\n```\n\nWhen finished you'll notice that this modules requires some libraries like `lodash`, `moment` and `shortid`.\n\n## Running the tests\n\nThe test is very very simple, you just have to clone the project, do `npm install` and run `npm run test`, nothing special.\n\n## API References\n\n### Struct\n\nYou just have to define the JKT struct once and then you could rely on them. The struct is defined by using template literal.\n\n```\nconst Person = jkt`\n  name: String\n  age: Number\n  birthday: Date\n  Hobbies: Array\n`\n```\n\n### Available Types\n\n| Type         | Description                                                                                                                                      | Show on Invalid? | Show on JSON result |\n| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | ------------------- |\n| `String`     | String type value                                                                                                                                | Yes              | Yes                 |\n| `String!`    | Force to only accept string value                                                                                                                | No               | No                  |\n| `Number`     | Numeric type value, works for either Integer or Float                                                                                            | Yes              | Yes                 |\n| `Number!`    | Force to only accept numeric value                                                                                                               | No               | No                  |\n| `Boolean`    | Boolean type value, works for either Integer or Float                                                                                            | Yes              | Yes                 |\n| `Boolean!`   | Force to only accept boolean value                                                                                                               | No               | No                  |\n| `Date`       | Date type value that accept `ISO 8601`, supported by `Moment` and it is timezone aware (will convert to UTC time) based on your machine timezone | Yes              | Yes                 |\n| `Date!`      | Force to only accept valid date value and will produce timezone aware date                                                                       | No               | No                  |\n| `DatePlain`  | Date type value that accept `ISO 8601`, supported by `Moment` and it is not timezone aware                                                       | Yes              | Yes                 |\n| `DatePlain!` | Force to only accept valid date value and will not produce timezone aware date                                                                   | No               | No                  |\n| `Array`      | Array type value                                                                                                                                 | Yes              | Yes                 |\n| `Array!`     | Force to only accept array value                                                                                                                 | No               | No                  |\n| `Object`     | Object type value                                                                                                                                | Yes              | Yes                 |\n| `Object!`    | Force to only accept object value                                                                                                                | No               | No                  |\n| `Function`   | Function type value                                                                                                                              | No               | No                  |\n| `Function!`  | Force to only accept function                                                                                                                    | No               | No                  |\n| `ANY`        | Any type value will be valid                                                                                                                     | Yes              | Yes                 |\n\n### Instance of Struct\n\nYou can assume the `Person` as a structure for json data, then every time you do parsing, you just have to pass an argument into `Person`.\n\n```\nconst aditya = Person({\n  name: \"Aditya Kresna\",\n  age: '26',\n  birthday: '1991-06-18' // ISO 8601\n})\n\n// now aditya is the instance of Person\n```\n\nThen you could use `aditya` properties or produce valid JSON format from it\n\n```\naditya.name // \"Aditya Kresna\"\naditya.birthday // moment time\naditya.toJSON() // produce valid json format\naditya.j() // the shorthand method\n```\n\nOne thing that you should know is if JKT fails to identify type of the value, it will returning `null` as a default, except you use **force** type like `String!` and `Number!`\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/jkt-basic)**\n\n### One Line vs Multi Line\n\nThere is a few method you can follow while making a struct, **One Line** and **Multi Line**. If you think your struct object is short and don't wanna make more space with using multi lines, you could simply create a struct separated by comma `,`.\n\n```\nconst Animal = jkt`type: String, color: String, isWild: Boolean`\n```\n\nor by multiple lines like this\n\n```\nconst Animal = jkt`\n  type: String\n  color: String\n  isWild: Boolean\n`\n\nconst Animal2 = jkt`\n  type: String,\n  color: String,\n  beast: Boolean\n`\n\nconst Animal3 = jkt`\n  type: String!,\n  color: String!,\n  beast: Boolean\n`\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/jkt-one-line-vs-multi-line)**\n\n### Custom Predefined Value\n\nWhen you need to setup custom value upfront, without checking it's type or doing some validations, You could use it as a predefined value by put them inside of expression `${}`. Predefined value is the value you define when defining the struct.\n\n```\nconst Mother = jkt`\n  name: String\n  birthday: Date\n  haveChild: ${true}\n`\n\nconst angela = Mother({\n  name: \"Angela\",\n  Birthday: \"1990-06-06\"\n})\n\nconst christy = Mother({\n  name: \"Angela\",\n  Birthday: \"1990-06-06\",\n  haveChild: false\n})\n\nconst Person = jkt`\n  name: String\n  sayTheWords: ${(words) =\u003e `Hi, ${words}`},\n  someOptions: ${{some: \"options\"}}\n`\n\nconst aditya = Person({\n  name: \"Aditya\"\n})\n\nangela.haveChild // true\nchristy.haveChild // false\n\naditya.sayTheWords('How are you') // \"Hi, How are you\"\n\naditya.j()\n// { name: \"Aditya\", someOptions: { some: \"options\" } }\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/custom-predefined-value)**\n\nYou could pass anything you want, but if you pass a `function` for example, it will not showing on the output when you calling `toJSON` or `j` function, because the value wasn't a valid JSON type.\n\n### Extending Struct\n\nOnce you define a struct it possible to extend into another struct.\n\n```\nconst Person = jkt`\n  name: String\n  age: Number\n  hobby: Array\n  birthday: Date\n`\n\nconst Driver = Person`\n  useBike: Boolean\n  useCar: Boolean\n`\n\nconst Doctor = Person`\n  specialist: String\n  hospitalLocation: String\n`\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/extending-struct)**\n\nBoth of `Driver` and `Doctor` is a child of `Person`, so you will get the `name`, `age`, `hobby` and `birthday` properties when you do parse of the `driver` and `doctor` instance.\n\n### Removing Parent Property\n\nSometimes we want to extend from existing struct but on a few situation we don't wanna include some properties. By using `!DELETE` we can exclude the property when extending from existing struct.\n\n```\nconst Person = jkt`\n  name: String\n  age: Number\n  hobby: Array\n  drinkBeer: Boolean\n`\n\nconst Child = Person`\n  toys: Array\n  drinkBeer: !DELETE   // this \"drinkBeer\" will be deleted on child struct\n`\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/removing-parent-property)**\n\n### Check The Instance and Child\n\nIt is also possible to checking the instance and child.\n\n```\nconst Person = jkt`\n  name: String\n  age: Number\n  hobby: Array\n`\nconst Child = Person`\n  toys: Array\n  doingHomework: Boolean\n`\n\nconst Mother = Person`\n  singleParent: Boolean\n`\n\nconst John = Child({\n  name: \"John Doe\"\n})\n\nChild.childOf(Person) // true\nMother.childOf(Person) // true\n\nJohn.instanceOf(Person) // true\nJohn.instanceOf(Child) // true\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/check-the-instance-and-child)**\n\n### Strict Types\n\nAs mentioned before (on a table), every unsupplied value or invalid type would make the property have `null` value when parsed. But we can force the property to not exist when invalid value raised.\n\n```\nconst Person = jkt`\n  name: String\n  age: Number!\n  hobby: Array!\n`\n\nconst John = Person({ name: \"John Doe\", age: \"not sure\"})\n\nJohn.j() // { name: \"John Doe\" }\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/strict-types)**\n\n### ENUM Value\n\nWe often need to reference some value based on it's own defined types. This could be done with `ENUM`, where ENUM is a feature when we need some property to strictly follow the type as we defined on ENUM itself.\n\n```\nconst Colors = jkt.ENUM`\n  RED: Maroon\n  WHITE\n  BLUE: ${'just blue'}\n`\n\nconst TSize = jkt.ENUM`small, medium, large, extra_large: ${'EXTRA-LARGE'}`\n\nconst TShirt = jkt`\n  model: String\n  brand: Number!\n  color: ${Colors}\n  size: ${TSize}\n`\n\n// Calling enum directly\nColors() // { RED: 'Maroon', WHITE: 'WHITE', BLUE: 'just blue' }\n\nTSize() // { SMALL: 'SMALL', MEDIUM: 'MEDIUM', LARGE: 'LARGE', EXTRA_LARGE: 'EXTRA-LARGE' }\n\n\n// Callling enum from struct using \"E\" property\nTShirt.E.COLOR.RED // \"Maroon\"\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/enum-value)**\n\nThe `E` stands for the collection of the ENUM on `TShirt`. If you want to see complete values of ENUM just take the `E` property.\n\nAll enum properties and value would be converted to **Upper-Case** string (even if it's a number), it doesn't accept any special characters except underscore `_` and If you want to set custom value just use an expression `${}`.\n\n### Nested Struct\n\nEvery single struct we define is an independent structure that could be used with another struct. By this point you got a very reusable component as you may need the same structure on another struct (eg. as a collection).\n\n```\nconst Person = jkt`\n  name: String\n  age: Number\n  birthday: Date\n`\n\nconst SchoolClass = jkt`\n  name: String\n  grade: Number\n  teacher: ${Person}\n`\n\n// show the schema\nSchoolClass.schema\n\n/**\n{\n  name: \"String\",\n  grade: \"Number\",\n  teacher: {\n    name: \"String\",\n    age: \"Number\",\n    birthday: \"Date\"\n  }\n}\n*/\n\nconst mySchoolClass = SchoolClass({\n  name: 'Awesome Class',\n  grade: '10',\n  teacher: {\n    name: 'Amelia',\n    age: 25,\n    birthday: '1992-05-31' // ISO 8601\n  }\n})\n\nmySchoolClass.j()\n/**\n{ name: \"Awesome Class\",\n  grade: 10,\n  teacher: {\n    name: \"Amelia\",\n    age: 25,\n    birthday: \"1992-05-30T17:00:00.000Z\"\n  }\n}\n*/\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/nested-struct)**\n\n### Array Container\n\nContainer to keep our struct inside json array.\n\n```\nconst Person = jkt`\n  name: String\n  age: Number\n  birthday: Date\n`\n\nconst SchoolClass = jkt`\n  name: String\n  grade: Number\n  students: ${jkt.c.array(Person)}\n`\n\nconst strictNull = false  // if some value has null, the item will not added into list\nconst defaultToArray = true // set default value to array ( not null )\nconst People = jkt.array(Person, strictNull, defaultToArray)\n\nconst listOfPeople = People([\n  {\n    name: 'Aditya',\n    age: '27',\n    birthday: '1991-06-18',\n  },\n  {\n    name: 'John',\n    age: '20',\n    birthday: '1996-10-04',\n  },\n])\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/array-container)**\n\n### Custom Value Translator\n\nWith all of provided parsers, I believe there is always not enough to cover up our desired types. So here's translator comes in.\n\n```\nconst Person = jkt`\n  name: String\n  age: Number\n  birthday: ${jkt.trans.custom(val =\u003e \"I'm old man =,=\")}\n`\n\nconst nina = Person({\n  name: \"Nina\",\n  age: \"25\",\n  birthday: new Date() // this will produce \"I'm old man =,=\"\n});\n\nnina.birthday // \"I'm old man =,=\"\nnina.j().birthday // \"I'm old man =,=\"\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/translator-custom-value)**\n\n### Arrow Mapping Key -\u003e Values\n\nWith mapping you could reuse key-value on supplied json to make your own custom key based on that source.\n\n```\nconst Person = jkt`\n  name: String\n  name-\u003efull_name: String // mapping from source key (name) to new key (full_name)\n  address: String\n  address-\u003eaddress2: String // mapping from source key (address) to new key (address2)\n  age: Number\n  age-\u003eageInString: String // mapping from source key (age) to new key (ageInString) with type String\n`\n\nconst aditya = Person({\n  name: \"Aditya\",\n  age: \"27\",\n  address: \"Kota Bekasi\"\n});\n\naditya.name // \"Aditya\"\naditya.full_name // \"Aditya\"\naditya.address2 // \"Kota Bekasi\"\naditya.age // 27\naditya.ageInString // \"27\"\n```\n\n**[\u003e See the result on RunKit](https://runkit.com/zeandcode/arrow-mapping)**\n\n### Struct \u0026 Instance References\n\nThese are detailed function \u0026 properties you could use when using jkt struct. You shouldn't use the following reserved words as a property for your struct, because it was reserved to support the module.\n\n### Struct Property \u0026 Function\n\n| Name       | Type           | Description                                                                                                            |\n| ---------- | -------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| `isJKT`    | Boolean (true) | Nothing special about this, just used to to identify JKT struct on internal parser.                                    |\n| `schema`   | JSON           | Schema of struct, you could inspect this property after defining the struct.                                           |\n| `childOf`  | Function       | To check if the struct is a child of the given struct                                                                  |\n| `__id`     | String         | The id of struct, every struct has an unique id generated based on `shortid` library                                   |\n| `__schema` | JSON           | The dirty schema of the struct which used internally to parse value                                                    |\n| `E`        | JSON           | A container of all enum values on the struct, this property only available when we set some property with `ENUM` type. |\n\n### Instance Function\n\n| Name             | Description                                                                                                                     |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| `instanceOf`     | To identify the instance of struct                                                                                              |\n| `getSchema`      | To get struct schema from the instance                                                                                          |\n| `getDirtySchema` | To get the real struct schema from the instance. The result including the function and properties to do parse inside the module |\n| `toJSON`         | To get valid json from the instance.                                                                                            |\n| `j`              | To get valid json from the instance. This is a shorthand method of `toJSON`                                                     |\n| `toString`       | To get json string from the instance.                                                                                           |\n\n## Author\n\n* **Aditya Kresna Permana** - _Indonesia_ - [SlaveOfCode](https://github.com/slaveofcode)\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details\n\n## Acknowledgments\n\n* This module may have some limitation based on reserved naming of the methods and properties\n* Highly inspired with styled-components style\n* This module may still buggy, make a pull request or make an issue if you found them.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslaveofcode%2Fjkt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslaveofcode%2Fjkt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslaveofcode%2Fjkt/lists"}