Efficient, easy-to-use, and fast PHP JSON stream parser

Overview

JSON Machine

Very easy to use and memory efficient drop-in replacement for inefficient iteration of big JSON files or streams for PHP 5.6+. See TL;DR. No dependencies in production except optional ext-json.

Build Status Latest Stable Version Monthly Downloads



TL;DR

<?php

use \JsonMachine\JsonMachine;

// this often causes Allowed Memory Size Exhausted
- $users = json_decode(file_get_contents('500MB-users.json'));

// this usually takes few kB of memory no matter the file size
+ $users = JsonMachine::fromFile('500MB-users.json');

foreach ($users as $id => $user) {
    // just process $user as usual
}

Random access like $users[42] or counting results like count($users) is not possible by design. Use above-mentioned foreach and find the item or count the collection there.

Requires ext-json if used out of the box. See Decoders.

Introduction

JSON Machine is an efficient, easy-to-use and fast JSON stream/pull/incremental/lazy (whatever you name it) parser based on generators developed for unpredictably long JSON streams or documents. Main features are:

  • Constant memory footprint for unpredictably large JSON documents.
  • Ease of use. Just iterate JSON of any size with foreach. No events and callbacks.
  • Efficient iteration on any subtree of the document, specified by Json Pointer
  • Speed. Performance critical code contains no unnecessary function calls, no regular expressions and uses native json_decode to decode JSON document items by default. See Decoders.
  • Parses not only streams but any iterable that produces JSON chunks.
  • Thoroughly tested. More than 100 tests and 700 assertions.

Parsing JSON documents

Itearting a collection

Let's say that fruits.json contains this really big JSON document:

// fruits.json
{
    "apple": {
        "color": "red"
    },
    "pear": {
        "color": "yellow"
    }
}

It can be parsed this way:

<?php

use \JsonMachine\JsonMachine;

$fruits = JsonMachine::fromFile('fruits.json');

foreach ($fruits as $name => $data) {
    // 1st iteration: $name === "apple" and $data === ["color" => "red"]
    // 2nd iteration: $name === "pear" and $data === ["color" => "yellow"]
}

Parsing a json array instead of a json object follows the same logic. The key in a foreach will be a numeric index of an item.

If you prefer JSON Machine to return objects instead of arrays, use new ExtJsonDecoder() as decoder which by default decodes objects - same as json_decode

<?php

use JsonMachine\JsonDecoder\ExtJsonDecoder;
use JsonMachine\JsonMachine;

$objects = JsonMachine::fromFile('path/to.json', '', new ExtJsonDecoder);

Parsing a subtree

If you want to iterate only results subtree in this fruits.json:

// fruits.json
{
    "results": {
        "apple": {
            "color": "red"
        },
        "pear": {
            "color": "yellow"
        }
    }
}

use Json Pointer "/results" as the second argument:

<?php

use \JsonMachine\JsonMachine;

$fruits = JsonMachine::fromFile("fruits.json", "/results");
foreach ($fruits as $name => $data) {
    // The same as above, which means:
    // 1st iteration: $name === "apple" and $data === ["color" => "red"]
    // 2nd iteration: $name === "pear" and $data === ["color" => "yellow"]
}

Note:

Value of results is not loaded into memory at once, but only one item in results at a time. It is always one item in memory at a time at the level/subtree you are currently iterating. Thus, the memory consumption is constant.

Parsing nested values in arrays

The JSON Pointer spec also allows to use a hyphen (-) instead of a specific array index. JSON Machine interprets it as a wildcard which matches any array index (not any object key). This enables you to iterate nested values in arrays without loading the whole item.

Example:

// fruitsArray.json
{
    "results": [
        {
            "name": "apple",
            "color": "red"
        },
        {
            "name": "pear",
            "color": "yellow"
        }
    ]
}

To iterate over all colors of the fruits, use the JSON pointer "/results/-/color".

Getting single scalar values

You can parse sigle scalar value anywhere in the document the same way as a collection. Consider this example:

// fruits.json
{
    "lastModified": "2012-12-12",
    "apple": {
        "color": "red"
    },
    "pear": {
        "color": "yellow"
    },
    // ... gigabytes follow ...
}

Get the single value of lastModified key like this:

<?php

use \JsonMachine\JsonMachine;

$fruits = JsonMachine::fromFile('fruits.json', '/lastModified');
foreach ($fruits as $key => $value) {
    // 1st and final iteration:
    // $key === 'lastModified'
    // $value === '2012-12-12'
}

When parser finds the value and yields it to you, it stops parsing. So when a single scalar value is in the beginning of a gigabytes-sized file or stream, it just gets the value from the beginning in no time and with almost no memory consumed.

The obvious shortcut is:

<?php

use \JsonMachine\JsonMachine;

$fruits = JsonMachine::fromFile('fruits.json', '/lastModified');
$lastModified = iterator_to_array($fruits)['lastModified'];

Single scalar value access supports array indices in json pointer as well.

What is Json Pointer anyway?

It's a way of addressing one item in JSON document. See the Json Pointer RFC 6901. It's very handy, because sometimes the JSON structure goes deeper, and you want to iterate a subtree, not the main level. So you just specify the pointer to the JSON array or object you want to iterate and off you go. When the parser hits the collection you specified, iteration begins. It is always a second parameter in all JsonMachine::from* functions. If you specify a pointer to a non-existent position in the document, an exception is thrown. It can be used to access scalar values as well.

Some examples:

Json Pointer value Will iterate through
"" (empty string - default) ["this", "array"] or {"a": "this", "b": "object"} will be iterated (main level)
"/result/items" {"result":{"items":["this","array","will","be","iterated"]}}
"/0/items" [{"items":["this","array","will","be","iterated"]}] (supports array indices)
"/results/-/status" {"results":[{"status": "iterated"}, {"status": "also iterated"}]} (a hyphen instead of an array index)
"/" (gotcha! - a slash followed by an empty string, see the spec) {"":["this","array","will","be","iterated"]}

Parsing streaming responses from a JSON API

A stream API response or any other JSON stream is parsed exactly the same way as file is. The only difference is, you use JsonMachine::fromStream($streamResource) for it, where $streamResource is the stream resource with the JSON document. The rest is the same as with parsing files. Here are some examples of popular http clients which support streaming responses:

GuzzleHttp

Guzzle uses its own streams, but they can be converted back to PHP streams by calling \GuzzleHttp\Psr7\StreamWrapper::getResource(). Pass the result of this function to JsonMachine::fromStream function, and you're set up. See working GuzzleHttp example.

Symfony HttpClient

A stream response of Symfony HttpClient works as iterator. And because JSON Machine is based on iterators, the integration with Symfony HttpClient is very simple. See HttpClient example.

Tracking the progress

Big documents may take a while to parse. Call JsonMachine::getPosition() in your foreach to get current count of the processed bytes from the beginning. Percentage is then easy to calculate as position / total * 100. To find out the total size of your document in bytes you may want to check:

  • strlen($document) if you parse a string
  • filesize($file) if you parse a file
  • Content-Length http header if you parse a http stream response
  • ... you get the point
<?php

use JsonMachine\JsonMachine;

$fileSize = filesize('fruits.json');
$fruits = JsonMachine::fromFile('fruits.json');
foreach ($fruits as $name => $data) {
    echo 'Progress: ' . intval($fruits->getPosition() / $fileSize * 100) . ' %'; 
}

Decoders

As the third and optional parameter of all the JsonMachine::from* functions is an instance of JsonMachine\JsonDecoder\Decoder. If none is specified, ExtJsonDecoder is used by default. It requires ext-json PHP extension to be present, because it uses json_decode. When json_decode doesn't do what you want, implement JsonMachine\JsonDecoder\Decoder and make your own.

Available decoders

  • ExtJsonDecoder - Default. Uses json_decode to decode keys and values. Constructor takes the same parameters as json_decode.

  • PassThruDecoder - uses json_decode to decode keys but returns values as pure JSON strings. Useful when you want to parse a JSON item with something else directly in the foreach and don't want to implement JsonMachine\JsonDecoder\Decoder. Constructor has the same parameters as json_decode. Example:

<?php

use JsonMachine\JsonDecoder\PassThruDecoder;
use JsonMachine\JsonMachine;

$items = JsonMachine::fromFile('path/to.json', '', new PassThruDecoder);
  • ErrorWrappingDecoder - A decorator which wraps decoding errors inside DecodingError object thus enabling you to skip malformed items instead of dying on SyntaxError exception. Example:
<?php

use JsonMachine\JsonMachine;
use JsonMachine\JsonDecoder\DecodingError;
use JsonMachine\JsonDecoder\ErrorWrappingDecoder;
use JsonMachine\JsonDecoder\ExtJsonDecoder;

$items = JsonMachine::fromFile('path/to.json', '', new ErrorWrappingDecoder(new ExtJsonDecoder()));
foreach ($items as $key => $item) {
    if ($key instanceof DecodingError || $item instanceof DecodingError) {
        // handle error of this malformed json item
        continue;
    }
    var_dump($key, $item);
}

Error handling

Since 0.4.0 every exception extends JsonMachineException, so you can catch that to filter any error from JSON Machine library.

Skipping malformed items

If there's an error anywhere in a json stream, SyntaxError exception is thrown. That's very inconvenient, because if there is an error inside one json item you are unable to parse the rest of the document because of one malformed item. ErrorWrappingDecoder is a decoder decorator which can help you with that. Wrap a decoder with it, and all malformed items you are iterating will be given to you in the foreach via DecodingError. This way you can skip them and continue further with the document. See example in Available decoders. Syntax errors in the structure of a json stream between the iterated items will still throw SyntaxError exception though.

Parser efficiency

Streams / files

JSON Machine reads a stream (or a file) 1 JSON item at a time and generates corresponding 1 PHP array at a time. This is the most efficient way, because if you had say 10,000 users in JSON file and wanted to parse it using json_decode(file_get_contents('big.json')), you'd have the whole string in memory as well as all the 10,000 PHP structures. Following table shows the difference:

String items in memory at a time Decoded PHP items in memory at a time Total
json_decode() 10000 10000 20000
JsonMachine::from*() 1 1 2

This means, that JsonMachine is constantly efficient for any size of processed JSON. 100 GB no problem.

In-memory JSON strings

There is also a method JsonMachine::fromString(). If you are forced to parse a big string, and the stream is not available, JSON Machine may be better than json_decode. The reason is that unlike json_decode, JSON Machine still traverses the JSON string one item at a time and doesn't load all resulting PHP structures into memory at once.

Let's continue with the example with 10,000 users. This time they are all in string in memory. When decoding that string with json_decode, 10,000 arrays (objects) is created in memory and then the result is returned. JSON Machine on the other hand creates single structure for each found item in the string and yields it back to you. When you process this item and iterate to the next one, another single structure is created. This is the same behaviour as with streams/files. Following table puts the concept into perspective:

String items in memory at a time Decoded PHP items in memory at a time Total
json_decode() 10000 10000 20000
JsonMachine::fromString() 10000 1 10001

The reality is even better. JsonMachine::fromString consumes about 5x less memory than json_decode. The reason is that a PHP structure takes much more memory than its corresponding JSON representation.

Troubleshooting

"I'm still getting Allowed memory size ... exhausted"

One of the reasons may be that the items you want to iterate over are in some sub-key such as "results" but you forgot to specify a json pointer. See Parsing a subtree.

"That didn't help"

The other reason may be, that one of the items you iterate is itself so huge it cannot be decoded at once. For example, you iterate over users and one of them has thousands of "friend" objects in it. Use PassThruDecoder which does not decode an item, get the json string of the user and parse it iteratively yourself using JsonMachine::fromString().

<?php

use JsonMachine\JsonMachine;
use JsonMachine\JsonDecoder\PassThruDecoder;

$users = JsonMachine::fromFile('users.json', '', new PassThruDecoder);
foreach ($users as $user) {
    foreach (JsonMachine::fromString($user, "/friends") as $friend) {
        // process friends one by one
    }
}

"I am still out of luck"

It probably means that the JSON string $user itself or one of the friends are too big and do not fit in memory. However, you can try this approach recursively. Parse "/friends" with PassThruDecoder getting one $friend json string at a time and then parse that using JsonMachine::fromString()... If even that does not help, there's probably no solution yet via JSON Machine. A feature is planned which will enable you to iterate any structure fully recursively and strings will be served as streams.

Installation

composer require halaxa/json-machine

or clone or download this repository (not recommended because of no autoloading).

Development

Clone this repository. This library supports two development approaches:

  1. non containerized (PHP and composer already installed on your machine)
  2. containerized (Docker on your machine)

Non containerized

Run composer run -l in the project dir to see available dev scripts. This way you can run some steps of the build process such as tests.

Containerized

Install Docker and run make in the project dir on your host machine to see available dev tools/commands. You can run all the steps of the build process separately as well as the whole build process at once. Make basically runs composer dev scripts inside containers in the background.

Support

Do you like this library? Star it, share it, show it :) Issues and pull requests are very welcome.

License

Apache 2.0

Cogwheel element: Icons made by TutsPlus from www.flaticon.com is licensed by CC 3.0 BY

Table of contents generated with markdown-toc

Comments
  • Not decoding JSON

    Not decoding JSON

    I guess this sounds strange, but I need to process JSON files of GB in size... and I don't want to decode the nodes to arrays or objects. I just want the JSON!

    Obviously I could json_encode the array that's produced, but with millions of transactions it's worrying to put them through an unnecessary step where an error could be introduced in the decode/encode process.

    (The background is this: I have millions of user transactions to feed into a webhook. The webhook is expecting JSON formatted exactly in the way the nodes in the JSON blob are formatted. I just need to take each node, feed it to the webhook, check the response, and move onto the next one.)

    Any options here?

    enhancement 
    opened by JohnnyWalkerDesign 10
  • Getting un catchable errors on non JSON files

    Getting un catchable errors on non JSON files

    When calling fromFile on a wrong file format I get some uncatchable errors. I had this issue with both 0.7.0 and 1.1.1

    \JsonMachine\JsonMachine::fromFile($filename, "/myattribute");

    I get the following fatal error with a zip file, but I can also have similar issues with text files

    message: Undefined variable $P script: .../halaxa/json-machine/src/Parser.php line: 115

    Testing vars before $tokenType = ${$token[0]}; seems to be helful.

    if($token == null || !isset($token[0])|| !isset(${$token[0]})) { throw new JsonMachineException("Error parsing stream."); }

    opened by flavinus 9
  • Fix the parsing of nested sub-trees that use wildcards

    Fix the parsing of nested sub-trees that use wildcards

    Hey @halaxa! Long time since our last PR! 😄

    Your package keeps improving, I love the support for multiple JSON pointers ❤ī¸

    While updating my package (based on yours), I noticed that some changes are interrupting the iteration of nested sub-trees at the first matching JSON object and ignore the remaining iterations. Which appears to be the issue flagged here: https://github.com/halaxa/json-machine/issues/78

    This PR aims to bring the following changes:

    • let indexes of JSON arrays be integer within the current path. This brings 2 benefits:
      • accurate current path, JSON array indexes are actually integers
      • avoid the use of regular expressions to perform checks against parts of the path
    • fix how we compute the current path and current path wildcard
      • currently these paths are not cleaned when the current level drops by 2 or more levels
    • fix the parsing of nested sub-trees that use wildcards
      • currently they are interrupted after the first iteration
    • simplify and make the logic to compute the matching JSON pointer more accurate
    • improve and add one more test for parsing nested sub-trees using wildcards
    opened by cerbero90 9
  • Subtree continues to iterate after last item

    Subtree continues to iterate after last item

    Hi @halaxa

    Is there a way to stop iterating the subtree? I have a JSON file of 500 GB with 10 subtrees. Right now the code would continue iterating the subtree and thus wasting alot of time doing so.

    The problem is there is no way - with the current code base - to know how to break out of the for loop. I would argue that it is most useful that the iteration stops by it self instead of having to code a break your self. What do you think?

    Reference: #21

    opened by anotherdevs 9
  • Wildcard iterator on array bug?

    Wildcard iterator on array bug?

    json example:

    [ {"id":125}, {"id":785}, {"id":459}, {"id":853} ]

    php code:

    $items = JsonMachine::fromFile( dirname(__FILE__) . '/data/products.json', '/-/id');

    foreach ($items as $data) { echo $data; }

    output:

    125

    What I'm doing wrong? JSON pointers '/0/id', '/1/id', '/2/id', etc work great. But I can't seem to get the '-' wildcard working...

    bug question 
    opened by drasier 8
  • Ignore UTF BOM at the beginning of the stream

    Ignore UTF BOM at the beginning of the stream

    When the json file stream contains a BOM sequence at the begining, the parser throws an exception and cannot parse the file, even if the encoding is UTF-8.

    With this change, the parser ignore the BOM sequence if found.

    I included BOM sequences for UTF-16 (BE/LE) and UTF-32 (BE/LE) too.

    opened by formatz 8
  • Use a 'token' object-stream between the lexer and parser.

    Use a 'token' object-stream between the lexer and parser.

    I think this will add a lot of benefits, especially in future PRs/commits (I have a few other ideas). Also by adding a 'token' object it starts to reduce complexity in the Lexer/Parser classes, as seen by the commits (the code is easier to follow along with).

    The tokens produced by the lexer also now track the any linebreaks (you will see why in my next PR).

    :-)

    opened by nbish11 8
  • PHP Fatal error:  Allowed memory size exhausted

    PHP Fatal error: Allowed memory size exhausted

    PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/html/vendor/halaxa/json-machine/src/Parser.php on line 177

    Json-machine version is 0.3.2

    I am trying to read file having size of 27mb.

    opened by milinmestry 7
  • Option to decode JSON as object, instead of associative array

    Option to decode JSON as object, instead of associative array

    By default, json_decode will convert the string to an object, not to associative arrays. I wonder if it's possible to get the same behaviour in json-machine, or should I use json_decode(json_encode($field), false)?

    opened by rodamaral 7
  • Option or method for preserving the precision of numeric literals

    Option or method for preserving the precision of numeric literals

    Currently, the precision of JSON numbers is not, in general, preserved.

    Unfortunately, using JSON_BIGINT_AS_STRING, at least by itself, doesn't help, first because it converts all "big integers" to strings (see below), and because it does nothing for "big decimals" (meaning "big or little decimals").

    Perhaps asking for the preservation of numeric decimals is too much to ask for in this project; if so, please interpret this ER as a request for the preservation of integer precision.

    --

    print json_encode(json_decode("[\"123\", 123]", flags: JSON_BIGINT_AS_STRING))."\n";
    
    print json_encode(json_decode("[\"123000000000000000000000000123\", 123000000000000000000000000123]", flags: JSON_BIGINT_AS_STRING))."\n";
    

    produces:

    ["123",123]
    ["123000000000000000000000000123","123000000000000000000000000123"]
    

    whereas for the second array, we want:

    ["123000000000000000000000000123",123000000000000000000000000123]
    
    enhancement 
    opened by pkoppstein 6
  • Let JSON pointer iterate through values in nested arrays

    Let JSON pointer iterate through values in nested arrays

    Hi @halaxa and thanks for this brilliant package :)

    Based on RFC 6901, the character - can reference a JSON array and applications using a JSON pointer can specify how it should handle such character. In particular:

    If the currently referenced value is a JSON array, the reference token MUST contain either:

    • characters comprised of digits [...], or

    • exactly the single character "-", making the new referenced value the (nonexistent) member after the last array element.

    and

    Note that the use of the "-" character to index an array will always result in such an error condition because by definition it refers to a nonexistent array element. Thus, applications of JSON Pointer need to specify how that character is to be handled, if it is to be useful.

    Any error condition for which a specific action is not defined by the JSON Pointer application results in termination of evaluation.

    This PR aims to take advantage of this spec to let the JSON pointer iterate through values in nested arrays.

    For example, given the following JSON:

    {
        "data": [
            {
                "name": "Team 1",
                "users": [
                    {
                        "id": 1
                    },
                    {
                        "id": 2
                    }
                ]
            },
            {
                "name": "Team 2",
                "users": [
                    {
                        "id": 3
                    }
                ]
            }
        ]
    }
    

    the JSON pointer /data/-/users/-/id will iterate through all user IDs.

    This PR also tests the feature and updates the README.

    opened by cerbero90 6
  • UnexpectedEndSyntaxErrorException

    UnexpectedEndSyntaxErrorException

    I sometimes get this error reading valid json files. Any idea why this could be happening? If I load the file into any json validator, there is no error on ','. Sometimes the position is not ',', but another arbitrary part of the json file,

    PHP Fatal error: Uncaught JsonMachine\Exception\UnexpectedEndSyntaxErrorException: JSON string ended unexpectedly ',' At position 0. in /.../.../.../.../.../vendor/halaxa/json-machine/src/Parser.php:368 Stack trace: #0 /.../.../.../.../.../vendor/halaxa/json-machine/src/Parser.php(249): JsonMachine\Parser->error() #1 /.../.../.../.../.../.../load.php(92): JsonMachine\Parser->getIterator()

    opened by TechOverflow 2
  • CLI script for streaming

    CLI script for streaming

    @halaxa asked me to start a new thread stemming from the discussion at https://github.com/halaxa/json-machine/issues/73

    Hopefully the script described below, which I'll call jm, will provide a basis for discussion or perhaps even the foundation of a script worthy of inclusion in the JSON Machine repository.

    The --help option produces quite extensive documentation, so for now I'll just add two points:

    1. The script attempts to make installation as painless as possible for the uninitiated, and I hope that further enhancements in that regard will be added;
    2. Ideally, the script would preserve the precision of all JSON numbers (at least as the default) -- see https://github.com/halaxa/json-machine/issues/87

    [ EDIT: The jm script is now in the "jm" repository. ]

    enhancement 
    opened by pkoppstein 8
  • Wildcard pointer doesn't work properly

    Wildcard pointer doesn't work properly

    Hello! I have a problem to using wildcard pointer /results/-/color like in example from root documentation: as result I receive only 1st iteration and second is not available through the foreach or iterator

    $fruits = Items::fromFile('fruitsArray.json', ['pointer' => '/results/-/color']);

    • my code example below:
    <?php 
    
    $json = '{"results":[{"name":"apple","color":"red"},{"name":"pear","color":"yellow"},{"name":"some","color":"green"}]}';
    $fruits = Items::fromString($json, ['pointer' => "/results/-/color"]);
    
    var_dump(iterator_count($fruits->getIterator())); // result 1
    
    foreach ($fruits as $key => $value) {
    	echo "{$value}\n"; // result only red
    }
    
    • also trying to pass the test of package and it's good
    • package version is 1.1.1

    P.S: Your library is awesome)

    opened by antonMilukov 3
  • CLI support?

    CLI support?

    Please let me know by reactions/voting or comments if a CLI version of JSON Machine would be useful to have. Thanks.

    jm command would take a JSON stream from stdin, and send items one by one to stdout wrapped in a single-item JSON object encoded as {key: value}.

    Possible usage:

    $ wget <big list of users to stdout> | jm --pointer=/results
    {"0": {"name": "Frank Sinatra", ...}}
    {"1": {"name": "Ray Charles", ...}}
    ...
    

    Another idea might be to wrap the item in a JSON list instead of an object, like so:

    $ wget <big list of users to stdout> | jm --pointer=/results
    [0, {"name": "Frank Sinatra", ...}]
    [1, {"name": "Ray Charles", ...}]
    ...
    
    enhancement 
    opened by halaxa 18
  • Push parsing support

    Push parsing support

    Support to incrementally feed the parser via an explicit method call where the pull approach of foreach cannot be used. Useful for example for curl's CURLOPT_WRITEFUNCTION or when receiving json chunks in an event loop.

    Proposed usage (implicit):

    $items = new PushItems(['pointer' => '/results']);
    
    $callback = function ($jsonChunk) use ($items) {
        $items->push($jsonChunk);
        foreach($items as $item) {
            // process currently available items
        }
    }
    

    or more explicit (similar to current API):

    $queue = new QueueChunks();
    $items = Items::fromQueue($queue, ['pointer' => '/results']);
    
    $callback = function ($jsonChunk) use ($items, $queue) {
        $queue->push($jsonChunk);
        foreach($items as $item) {
            // process currently available items
        }
    }
    

    Any other proposal?

    enhancement 
    opened by halaxa 0
  • Performance improvements (lexer/parser)

    Performance improvements (lexer/parser)

    Hi guys,

    the memory usage is awesome but the cpu-time is ~100x compared to json_decode (100MB json with 10000 entries). Did you consider using a c-extension for the tokenizing/parsing? Never wrote a extension, but looks like we could extend ext-json or even just use ext-parle for the heavy lifting.

    Could try to implement a lexer with ext-parle and look how the performance changes and then implement a parser if you guys think this is a good idea.

    Greeting

    enhancement 
    opened by fcaps 5
Releases(1.1.3)
Owner
Filip Halaxa
Filip Halaxa
A super fast, highly extensible markdown parser for PHP

A super fast, highly extensible markdown parser for PHP What is this? A set of PHP classes, each representing a Markdown flavor, and a command line to

Carsten Brandt 989 Dec 16, 2022
This is a simple, streaming parser for processing large JSON documents

Streaming JSON parser for PHP This is a simple, streaming parser for processing large JSON documents. Use it for parsing very large JSON documents to

Salsify 687 Jan 4, 2023
Highly-extensible PHP Markdown parser which fully supports the CommonMark and GFM specs.

league/commonmark league/commonmark is a highly-extensible PHP Markdown parser created by Colin O'Dell which supports the full CommonMark spec and Git

The League of Extraordinary Packages 2.4k Jan 1, 2023
An HTML5 parser and serializer for PHP.

HTML5-PHP HTML5 is a standards-compliant HTML5 parser and writer written entirely in PHP. It is stable and used in many production websites, and has w

null 1.2k Dec 31, 2022
Advanced shortcode (BBCode) parser and engine for PHP

Shortcode Shortcode is a framework agnostic PHP library allowing to find, extract and process text fragments called "shortcodes" or "BBCodes". Example

Tomasz Kowalczyk 358 Nov 26, 2022
Parser for Markdown and Markdown Extra derived from the original Markdown.pl by John Gruber.

PHP Markdown PHP Markdown Lib 1.9.0 - 1 Dec 2019 by Michel Fortin https://michelf.ca/ based on Markdown by John Gruber https://daringfireball.net/ Int

Michel Fortin 3.3k Jan 1, 2023
Better Markdown Parser in PHP

Parsedown Better Markdown Parser in PHP - Demo. Features One File No Dependencies Super Fast Extensible GitHub flavored Tested in 5.3 to 7.3 Markdown

Emanuil Rusev 14.3k Jan 8, 2023
📜 Modern Simple HTML DOM Parser for PHP

?? Simple Html Dom Parser for PHP A HTML DOM parser written in PHP - let you manipulate HTML in a very easy way! This is a fork of PHP Simple HTML DOM

Lars Moelleken 665 Jan 4, 2023
Parsica - PHP Parser Combinators - The easiest way to build robust parsers.

Parsica The easiest way to build robust parsers in PHP.

null 0 Feb 22, 2022
This is a php parser for plantuml source file.

PlantUML parser for PHP Overview This package builds AST of class definitions from plantuml files. This package works only with php. Installation Via

Tasuku Yamashita 5 May 29, 2022
A PHP hold'em range parser

mattjmattj/holdem-range-parser A PHP hold'em range parser Installation No published package yet, so you'll have to clone the project manually, or add

Matthias Jouan 1 Feb 2, 2022
A New Markdown parser for PHP5.4

Ciconia - A New Markdown Parser for PHP The Markdown parser for PHP5.4, it is fully extensible. Ciconia is the collection of extension, so you can rep

Kazuyuki Hayashi 357 Jan 3, 2023
A lightweight lexical string parser for BBCode styled markup.

Decoda A lightweight lexical string parser for BBCode styled markup. Requirements PHP 5.6.0+ Multibyte Composer Contributors "Marten-Plain" emoticons

Miles Johnson 194 Dec 27, 2022
Simple URL parser

urlparser Simple URL parser This is a simple URL parser, which returns an array of results from url of kind /module/controller/param1:value/param2:val

null 1 Oct 29, 2021
UpToDocs scans a Markdown file for PHP code blocks, and executes each one in a separate process.

UpToDocs UpToDocs scans a Markdown file for PHP code blocks, and executes each one in a separate process. Include this in your CI workflows, to make s

Mathias Verraes 56 Nov 26, 2022
HTML sanitizer, written in PHP, aiming to provide XSS-safe markup based on explicitly allowed tags, attributes and values.

TYPO3 HTML Sanitizer ℹī¸ Common safe HTML tags & attributes as given in \TYPO3\HtmlSanitizer\Builder\CommonBuilder still might be adjusted, extended or

TYPO3 GitHub Department 22 Dec 14, 2022
A simple PHP scripting application which fetch emails from your Gmail account according to a filter and parses them for information.

A simple PHP scripting application which fetch emails from your Gmail account according to a filter and parses them for information.

Haitham Sweilem 1 Jan 18, 2022
Plug and play flat file markdown blog for your Laravel-projects

Ampersand Plug-and-play flat file markdown blog tool for your Laravel-project. Create an article or blog-section on your site without the hassle of se

Marcus Olsson 22 Dec 5, 2022
Convert HTML to Markdown with PHP

HTML To Markdown for PHP Library which converts HTML to Markdown for your sanity and convenience. Requires: PHP 7.2+ Lead Developer: @colinodell Origi

The League of Extraordinary Packages 1.5k Dec 28, 2022