A JSON de- and encoder for SuperCollider
The JSON implementation of the SuperCollider standard library lacks certain features such as
- a JSON encoder (the conversion of an dictionary to a JSON string)
- parsing JSON values into their respective type (
.parseJSON
converts everything to a string)
which this Quark implements, building on top of the existing implementation.
There also exists a json Quark which also adds a wrapper for sccode.org but lacks a recursive encoding of objects.
The goal of JSONlib
is to simply provide a full implementation of the JSON standard in sclang and nothing beyond it.
Quickstart
Installation
// install the quark
Quarks.install("https://github.com/musikinformatik/JSONlib.git");
// restart the interpreter so the new classes are available
thisProcess.recompile;
// open documention
HelpBrowser.openHelpFor("Classes/JSONlib");
Basic usage
Parse a JSON
Let’s say we have a JSON with an integer as a value
{
"hello": 42
}
which we want to parse in sclang.
// use Symbol instead of String to get rid of escaping quotation marks
j = '{"hello": 42}';
// turn this into an Event
d = JSONlib.convertToSC(j);
// -> ( 'hello': 42 )
// an integer gets parsed as an actual integer
d[\hello].class
// -> Integer
// compare to the built-in method of sclang
// it uses a Dictionary instead of an Event
d = j.parseJSON()
// -> Dictionary[ (hello -> 42) ]
// but the Integer 42 is a String here
d["hello"].class
// -> String
Encode an Event as JSON
// create an event
e = (\foo: "bar", \baz: (\nested: true));
e.asJSON
// -> { "baz": { "nested": true }, "foo": "bar" }
// or use the class JSONlib
JSONlib.convertToJSON(e);
// -> { "baz": { "nested": true }, "foo": "bar" }
Use custom en/decoders to store functions
// create event with function
x = (\myFunc: {|x| x**2}, \data: 42);
// encode it to JSON
(
a = JSONlib.convertToJSON(x, customEncoder: {|x|
if(x.class==Function, {
"--func%".format(x.asCompileString).quote;
});
});
)
// -> { "data": 42, "myFunc": --func{|x| x**2} }
// decode JSON to SC with our custom decoder
// which re-constructs the function
(
b = JSONlib.convertToSC(a, customDecoder: {|x|
if(x.class==String) {
if(x.beginsWith("--func")) {
x["--func".size()..].compile().();
}
}
});
)
// -> ( 'myFunc': a Function, 'data': 42 )
b[\myFunc].(4)
// -> 16.0
Transfer nested objects via OSC
JSON allows to distribute and receive nested objects via OSC by distributing it as a String in an OSC message.
// create event
e = (\hello: (\foo: 42));
// create local listener which converts a JSON string to an SC object
(
OSCdef(\myJSONparser, func: {|m|
// received strings are symbols, so we need to cast them to strings
"Received %".format(JSONlib.convertToSC(m[1].asString)).postln;
}, path: "/myAddress", recvPort: 57120);
)
// send nested event as JSON
(
NetAddr(hostname: "127.0.0.1", port: 57120).sendMsg(
"/myAddress",
JSONlib.convertToJSON(e),
);
)
// Received ( 'hello': ( 'foo': 42 ) )
// clear OSC listener
OSCdef.clear;
More is described in the SCdoc documentation.
Developed by @julian and me @ IMM Düsseldorf
Enjoy!