7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <title>Tutorial — Jansson 2.7 documentation</title>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <link rel="stylesheet" href="_static/default.css" type="text/css" />
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest var DOCUMENTATION_OPTIONS = {
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest URL_ROOT: './',
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest VERSION: '2.7',
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest COLLAPSE_INDEX: false,
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest FILE_SUFFIX: '.html',
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste HAS_SOURCE: true
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <script type="text/javascript" src="_static/jquery.js"></script>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <script type="text/javascript" src="_static/underscore.js"></script>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <script type="text/javascript" src="_static/doctools.js"></script>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <link rel="top" title="Jansson 2.7 documentation" href="index.html" />
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <link rel="next" title="RFC Conformance" href="conformance.html" />
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <link rel="prev" title="Upgrading from 1.x" href="upgrading.html" />
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <li class="right" style="margin-right: 10px">
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <a href="genindex.html" title="General Index"
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <a href="conformance.html" title="RFC Conformance"
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara <a href="upgrading.html" title="Upgrading from 1.x"
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara <li><a href="index.html">Jansson 2.7 documentation</a> »</li>
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara<span id="id1"></span><h1>Tutorial<a class="headerlink" href="#tutorial" title="Permalink to this headline">¶</a></h1>
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara<p>In this tutorial, we create a program that fetches the latest commits
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswaraof a repository in <a class="reference external" href="https://github.com/">GitHub</a> over the web. <a class="reference external" href="http://developer.github.com/">GitHub API</a> uses JSON, so
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswarathe result can be parsed using Jansson.</p>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<p>To stick to the the scope of this tutorial, we will only cover the the
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Joosteparts of the program related to handling JSON data. For the best user
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrestexperience, the full source code is available:
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste<a class="reference download internal" href="_downloads/github_commits.c"><tt class="xref download docutils literal"><span class="pre">github_commits.c</span></tt></a>. To compile it (on Unix-like systems with
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Joostegcc), use the following command:</p>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<div class="highlight-c"><div class="highlight"><pre><span class="n">gcc</span> <span class="o">-</span><span class="n">o</span> <span class="n">github_commits</span> <span class="n">github_commits</span><span class="p">.</span><span class="n">c</span> <span class="o">-</span><span class="n">ljansson</span> <span class="o">-</span><span class="n">lcurl</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<p><a class="reference external" href="http://curl.haxx.se/">libcurl</a> is used to communicate over the web, so it is required to
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrestcompile the program.</p>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<div class="highlight-c"><div class="highlight"><pre><span class="n">github_commits</span> <span class="n">USER</span> <span class="n">REPOSITORY</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<p><tt class="docutils literal"><span class="pre">USER</span></tt> is a GitHub user ID and <tt class="docutils literal"><span class="pre">REPOSITORY</span></tt> is the repository
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrestname. Please note that the GitHub API is rate limited, so if you run
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswarathe program too many times within a short period of time, the sever
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswarastarts to respond with an error.</p>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<div class="section" id="the-github-repo-commits-api">
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<span id="tutorial-github-commits-api"></span><h2>The GitHub Repo Commits API<a class="headerlink" href="#the-github-repo-commits-api" title="Permalink to this headline">¶</a></h2>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<p>The <a class="reference external" href="http://developer.github.com/v3/repos/commits/">GitHub Repo Commits API</a> is used by sending HTTP requests to
7ad2fbd2d39159e30fdde02d014626b643758033Andrew ForrestURLs like <tt class="docutils literal"><span class="pre">https://api.github.com/repos/USER/REPOSITORY/commits</span></tt>,
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrestwhere <tt class="docutils literal"><span class="pre">USER</span></tt> and <tt class="docutils literal"><span class="pre">REPOSITORY</span></tt> are the GitHub user ID and the name
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrestof the repository whose commits are to be listed, respectively.</p>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste<p>GitHub responds with a JSON array of the following form:</p>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste<div class="highlight-none"><div class="highlight"><pre>[
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste "sha": "<the commit ID>",
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste "commit": {
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste "message": "<the commit message>",
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste <more fields, not important to this tutorial...>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste <more fields...>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste "sha": "<the commit ID>",
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste "commit": {
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste "message": "<the commit message>",
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste <more fields...>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste <more fields...>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste <more commits...>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste<p>In our program, the HTTP request is sent using the following
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Joostefunction:</p>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">request</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">url</span><span class="p">);</span>
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Jooste<p>It takes the URL as a parameter, preforms a HTTP GET request, and
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Joostereturns a newly allocated string that contains the response body. If
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Joostethe request fails, an error message is printed to stderr and the
8acf5a373074b7db10b49aa33b35f8a541cabfd1Jaco Joostereturn value is <em>NULL</em>. For full details, refer to <a class="reference download internal" href="_downloads/github_commits.c"><tt class="xref download docutils literal"><span class="pre">the</span> <span class="pre">code</span></tt></a>, as the actual implementation is not important
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<span id="tutorial-the-program"></span><h2>The Program<a class="headerlink" href="#the-program" title="Permalink to this headline">¶</a></h2>
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara<div class="highlight-c"><div class="highlight"><pre><span class="cp">#include <string.h></span>
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara<span class="cp">#include <jansson.h></span>
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara<p>Like all the programs using Jansson, we need to include
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara<tt class="file docutils literal"><span class="pre">jansson.h</span></tt>.</p>
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara<p>The following definitions are used to build the GitHub API request
d9156ce7de2695a23e4b5b04916c38ead2d5df40Ram Anaswara<div class="highlight-c"><div class="highlight"><pre><span class="cp">#define URL_FORMAT "https:</span><span class="c1">//api.github.com/repos/%s/%s/commits"</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<p>The following function is used when formatting the result to find the
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrestfirst newline in the commit message:</p>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<div class="highlight-c"><div class="highlight"><pre><span class="cm">/* Return the offset of the first newline in text or the length of</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<span class="cm"> text if there's no newline */</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest<span class="k">static</span> <span class="kt">int</span> <span class="nf">newline_offset</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">text</span><span class="p">)</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">newline</span> <span class="o">=</span> <span class="n">strchr</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="sc">'\n'</span><span class="p">);</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">newline</span><span class="p">)</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <span class="k">return</span> <span class="n">strlen</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
7ad2fbd2d39159e30fdde02d014626b643758033Andrew Forrest <span class="k">return</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">newline</span> <span class="o">-</span> <span class="n">text</span><span class="p">);</span>
<div class="highlight-c"><div class="highlight"><pre><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="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">text</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">url</span><span class="p">[</span><span class="n">URL_SIZE</span><span class="p">];</span>
<span class="kt">json_t</span> <span class="o">*</span><span class="n">root</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">3</span><span class="p">)</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"usage: %s USER REPOSITORY</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"List commits at USER's REPOSITORY.</span><span class="se">\n\n</span><span class="s">"</span><span class="p">);</span>
<div class="highlight-c"><div class="highlight"><pre><span class="n">snprintf</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">URL_SIZE</span><span class="p">,</span> <span class="n">URL_FORMAT</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
<p>This uses the <tt class="docutils literal"><span class="pre">URL_SIZE</span></tt> and <tt class="docutils literal"><span class="pre">URL_FORMAT</span></tt> constants defined above.
<div class="highlight-c"><div class="highlight"><pre><span class="n">text</span> <span class="o">=</span> <span class="n">request</span><span class="p">(</span><span class="n">url</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">text</span><span class="p">)</span>
<p>If an error occurs, our function <tt class="docutils literal"><span class="pre">request</span></tt> prints the error and
<p>Next we’ll call <a class="reference internal" href="apiref.html#c.json_loads" title="json_loads"><tt class="xref c c-func docutils literal"><span class="pre">json_loads()</span></tt></a> to decode the JSON text we got
<div class="highlight-c"><div class="highlight"><pre><span class="n">root</span> <span class="o">=</span> <span class="n">json_loads</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&</span><span class="n">error</span><span class="p">);</span>
<span class="n">free</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">root</span><span class="p">)</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"error: on line %d: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">error</span><span class="p">.</span><span class="n">line</span><span class="p">,</span> <span class="n">error</span><span class="p">.</span><span class="n">text</span><span class="p">);</span>
<p>We don’t need the JSON text anymore, so we can free the <tt class="docutils literal"><span class="pre">text</span></tt>
variable right after decoding it. If <a class="reference internal" href="apiref.html#c.json_loads" title="json_loads"><tt class="xref c c-func docutils literal"><span class="pre">json_loads()</span></tt></a> fails, it
returns <em>NULL</em> and sets error information to the <a class="reference internal" href="apiref.html#c.json_error_t" title="json_error_t"><tt class="xref c c-type docutils literal"><span class="pre">json_error_t</span></tt></a>
<a class="reference internal" href="#tutorial-github-commits-api"><em>The GitHub Repo Commits API</em></a>.</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">json_is_array</span><span class="p">(</span><span class="n">root</span><span class="p">))</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"error: root is not an array</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">json_decref</span><span class="p">(</span><span class="n">root</span><span class="p">);</span>
<div class="highlight-c"><div class="highlight"><pre><span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">json_array_size</span><span class="p">(</span><span class="n">root</span><span class="p">);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="kt">json_t</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="o">*</span><span class="n">sha</span><span class="p">,</span> <span class="o">*</span><span class="n">commit</span><span class="p">,</span> <span class="o">*</span><span class="n">message</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">message_text</span><span class="p">;</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">json_array_get</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">json_is_object</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"error: commit data %d is not an object</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">json_decref</span><span class="p">(</span><span class="n">root</span><span class="p">);</span>
<p>The function <a class="reference internal" href="apiref.html#c.json_array_size" title="json_array_size"><tt class="xref c c-func docutils literal"><span class="pre">json_array_size()</span></tt></a> returns the size of a JSON
i’th element of the <tt class="docutils literal"><span class="pre">root</span></tt> array using <a class="reference internal" href="apiref.html#c.json_array_get" title="json_array_get"><tt class="xref c c-func docutils literal"><span class="pre">json_array_get()</span></tt></a>.
<div class="highlight-c"><div class="highlight"><pre> <span class="n">sha</span> <span class="o">=</span> <span class="n">json_object_get</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="s">"sha"</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">json_is_string</span><span class="p">(</span><span class="n">sha</span><span class="p">))</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"error: commit %d: sha is not a string</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">json_decref</span><span class="p">(</span><span class="n">root</span><span class="p">);</span>
<span class="n">commit</span> <span class="o">=</span> <span class="n">json_object_get</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="s">"commit"</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">json_is_object</span><span class="p">(</span><span class="n">commit</span><span class="p">))</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"error: commit %d: commit is not an object</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">json_decref</span><span class="p">(</span><span class="n">root</span><span class="p">);</span>
<span class="n">message</span> <span class="o">=</span> <span class="n">json_object_get</span><span class="p">(</span><span class="n">commit</span><span class="p">,</span> <span class="s">"message"</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">json_is_string</span><span class="p">(</span><span class="n">message</span><span class="p">))</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"error: commit %d: message is not a string</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">json_decref</span><span class="p">(</span><span class="n">root</span><span class="p">);</span>
from a JSON string using <a class="reference internal" href="apiref.html#c.json_string_value" title="json_string_value"><tt class="xref c c-func docutils literal"><span class="pre">json_string_value()</span></tt></a>:</p>
<div class="highlight-c"><div class="highlight"><pre> <span class="n">message_text</span> <span class="o">=</span> <span class="n">json_string_value</span><span class="p">(</span><span class="n">message</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%.8s %.*s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="n">json_string_value</span><span class="p">(</span><span class="n">id</span><span class="p">),</span>
<span class="n">newline_offset</span><span class="p">(</span><span class="n">message_text</span><span class="p">),</span>
<a class="reference internal" href="apiref.html#c.json_loads" title="json_loads"><tt class="xref c c-func docutils literal"><span class="pre">json_loads()</span></tt></a>, remember? It returns a <em>new reference</em> to the
to decrease the reference count using <a class="reference internal" href="apiref.html#c.json_decref" title="json_decref"><tt class="xref c c-func docutils literal"><span class="pre">json_decref()</span></tt></a>. This way
<div class="highlight-c"><div class="highlight"><pre><span class="n">json_decref</span><span class="p">(</span><span class="n">root</span><span class="p">);</span>
<a class="reference internal" href="apiref.html#apiref-reference-count"><em>Reference Count</em></a> in <a class="reference internal" href="apiref.html#apiref"><em>API Reference</em></a>.</p>
<h2>Conclusion<a class="headerlink" href="#conclusion" title="Permalink to this headline">¶</a></h2>
<a class="reference internal" href="apiref.html#apiref"><em>API Reference</em></a> to explore all features of Jansson.</p>