<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title> [json decode] And [json encode]: JSON Data in Pd </title> <style> /* Page tweaks */ .preview-page { margin-top: 64px; margin-bottom: 21px; } /* User-content tweaks */ .timeline-comment-wrapper > .timeline-comment:after, .timeline-comment-wrapper > .timeline-comment:before { content: none; } /* User-content overrides */ .discussion-timeline.wide { width: 920px; } </style> <link href="style.css" rel="stylesheet"/> </head> <body> <div class="page"> <div class="preview-page" data-autorefresh-url="" id="preview-page"> <main id="js-repo-pjax-container"> <div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5"> <div class="repository-content"> <div class="clearfix"> <div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end"> <div class="Layout-main"> <div class="Box md Box--responsive" id="readme"> <div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2"> <div class="d-flex flex-items-center"> <h2 class="Box-title"> [json decode] And [json encode]: JSON Data in Pd </h2> </div> </div> <div class="Box-body px-5 pb-5"> <article class="markdown-body entry-content container-lg" id="grip-content"> <p> Pd does not have boolean values, and no notion of a NULL object, only lists, symbols (=strings) and floats (=numbers). </p> <p> To use the definitions from <a href="http://json.org/" rel="nofollow"> json.org </a> this leads to the following mapping of JSON data to Pd: </p> <table> <thead> <tr> <th> JSON type </th> <th> Pd type </th> <th> JSON example </th> <th> Pd example </th> </tr> <tr> </tr> </thead> <tbody> <tr> <td> string </td> <td> symbol </td> <td> "my string, containing a comma" </td> <td> symbol my string\, containing a comma </td> </tr> <tr> </tr> <tr> <td> number </td> <td> float </td> <td> 1.01 </td> <td> 1.01 </td> </tr> <tr> </tr> <tr> <td> object </td> <td> see below </td> <td> {"key": "value"} </td> <td> </td> </tr> <tr> </tr> <tr> <td> array </td> <td> see below </td> <td> [{"key": "value"}, {"other key": "other value"}] </td> <td> </td> </tr> <tr> </tr> <tr> <td> boolean </td> <td> float </td> <td> true </td> <td> 1 </td> </tr> <tr> </tr> <tr> <td> boolean </td> <td> float </td> <td> false </td> <td> 0 </td> </tr> <tr> </tr> <tr> <td> null </td> <td> symbol </td> <td> null </td> <td> symbol </td> </tr> <tr> </tr> </tbody> </table> <p> As you can infer from the table, values of <code> true </code> , <code> false </code> , or <code> null </code> cannot be constructed by <code> [json-encode] </code> , but can be read by the objects. A value of null yields a Pd value of an empty symbol. </p> <h2> <a aria-hidden="true" class="anchor" href="#json-decode" id="user-content-json-decode"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> <code> [json-decode] </code> </h2> <p> Feeding a symbol or list to <code> [json-decode] </code> will parse the values and generate an output. If you use a list, then all elements of the list will be converted to symbols and concatenated using a space as separator, so <code> symbol my value </code> will generate the same output as <code> list my value </code> . </p> <p> You must feed exactly one valid JSON object or array of objects as a symbol or list message to <code> [json-decode] </code> . Any other correct JSON data cannot be interpreted by the <code> [json-decode] </code> . </p> <h3> <a aria-hidden="true" class="anchor" href="#output-of-a-json-object" id="user-content-output-of-a-json-object"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> Output of a JSON object </h3> <p> JSON objects are interpreted by <code> [json-decode] </code> as key value stores. Each key/value pair outputs a list on the middle outlet, where the key is always converted to a symbol, while the value is converted according to the table above. Arrays and objects are converted to their string representation again and then output as a symbol. </p> <p> After all key/value are sent to the middle outlet, a <code> bang </code> is emitted from the left outlet. </p> <p> <strong> Example: </strong> </p> <p> JSON string: </p> <pre><code>{ "id": 1, "active": true, "obsolete": false, "name": "PuREST JSON", "objects": ["json-decode", "json-encode", "urlparams", "rest", "oauth"], "author": {"name": "me", "age": "none of your business"} } </code></pre> <p> Output: </p> <ol> <li> middle: <code> list id 1 </code> </li> <li> middle: <code> list active 1 </code> </li> <li> middle: <code> list obsolete 0 </code> </li> <li> middle: <code> list name PuREST JSON </code> </li> <li> middle: <code> list objects ["json-decode"\, "json-encode"\, "urlparams"\, "rest"\, "oauth"] </code> </li> <li> middle: <code> list author {"name": "me"\, "age": "none of your business"} </code> </li> <li> left: <code> bang </code> </li> </ol> <h3> <a aria-hidden="true" class="anchor" href="#output-of-an-array-of-json-objects" id="user-content-output-of-an-array-of-json-objects"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> Output of an Array of JSON objects </h3> <p> An array generates the same output as a series of JSON objects, including <code> bang </code> messages on the left outlet. </p> <p> <strong> Example: </strong> </p> <p> JSON string: </p> <pre><code>[ {"key": "value", "id": 1}, {"id": 2}, {"id": 3} ] </code></pre> <p> Output: </p> <ol> <li> middle: <code> list key value </code> </li> <li> middle: <code> list id 1 </code> </li> <li> left: <code> bang </code> </li> <li> middle: <code> list id 2 </code> </li> <li> left: <code> bang </code> </li> <li> middle: <code> list id 3 </code> </li> <li> left: <code> bang </code> </li> </ol> <h3> <a aria-hidden="true" class="anchor" href="#error-handling" id="user-content-error-handling"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> Error handling </h3> <p> If the string fed into <code> [json-decode] </code> cannot be converted into a valid JSON object, then Pd will write an error to the console, and the right outlet will output a bang. Use that for error handling. </p> <h3> <a aria-hidden="true" class="anchor" href="#some-hints-for-data-processing" id="user-content-some-hints-for-data-processing"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> Some hints for data processing </h3> <ul> <li> Use <code> list trim </code> from list-abs for trimming the list selector off the output and then use <code> [route] </code> for the data. If you want to create new lists, feed them into <code> [pack] </code> . </li> <li> If you process an array of same object types, use the approach above and store the values in a FIFO buffer, e. g. <code> [fifop] </code> from zexy or <code> [list-fifo] </code> from list-abs. </li> <li> Do not expect JSON data to be ordered: <code> {"id": 1, "name: "my name"} </code> and <code> {"name": "my name", "id": 1} </code> are in fact the same object. Use an empty first inlet of <code> [pack] </code> and the <code> bang </code> from the left outlet to create your own lists. </li> </ul> <h2> <a aria-hidden="true" class="anchor" href="#json-encode" id="user-content-json-encode"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> <code> [json-encode] </code> </h2> <h3> <a aria-hidden="true" class="anchor" href="#reading-and-writing-json-files" id="user-content-reading-and-writing-json-files"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> Reading and Writing JSON files </h3> <p> <code> [json-encode] </code> can hold one JSON object at a time in its memory. Therefore, if you read JSON data from a file using the <code> [read( </code> message, the message needs exactly one additional parameter, the path to the file to read. </p> <p> The file must contain exactly one JSON object. If you want to read an array, you must wrap the array in an object. </p> <p> <strong> Example: </strong> </p> <p> <code> [{"key": "value"}, {"another key": "another value"}] </code> cannot be read, but <code> {"wrapping": [{"key": "value"}, {"another key": "another value"}]} </code> can. </p> <p> To write data to a file, use the <code> [write( </code> message. This message needs exactly one additional parameter, the path to the file to write the JSON object as string. It will overwrite existing content without asking for confirmation. </p> <h3> <a aria-hidden="true" class="anchor" href="#storing-data-with-add-and-array" id="user-content-storing-data-with-add-and-array"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> Storing Data with <code> [add( </code> And <code> [array( </code> </h3> <p> There are two messages for adding values to the JSON object stored in <code> [json-encode] </code> , <code> [add( </code> and <code> [array( </code> . Both need at least two additional values. The first parameter must be a symbol and represents the key. As Pd currently has no way to escape whitespace, there is no simple way to generate keys with space in it, a workaround is possible using <code> [makefilename] </code> from <a href="http://puredata.info/downloads/zexy" rel="nofollow"> zexy </a> . </p> <p> If the message has exactly two additional parameters, and the second parameter is a float, then the value will be stored as a number. Otherwise all additional parameters will be concatenated with a space. </p> <p> If the additional parameters can be converted to a JSON object, then the resulting string will be converted thusly, otherwise, a string is stored. </p> <p> Adding a value with an already stored key will result in overwriting the existing value. </p> <p> <strong> Example: </strong> </p> <ul> <li> <code> [add key 1( </code> will store <code> {"key":1} </code> . </li> <li> <code> [add key first second third( </code> will store <code> {"key":"first second third"} </code> . </li> <li> <code> [add key {"first":"second third"}( </code> will store <code> {"key":{first: "second third"}} </code> . </li> </ul> <p> <code> [array( </code> will add data to an array with the name of the key. The members of the array will be sorted in the specified order. If a value with the same key exists, but was stored with <code> [add( </code> , the value will be discarded. A new <code> [add( </code> message with the same key will discard the stored array. </p> <p> <strong> Example: </strong> </p> <ol> <li> <code> [add id 1( </code> => <code> {"id": 1} </code> . </li> <li> <code> [array id 2( </code> => <code> {"id": [2]} </code> . </li> <li> <code> [array id 3( </code> => <code> {"id": [2, 3]} </code> . </li> <li> <code> [add id 4( </code> => <code> {"id": 4} </code> . </li> </ol> <h3> <a aria-hidden="true" class="anchor" href="#outputting-and-clearing-data" id="user-content-outputting-and-clearing-data"> <span aria-hidden="true" class="octicon octicon-link"> </span> </a> Outputting And Clearing Data </h3> <p> Issuing a <code> [bang( </code> message to <code> [json-encode] </code> will output the JSON object as a string on its only outlet. If no data is stored, an empty symbol is sent. </p> <p> You can clear the stored object with the <code> [clear( </code> method. </p> </article> </div> </div> </div> </div> </div> </div> </div> </main> </div> </div> <script> function showCanonicalImages() { var images = document.getElementsByTagName('img'); if (!images) { return; } for (var index = 0; index < images.length; index++) { var image = images[index]; if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) { image.src = image.getAttribute('data-canonical-src'); } } } function scrollToHash() { if (location.hash && !document.querySelector(':target')) { var element = document.getElementById('user-content-' + location.hash.slice(1)); if (element) { element.scrollIntoView(); } } } function autorefreshContent(eventSourceUrl) { var initialTitle = document.title; var contentElement = document.getElementById('grip-content'); var source = new EventSource(eventSourceUrl); var isRendering = false; source.onmessage = function(ev) { var msg = JSON.parse(ev.data); if (msg.updating) { isRendering = true; document.title = '(Rendering) ' + document.title; } else { isRendering = false; document.title = initialTitle; contentElement.innerHTML = msg.content; showCanonicalImages(); } } source.onerror = function(e) { if (e.readyState === EventSource.CLOSED && isRendering) { isRendering = false; document.title = initialTitle; } } } window.onhashchange = function() { scrollToHash(); } window.onload = function() { scrollToHash(); } showCanonicalImages(); var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url'); if (autorefreshUrl) { autorefreshContent(autorefreshUrl); } </script> </body> </html>