Skip to content

Commit

Permalink
Merge pull request #11 from musikinformatik/null-ref
Browse files Browse the repository at this point in the history
Null ref
  • Loading branch information
telephon authored Jan 19, 2023
2 parents 9662973 + f4acfce commit f5c7460
Showing 1 changed file with 53 additions and 22 deletions.
75 changes: 53 additions & 22 deletions classes/JSONlib.sc
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
JSONlibNull {}


JSONlib {

var <>postWarnings;
Expand Down Expand Up @@ -53,7 +50,8 @@ JSONlib {
};
^case
{ v.isKindOf(Symbol) } { this.prConvertToJson(v.asString) }
{ v == "null" or: { v.class == JSONlibNull } or: { v == nil } } { "null" }
// only check value if it is a ref
{ v.isNil or: { v.isKindOf(Ref) and: { v.value.isNil } } } { "null" }
// sc closely implements the JSON string, see https://www.json.org/json-en.html
// but the post window parses \n as linebreak etc. which makes copying of the JSON from
// the post window error prone
Expand Down Expand Up @@ -117,8 +115,8 @@ JSONlib {
{ v.isString and: { "^[-]?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?$".matchRegexp(v.asString) } } { v.asFloat }
{ v == "true" } { true }
{ v == "false" } { false }
// an event can not store nil as a value so we replace it with JSONNull
{ v == nil } { if(useEvent, {JSONlibNull()}, {nil}) }
// an event can not store nil as a value so wrap it in a Ref
{ v == nil } { Ref(nil) }
{ v.isArray } { v.collect { |x| this.prConvertToSC(x) } }
{ v.isKindOf(Dictionary) } {
if(useEvent) {
Expand Down Expand Up @@ -173,7 +171,7 @@ TestJSONlib : UnitTest {
\array: [1,2,3],
\true: true,
\false: false,
\null: JSONlibNull(),
\null: `nil,
);
var j = JSONlib.convertToJSON(o);
this.assertEquals(j, "{ \"array\": [ 1, 2, 3 ], \"false\": false, \"null\": null, \"number\": 10, \"object\": { \"foo\": \"bar\" }, \"string\": \"string\", \"true\": true }");
Expand Down Expand Up @@ -276,22 +274,13 @@ TestJSONlib : UnitTest {

test_nullEncode {
var o = (
null: JSONlibNull()
null: `nil
);
var j = JSONlib.convertToJSON(o);
this.assertEquals(
j,
"{ \"null\": null }",
"Use JSONlibNull to represent null in event";
);

o = Dictionary();
o.put("null", JSONlibNull());
j = JSONlib.convertToJSON(o);
this.assertEquals(
j,
"{ \"null\": null }",
"Use JSONlibNull to represent null in event";
"Use Ref(nil) to represent null in event";
);

// .parseJson allows us to store nil in a dict
Expand Down Expand Up @@ -319,6 +308,7 @@ TestJSONlib : UnitTest {
);
}

// encoding of non-json values
test_functionAsValue {
var o = (
\func: {|x| "hello".postln}
Expand Down Expand Up @@ -348,6 +338,43 @@ TestJSONlib : UnitTest {
);
}

// additional ref/nil test
test_anotherFunctionAsValue {
// primary purpose to verify null check
var o = (
\func: { |x| x !? (x+1) },
);
var j = JSONlib.convertToJSON(o);
this.assertEquals(
j,
"{ \"func\": \"{ |x| x !? (x+1) }\" }",
".value should not get called on a non-ref",
);
}

test_ref {
var o = (
\ref: `42,
);
var j = JSONlib.convertToJSON(o);
this.assertEquals(
j,
"{ \"ref\": \"`(42)\" }",
"Non-nil refs should be encoded as compile strings",
);
}

test_stringNull {
var o = (
\null: "null",
);
var j = JSONlib.convertToJSON(o);
this.assertEquals(
j,
"{ \"null\": \"null\" }",
"A \"null\" string should be represented as a string",
)
}

// decoding tests - taken from json.org
// we only test for valid json
Expand All @@ -364,12 +391,13 @@ TestJSONlib : UnitTest {
test_valuesDecode {
var j = TestJSONlib.prLoadJsonFile("values.json");
this.assertEquals(j[\string], "string", "Value can be strings");
this.assertEquals(j[\number], 10, "Value can be integer numebrs");
this.assertEquals(j[\number], 10, "Value can be integer numbers");
this.assertEquals(j[\object][\foo], "bar", "Values can be objects");
this.assertEquals(j[\array], [1, 2, 3], "Value can be an array");
this.assertEquals(j[\true], true, "Value can be true");
this.assertEquals(j[\false], false, "Value can be false");
this.assertEquals(j[\null].class, JSONlibNull, "Value can be null");
this.assertEquals(j[\null].class, Ref, "Null needs to be wrapped in a Ref");
this.assertEquals(j[\null].value, nil, "Unwrapping Ref(nil) should be nil");
}

test_stringsDecode {
Expand Down Expand Up @@ -419,9 +447,12 @@ TestJSONlib : UnitTest {
test_jsonNullDecode {
var p = TestJSONlib.prJsonFilePath("values.json");
var j = JSONlib.parseFile(p, useEvent: true);
this.assertEquals(j[\null].class, JSONlibNull, "As an Event can not store nil as value we implemented JSONlibNull");
this.assert(j.keys.asArray.includes(\null), "Null ref value needs to have a key in event");
this.assertEquals(j[\null].value, nil, "As an Event can not store nil we wrap it in a Ref");
j = JSONlib.parseFile(p, useEvent: false);
this.assertEquals(j["null"], nil, "the SC dict can store nil");
j.keys.asArray.postln;
this.assert(j.keys.asArray.any({|x| x == "null"}), "Null ref value needs to have a string key in dictionary");
this.assertEquals(j["null"].value, nil, "As a Dictionary can not store nil we wrap it in a Ref");
}

test_jsonEncodeDict {
Expand Down

0 comments on commit f5c7460

Please sign in to comment.