PHPackages                             dotink/jin - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. dotink/jin

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

dotink/jin
==========

Jsonified Ini Notation

5.6.1(1y ago)1410.2k↓50%12MITPHPPHP &gt;=8.2

Since Jun 6Pushed 1y ago1 watchersCompare

[ Source](https://github.com/dotink/jin)[ Packagist](https://packagist.org/packages/dotink/jin)[ RSS](/packages/dotink-jin/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (3)Versions (48)Used By (2)

JIN - Jsonified Ini Notation
============================

[](#jin---jsonified-ini-notation)

JIN is data format which uses the structure of an INI file with JSON-like values.

It is a simple and informal language which is most suitable for confgiruation data and settings. It works best as a metaconfiguration or schema configuration of sorts, but can also just give rich type and object support to something as simple as a `.env` file.

In some ways it is similar to TOML (), but does not have a formal specification. Parsing rules can best be described as follows:

- File structure is that of an INI file
    - key = value
    - \[section\]
    - ; comment
- Values are JSON-like with the following differences
    - Escaped character, e.g. \\n, \\b, \\t are not supported
    - A single \\ does not need to be escaped

Basic Usage
-----------

[](#basic-usage)

```
$jin_parser  = new Dotink\Jin\Parser()
$jin_string  = file_get_contents('config.jin');
$config_data = $jin_parser->parse($jin_string)->get();
```

Calling `get()` on the collection will return the full parsed data as an associative array.

If you'd rather work directly with the collection you can leave off the `get()`. You can see more documentation about the collection at ():

```
$config = $jin_parser->parse($jin_string);
```

Using the collection directly will allow you to use the "dot notation" to reference and retrieve specific values, as well as to supply defaults if they don't exist:

```
$config->get('database.connections.default', [
	'name' => 'website',
	'host' => 'localhost',
	'user' => 'web',
	'pass' => '3ch0th3w4lRUS'
]);
```

You can, additionally, preserve `stdClass` objects in parsed JSON by passing FALSE to the second parameter:

```
$config_data = $jin_parser->parse($jin_string, FALSE)->get();
```

The Language
------------

[](#the-language)

### A Simple Field

[](#a-simple-field)

```
field = value ; INI style string
```

Strings don't have to be quoted, but can be:

```
field = "value" ; JSON style string
```

Integers are converted to the proper type automatically:

```
integerValue = 1
```

Floats too...

```
floatValue = 1.03
```

Booleans and NULL values are case insensitive:

```
boolValue = false
```

```
boolValue = TRUE
```

```
nullValue = NULL
```

### Multi-Line Text

[](#multi-line-text)

```
multi = JIN supports multi-line values until the new line resembles
an INI database structure.  So, for example, this line would be parsed
with new lines preserved until `foo=bar` or `[section]` or `\n\n`.
```

### Comments

[](#comments)

Comments are allowed anywhere in a value, so it is important to keep in mind that anything after an `;` character is going to be cut off.

```
field = "This probably does not do what you expect; this is stripped"
```

### JSON-like Values

[](#json-like-values)

Arrays are defined literally:

```
favoriteFoods = ["Tacos", "Sushi", "Curry"]
```

Objects are also defined literally too:

```
favorites = {"food":  "Indian", "music": "Classic Rock"}
```

Both can span multiple lines and contain comments:

```
multiFoods = [
	"Tacos",
	"Sushi", ; Most keto friendly
	"Curry"
]

multiFavorites = {
	;
	; The basics
	;

	"food": "Tacos",
	"music": "Classic Rock" ; Not actually my favorite
}
```

#### Differences

[](#differences)

Although values can be JSON-like, they are not, strictly speaking, JSON. The major difference is that they do not support JSON's built in escaped characters, so you cannot use `\n` or `\t`. On the bright side, you do not need to escape a backslash:

```
middlewares = [
	"App\Middleware\ResponseHandler"
]
```

### Sections

[](#sections)

Sections provide an alternative to JSON object structures. Note, sections are never parsed as `stdClass` objects, but will always return associative arrays.

```
[category]

	fieldOne   = valueOne
	fieldTwo   = valueTwo
	fieldThree = 1
	fieldFour  = [0, 7, 9, 13]
	fieldFive  = {
		"foo": "bar"
	}
```

### Sub-Sections

[](#sub-sections)

You can add sub-sections by separating the previous category name by a dot. This is extremely useful for keyed configuration values with repeating data, for example, imagine a database config with multiple aliases connections:

```
[database]

	[database.connections.default]
		driver = pgsql
		dbname = website
		host   = localhost

	[database.connections.forums]
		driver = mysql
		dbname = forums
		host   = localhost
		user   = web
		pass   = 3ch0th3w4lRUS
```

### Section References

[](#section-references)

You can reference a parent section for shorter section names.

```
[database]

	[&.connections.default]
		driver = pgsql
		dbname = website
		host   = localhost
```

References can be stacked to refer to sub-sub-sections. Reference stacking always begins from the last section defined without a reference:

```
[database]

	[&.connections]

		;
		; This section contains all of our database connections
		;

		[&&.default]
			driver = pgsql
			dbname = website
			host   = localhost
```

Environment Variables
---------------------

[](#environment-variables)

You can get values from the environment.

```
envField = env(DEBUGGING)
```

And provide defaults when they are not set:

```
envField = env(DEBUGGING, TRUE)
```

Native Language Values
----------------------

[](#native-language-values)

You can use native language functions (in this implementation, PHP):

```
runField = run(md5('hash this thing'))
```

You can add context to the parser for access to variables as well:

```
$jin_parser  = new Dotink\Jin\Parser([
	'app' => $app
]);
```

Then access/use them as you'd expect:

```
cacheDirectory = run($app->getDirectory('storage/cache', TRUE))
```

Custom Functions
----------------

[](#custom-functions)

You can add custom functions by passing an array of callables keyed by the function name as the second parameter to the parser:

```
$jin_parser  = new Dotink\Jin\Parser([], [
	'hello' => function($name) {
		return 'Hello ' . $name;
	}
]);
```

Then use them as you'd expect.

```
hello = hello(Matt)
```

Note, you can overload the `env()` and even the `run()` function, however, overloading structures such as `map()`, `def()`, `inc()` will not work.

### Templates

[](#templates)

Templates provide a powerful way to duplciate complex data structures with different values:

```
[database]

	settings = def(type, name, host, user, pass) {
		{
			"type": $type,
			"name": $name,
			"host": $host,
			"auth": {
				"user": $user,
				"pass": $pass
			}
		}
	}

	[&.connections]

		default = inc(database.settings) {
			pgsql
			my_database
			localhost

			;
			; Do not be afraid to use any valid value where values are
			; specified
			;

			env(DB_USER, web)
			env(DB_PASS, NULL)
		}
```

Templates can also be used to create arrays of non-keyed objects:

```
[routing]

	route = def(methods, pattern, target) {
		{
			"methods": $methods,
			"pattern": $pattern,
			"target": $target
		}
	}

	;
	; The map function takes a tab separated list of values.  Multiple tabs
	; are reduced to one before parsing.
	;

	routes = map(routing.route) {
		["GET"]		/		ViewHome
		["GET"]		/articles	ListArticles
		["POST"]	/articles	CreateArticle
		["GET"]		/articles/{id}	ViewArticle
		["POST"]	/articles/{id}	EditArticle
	}
```

Testing
-------

[](#testing)

```
php vendor/bin/phpunit --bootstrap vendor/autoload.php test/routines/

```

Addendum
--------

[](#addendum)

JIN was originally written as a way to configure a data mapper ORM. It is a very flexible and intuitive language, but it may not make sense in all cases. It is strongly recommended that if you are using it for frequently accessed configurations (like during runtime) that you serialize and cache the resulting collection rather than parsing it on every load.

### Editor Support

[](#editor-support)

There is a hobbled together grammar file for Atom which can be found here:

Because of its similarity to TOML, TOML syntax highlighting also tends to look well. You can alternatively try JS/JSON syntax highlighting, but your mileage may vary depending on syntax highlighting implementations.

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance46

Moderate activity, may be stable

Popularity31

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity88

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~78 days

Recently: every ~0 days

Total

47

Last Release

415d ago

Major Versions

1.2.5 → 2.0.02018-10-06

2.5.1 → 3.0.02018-10-15

3.8.1 → 4.0.02022-03-29

4.9.0 → 5.0.02025-03-21

PHP version history (2 changes)1.0PHP &gt;=5.4.0

5.0.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/4ab2b91daf2aa6e4c7f98f785a3135daa3e9998bd7021d89df05a374e28ecde5?d=identicon)[mattsah](/maintainers/mattsah)

---

Top Contributors

[![mattsah](https://avatars.githubusercontent.com/u/586346?v=4)](https://github.com/mattsah "mattsah (59 commits)")

---

Tags

keyword

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/dotink-jin/health.svg)

```
[![Health](https://phpackages.com/badges/dotink-jin/health.svg)](https://phpackages.com/packages/dotink-jin)
```

###  Alternatives

[donatello-za/rake-php-plus

Yet another PHP implementation of the Rapid Automatic Keyword Extraction algorithm (RAKE).

271865.1k10](/packages/donatello-za-rake-php-plus)[cognesy/instructor-php

The complete AI toolkit for PHP: unified LLM API, structured outputs, agents, and coding agent control

310107.9k1](/packages/cognesy-instructor-php)[crwlr/crawler

Web crawling and scraping library.

37214.8k2](/packages/crwlr-crawler)[lingaro/magento2-codegen

Magento 2 Code Generator

966.5k](/packages/lingaro-magento2-codegen)[jeffreyvanrossum/wp-settings

Handy wrapper to make creating WordPress settings pages a breeze.

902.6k1](/packages/jeffreyvanrossum-wp-settings)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
