Write to JSON File

Is there an analog to the String.parseJSON for writing? I guess I could make a fancy format string that would write the things i want to, but it would be nice to take a Dictionary and ship it to the filesystem directly.

Edit: actually, it doesn’t have to be JSON. I’m looking to store some synth configs (and maybe make it easy to load presets). And JSON seemed like a good idea. But anything else that would enable me to save and load some numbers would work.

Something like this?

d= Dictionary.newFrom([\a, 3, \b, 2, \c, 1]);
f = File("~/test.json".standardizePath,"w");

SuperCollider makes it really easy to store things inside files and get them back.

Instead of “File.read”, which manipulates a string, you can also execute the file to get the content back directly, if you stored the data using .asCompileString :

// You can't do this if the file is not saved
var currentFolder = thisProcess.nowExecutingPath.dirname ++ "/";

// Datas stored inside an IdentityDictionary
var saveDatas = (
	foo: 5,
	bar: "test"

var saveFile, loadDatas;

// Saving the ID inside a file
saveFile = File(currentFolder ++ "saveFile.scd", "w");

// Retrieving the ID back
loadDatas = this.executeFile(currentFolder ++ "saveFile.scd");
// No conversion needed, this isn't a string, it's an ID dict (it's an Event, but it's the same)

Please note, if this makes sense to you, that you can use this to create new instances of an object prototype. This might help organizing the code/project, and allows you to quickly copy-paste an object prototype from a project to an other, or to dynamically load them :

var currentFolder = thisProcess.nowExecutingPath.dirname ++ "/";

// Object Prototype
var calculatorProto = (
	square: { |self, number|
		number * number

var protoFile, instance;

// Saving the ID inside a file
protoFile = File(currentFolder ++ "calculatorProto.scd", "w");

// Creating a new instance
instance = this.executeFile(currentFolder ++ "calculatorProto.scd");
1 Like

The following code is my attempt.
The code does not support array. You will need to modify the code including adding some lines to parse array.

~asJson =  { |dictionaryOrEvent|
	var txt, func;
	txt = "{\n";
	func = { |item, depth=0|
		var keys, tab;
		keys = item.keys.asArray.sort;
		(depth + 1).do{ tab = tab ++ "\t" };
		keys.do { |thisKey, index|
			var subDepth;
			subDepth = depth + 1;
			txt = txt ++ tab ++ thisKey.asString.quote ++ ":";
			if ("Event|Dictionary".matchRegexp(item[thisKey].class.asString)) {
				txt = txt + "{\n";
				func.(item[thisKey], subDepth);
				txt = txt ++ tab ++ "},\n"
			} {
				txt = txt + item[thisKey];
				txt = txt ++
				if (index == (keys.size - 1)) {
				} {
					", \n"
	txt ++ "}"

d = Dictionary.newFrom([\a, 3, \b, 2, \c, 1]);
e = (a: (aa: 2, ab: 3), b: 5, c: 4);
g = (a: (aa: 2, ab: 3), b: Dictionary.newFrom([\ba, 3, \bb, 2, \bc, 1]);, c: 4);
h = (a: [(aaa: 2, aab:3), (aba: 2, abb:3)])


~asJson.(h) // not transcribed

~jsonFile = "~/Downloads/test.json".standardizePath

~writeJSON = File(~jsonFile, "w+");
~writeJSON << ~asJson.(g)

~readJSON = File(~jsonFile, "r")

Please let me know if this works. I think it would be good if this function (of course array should be parsed correctly) was implemented as a method in the core library or quarks.

Maybe this helps

1 Like

Object.writeArchive and Object.readArchive are super easy. You just can’t expect to be able to human-read the file:

a = Array.fill(10, {[1.0.rand, 2.0.rand, 3.0.rand]});


b = Object.readArchive(Platform.defaultTempDir++"testArchive");



Ah, cool, thanks folks!

I’m going to give the .asCompileString method a try since I don’t necessarily need to make the content human editable.