blob: 88a12876e71cc7861ecbc80df75c530e1bb6b94e [file] [log] [blame] [raw]
<!DOCTYPE html><html><head><meta charset="utf-8" /><meta content="IE=edge" http-equiv="X-UA-Compatible" /><meta content="width=device-width, initial-scale=1, maximum-scale=2.0, user-scalable=yes, minimal-ui=yes" name="viewport" /><title>facil.io - JSON API</title><meta content="facil.io - JSON API" name="description" /><link href="https://fonts.googleapis.com/css?family=Montserrat|Quicksand|Karla" rel="stylesheet" type="text/css" /><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script><link href="/assets/styles/main.css" rel="stylesheet" type="text/css" /><script type="application/ld+json">{"@context":"http://schema.org","@type":"WebSite","url":"http://facil.io","name":"facil.io","description":"facil.io - a light web application framework in C, with support for HTTP, WebSockets and Pub/Sub out of the box.","keywords":"C, web, framework, websockets, websocket, realtime, real-time, easy","image":"http://facil.io/website/logo/facil-io.svg","author":[{"@type":"Person","name":"Bo (Myst)","url":"http://stackoverflow.com/users/4025095/myst","email":"bo(at)facil.io"}],"sourceOrganization":{"@context":"http://schema.org","@type":"Organization","name":"Plezi","url":"http://facil.io","description":"facil.io - a light web application framework in C, with support for HTTP, WebSockets and Pub/Sub out of the box.","logo":"http://facil.io/website/logo/facil-io.svg","image":"http://facil.io/website/logo/facil-io.svg","email":"bo(at)facil.io","member":[{"@type":"Person","name":"Bo (Myst)","url":"http://stackoverflow.com/users/4025095/myst","email":"bo(at)facil.io"}]}}</script><meta content="facil.io" name="apple-mobile-web-app-title" /><meta content="facil.io - the C Web Application Framework" name="application-name" /><meta content="#b91d47" name="msapplication-TileColor" /><meta content="/mstile-144x144.png" name="msapplication-TileImage" /><meta content="#ffffff" name="theme-color" /></head><body><a href="/" id="logo"></a><input id="show_nav" type="checkbox" /><nav id="top_nav"><ul><li><a href="/0.7.x/index">Latest Docs</a></li><li><a href="https://github.com/boazsegev/facil.io" target="_blank">Source Code</a></li><li><a href="javascript: change_themes();" id="theme">Night Theme</a></li></ul></nav><input id="show_sidebar" type="checkbox" /><nav id="side_bar"><h2 id="version-0-7-x"><a href="/0.7.x/index">Version 0.7.x</a></h2>
<h3 id="core-library"><a href="/0.7.x/fio">Core Library</a></h3>
<ul>
<li><a href="/0.7.x/fio#connection-protocol-management">Protocol Management</a></li>
<li><a href="/0.7.x/fio#running-facil-io">Running the IO reactor</a></li>
<li><a href="/0.7.x/fio#socket-connection-functions">Connection Functions</a></li>
<li><a href="/0.7.x/fio#event-task-scheduling">Event / Task Scheduling</a></li>
<li><a href="/0.7.x/fio#pub-sub-services">Pub/Sub Services</a></li>
<li><a href="/0.7.x/fio#the-custom-memory-allocator">Memory Allocation</a></li>
<li><a href="/0.7.x/fio#general-helpers">General Helpers</a></li>
<li><a href="/0.7.x/fio#linked-lists">Linked Lists</a></li>
<li><a href="/0.7.x/fio#string-helpers">String Helpers</a></li>
<li><a href="/0.7.x/fio#dynamic-arrays">Dynamic Arrays</a></li>
<li><a href="/0.7.x/fio#hash-maps-sets">Hash Maps / Sets</a></li>
<li><a href="/0.7.x/fio#version-and-compilation-related-macros">Compilation Macros</a></li>
<li><a href="/0.7.x/fio#weak-functions">Weak Functions</a></li>
</ul>
<h3 id="extensions"><a href="/0.7.x/extensions">Extensions</a></h3>
<!-- * [TLS (SSL)](/0.7.x/fio_tls) -->
<ul>
<li><a href="/0.7.x/http">HTTP / WebSockets</a></li>
<li><a href="/0.7.x/redis">Redis (client)</a></li>
<li><a href="/0.7.x/fio_cli">CLI (command line)</a></li>
</ul>
<h3 id="the-fiobj-types"><a href="/0.7.x/fiobj">The FIOBJ types</a></h3>
<ul>
<li><a href="/0.7.x/fiobj_core">Core Functions</a></li>
<li><a href="/0.7.x/fiobj_primitives">Primitives</a></li>
<li><a href="/0.7.x/fiobj_numbers">Numbers</a></li>
<li><a href="/0.7.x/fiobj_str">Strings</a></li>
<li><a href="/0.7.x/fiobj_ary">Array</a></li>
<li><a href="/0.7.x/fiobj_hash">HashMap</a></li>
<li><a href="/0.7.x/fiobj_data">Data Streams</a></li>
<li><a href="/0.7.x/fiobj_json">JSON</a></li>
<li><a href="/0.7.x/fiobj_mustache">Mustache</a></li>
</ul>
</nav><div id="md_container"><div class='toc'><ul>
<li>
<a href="#facil-io-json-api">facil.io - JSON API</a>
<ul>
<li>
<a href="#overview">Overview</a>
<ul>
<li>
<a href="#example">Example</a>
</li>
</ul>
</li>
<li>
<a href="#constants">Constants</a>
</li>
<li>
<a href="#types">Types</a>
<ul>
<li>
<a href="#parsing-result-types">Parsing result types</a>
</li>
<li>
<a href="#formating-result-type">Formating result type</a>
</li>
</ul>
</li>
<li>
<a href="#functions">Functions</a>
<ul>
<li>
<a href="#fiobj_json2obj"><code>fiobj_json2obj</code></a>
</li>
<li>
<a href="#fiobj_obj2json"><code>fiobj_obj2json</code></a>
</li>
<li>
<a href="#fiobj_obj2json2"><code>fiobj_obj2json2</code></a>
</li>
</ul>
</li>
<li>
<a href="#important-notes">Important Notes</a>
</li>
</ul>
</li>
</ul>
</div><h1 id="facil-io-json-api">facil.io - JSON API</h1>
<h2 id="overview">Overview</h2>
<p>Parsing, editing and outputting JSON in C can be easily accomplished using <a href="fiobj.md">facil.io&#39;s dynamic types</a> (<code>FIOBJ</code>).</p>
<p>There are <a href="json_performance.html">faster alternatives as well as slower alternatives out there</a> (i.e., the Qajson4c library is probably the most balanced alternative).</p>
<p>However, <code>facil.io</code> offers the added benefit of complete parsing from JSON to object. This is in contrast to some parsers that offer a mid-way structure (often a linked list of JSON nodes) or lazy (delayed) parsing for types such as <code>true</code>, <code>false</code> and Numbers.</p>
<p><code>facil.io</code> also offers the added benefit of complete formatting from a framework wide object type (<code>FIOBJ</code>) to JSON. This is in contrast to some solutions that require a linked list of node structures.</p>
<h3 id="example">Example</h3>
<p>The <code>facil.io</code> parser will parse any C string until it either consumes the whole string or completes parsing of a JSON object.</p>
<p>For example, the following program will minify (or prettify) JSON data:</p>
<pre><code class='highlight'><span class="c1">// include the `fiobj` module from `facil.io`</span>
<span class="cp">#include "fiobj.h"
#include &lt;string.h&gt;
</span><span class="c1">// this is passed as an argument to `fiobj_obj2json`</span>
<span class="c1">// change this to 1 to prettify.</span>
<span class="cp">#define PRETTY 1
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="k">const</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
<span class="c1">// a default string to demo</span>
<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">json</span> <span class="o">=</span> <span class="s">u8"{</span><span class="se">\n\t\"</span><span class="s">id</span><span class="se">\"</span><span class="s">:1,</span><span class="se">\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\t</span><span class="s">// comments are ignored.</span><span class="se">\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\t\"</span><span class="s">number</span><span class="se">\"</span><span class="s">:42,</span><span class="se">\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\t\"</span><span class="s">float</span><span class="se">\"</span><span class="s">:42.42,</span><span class="se">\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\t\"</span><span class="s">string</span><span class="se">\"</span><span class="s">:</span><span class="se">\"\\</span><span class="s">uD834</span><span class="se">\\</span><span class="s">uDD1E oh yeah...</span><span class="se">\"</span><span class="s">,</span><span class="se">\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\t\"</span><span class="s">hash</span><span class="se">\"</span><span class="s">:{</span><span class="se">\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\t\t\"</span><span class="s">nested</span><span class="se">\"</span><span class="s">:true</span><span class="se">\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\t</span><span class="s">},</span><span class="se">\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\t\"</span><span class="s">symbols</span><span class="se">\"</span><span class="s">:[</span><span class="se">\"</span><span class="s">id</span><span class="se">\"</span><span class="s">,"</span>
<span class="s">"</span><span class="se">\"</span><span class="s">number</span><span class="se">\"</span><span class="s">,</span><span class="se">\"</span><span class="s">float</span><span class="se">\"</span><span class="s">,</span><span class="se">\"</span><span class="s">string</span><span class="se">\"</span><span class="s">,</span><span class="se">\"</span><span class="s">hash</span><span class="se">\"</span><span class="s">,</span><span class="se">\"</span><span class="s">symbols</span><span class="se">\"</span><span class="s">]</span><span class="se">\n</span><span class="s">}"</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// accept command line JSON data</span>
<span class="n">json</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="p">}</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">attempting to parse:</span><span class="se">\n</span><span class="s">%s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">json</span><span class="p">);</span>
<span class="c1">// Parsing the JSON</span>
<span class="n">FIOBJ</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">FIOBJ_INVALID</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">consumed</span> <span class="o">=</span> <span class="n">fiobj_json2obj</span><span class="p">(</span><span class="o">&amp;</span><span class="n">obj</span><span class="p">,</span> <span class="n">json</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">json</span><span class="p">));</span>
<span class="c1">// test for errors</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">consumed</span> <span class="o">||</span> <span class="o">!</span><span class="n">obj</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">ERROR, couldn't parse data.</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Example use - printing some JSON data</span>
<span class="n">FIOBJ</span> <span class="n">key</span> <span class="o">=</span> <span class="n">fiobj_str_new</span><span class="p">(</span><span class="s">"number"</span><span class="p">,</span> <span class="mi">6</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">FIOBJ_TYPE_IS</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">FIOBJ_T_HASH</span><span class="p">)</span> <span class="c1">// make sure the JSON object is a Hash</span>
<span class="o">&amp;&amp;</span> <span class="n">fiobj_hash_get</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">key</span><span class="p">))</span> <span class="p">{</span> <span class="c1">// test for the existence of "number"</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"JSON print example - the meaning of life is %zu"</span><span class="p">,</span>
<span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">fiobj_obj2num</span><span class="p">(</span><span class="n">fiobj_hash_get</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">key</span><span class="p">)));</span>
<span class="p">}</span>
<span class="n">fiobj_free</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>
<span class="c1">// Formatting the JSON back to a String object and printing it up</span>
<span class="n">FIOBJ</span> <span class="n">str</span> <span class="o">=</span> <span class="n">fiobj_obj2json</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">PRETTY</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">Parsed JSON input was: %zu bytes"</span>
<span class="s">"</span><span class="se">\n</span><span class="s">JSON output is %zu bytes:</span><span class="se">\n\n</span><span class="s">%s</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span>
<span class="n">consumed</span><span class="p">,</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">fiobj_obj2cstr</span><span class="p">(</span><span class="n">str</span><span class="p">).</span><span class="n">len</span><span class="p">,</span> <span class="n">fiobj_obj2cstr</span><span class="p">(</span><span class="n">str</span><span class="p">).</span><span class="n">data</span><span class="p">);</span>
<span class="c1">// cleanup</span>
<span class="n">fiobj_free</span><span class="p">(</span><span class="n">str</span><span class="p">);</span>
<span class="n">fiobj_free</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
<h2 id="constants">Constants</h2>
<p><code>JSON_MAX_DEPTH</code> is the maximum depth for nesting. The default value is 32 (should be set during compile time).</p>
<p>Since bit mapping is used, the maximum available nesting value is 32 (32 nested levels use 32 bits in a <code>uint32_t</code> type).</p>
<p>Note that facil.io avoids recursion to protect against DoS attacks that attempt stack exploding techniques. </p>
<h2 id="types">Types</h2>
<h3 id="parsing-result-types">Parsing result types</h3>
<p>The JSON parser returns a <code>FIOBJ</code> dynamic object of any type (depending on the JSON data).</p>
<p>No assumptions should be made </p>
<h3 id="formating-result-type">Formating result type</h3>
<p>The JSON formatter returns a <code>FIOBJ</code> dynamic String, always.</p>
<h2 id="functions">Functions</h2>
<h3 id="fiobj_json2obj"><code>fiobj_json2obj</code></h3>
<pre><code class='highlight'><span class="kt">size_t</span> <span class="n">fiobj_json2obj</span><span class="p">(</span><span class="n">FIOBJ</span> <span class="o">*</span><span class="n">pobj</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
</code></pre>
<p>Parses JSON, setting <code>pobj</code> to point to the new Object.</p>
<p>Returns the number of bytes consumed. On Error, 0 is returned and no data is consumed.</p>
<h3 id="fiobj_obj2json"><code>fiobj_obj2json</code></h3>
<pre><code class='highlight'><span class="n">FIOBJ</span> <span class="n">fiobj_obj2json</span><span class="p">(</span><span class="n">FIOBJ</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">pretty</span><span class="p">);</span>
</code></pre>
<p>Stringify an object into a JSON string. Remember to <code>fiobj_free</code>.</p>
<p>Note that only the following basic fiobj types are supported: Primitives (True / False / NULL), Numbers (Number / Float), Strings, Hashes and Arrays.</p>
<p>Some objects (such as the POSIX specific IO type) are unsupported and may be formatted incorrectly.</p>
<h3 id="fiobj_obj2json2"><code>fiobj_obj2json2</code></h3>
<pre><code class='highlight'><span class="n">FIOBJ</span> <span class="n">fiobj_obj2json2</span><span class="p">(</span><span class="n">FIOBJ</span> <span class="n">dest</span><span class="p">,</span> <span class="n">FIOBJ</span> <span class="n">object</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">pretty</span><span class="p">);</span>
</code></pre>
<p>Formats an object into a JSON string, appending the JSON string to an existing String. Remember to <code>fiobj_free</code> as usual.</p>
<p>Note that only the foloowing basic fiobj types are supported: Primitives (True / False / NULL), Numbers (Number / Float), Strings, Hashes and Arrays.</p>
<p>Some objects (such as the POSIX specific IO type) are unsupported and may be formatted incorrectly.</p>
<h2 id="important-notes">Important Notes</h2>
<p>The parser assumes the whole JSON data is present in the data&#39;s buffer. A streaming parser is coded into the <a href="https://github.com/boazsegev/facil.io/blob/master/lib/facil/core/types/fiobj/fiobj_json.c"><code>fiobj_json.c</code> source file</a> but no external API is exposed.</p>
<p>The <a href="https://github.com/boazsegev/facil.io/blob/master/lib/facil/core/types/fiobj/fiobj_json.h"><code>fiobj_json.h</code> header file</a> might include more data.</p>
</div><a href="/" id="sign"></a><div class="hidden" id="notice"><a class="notice_close" onclick="hide_notice()">X</a><div id="notice_text"></div></div><script>function change_themes() {
if(localStorage.getItem("theme") == 'dark') {
localStorage.setItem("theme", "light");
} else {
localStorage.setItem("theme", "dark");
}
$('body')[0].className = localStorage.getItem("theme");
set_theme_link();
$('#show_nav').attr('checked', false);
return false;
};
function sidebar_name() { return window.location.pathname.slice(0, window.location.pathname.lastIndexOf("/")); }
function on_sidebar_link(e) {
sessionStorage.setItem("sidebar.expect", sidebar_name());
sessionStorage.setItem("sidebar.pos", document.getElementById("side_bar").scrollTop);
}
function load_sidebar_pos() {
var e = document.getElementById("side_bar");
if(!e) {
console.warn("No sidebar detected");
return;
}
var expect = sidebar_name();
if(sessionStorage.getItem("sidebar.expect") == expect) {
e.scrollTo(0, parseInt(sessionStorage.getItem("sidebar.pos")));
} else {
sessionStorage.setItem("sidebar.expect", false);
sessionStorage.setItem("sidebar.pos", 0);
}
if(e) {
// add link callbacks
var links = document.links;
var count = links.length;
for (var i = 0; i < count; i++) {
var href = links[i].href;
if(href.startsWith(document.location.origin)) {
href = href.slice(document.location.origin.length);
}
if(href.startsWith(expect)) {
/* add link event */
links[i].addEventListener("click", on_sidebar_link);
}
}
}
};
load_sidebar_pos();
function set_theme_link() {
$("#theme").html( ( (localStorage.getItem("theme") == 'dark') ? "Day" : "Night") + " Theme" );
}
$('body')[0].className = (localStorage.getItem("theme") == 'dark') ? "dark" : "light";
set_theme_link();
function show_notice() { document.getElementById("notice").classList.remove('hidden'); };
function hide_notice() { document.getElementById("notice").classList.add('hidden'); };
$('#toc').on("touchstart", function (e) { return true; } );
$('#toc').on("hover", function (e) { return true; } );
// hljs.initHighlighting();
// Google Analytics
// if(location.hostname != "localhost") {
// (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
// (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
// m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
// })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
// ga('create', 'UA-69931401-1', 'auto');
// ga('send', 'pageview');
// }</script></body></html>