JSON to Dictionary: how to add new associations?

Hi guys a quick question here,
I’m used to work with Dictionaries in the following way


// create the dict
a = Dictionary.new();
// this is a dictionary indeed
a.class;
// eventually add new associations to it
a.put(\cat, 10);
a.add(\dog -> 1);
// here we are
a.keys;

but, when the dictionary has been created parsing a JSON file, I’m not able to add new association inside it.


(
{
// read the JSON file
var path = "/path/to/my/test.json";
var f = File( path, "r");
~myDict = f.readAllString.parseJson;
}.value();
);

// this is also a dictionary 
~myDict.class; 
// it has some association in it, obviously 
// (depending on what's the JSON content)
~myDict.keys;
// but these lines will throw an error
~myDict.put(\cat, 10);
~myDict.add(\dog -> 1);

Why?
Are this dictionary different in some way?

It seems to me the second on (the JSON one) is “locked” whitout the possibility to expand itself with new associations. How can I pursue my goal of adding new associations in it?

I’ve also tried to examine the String.sc source file but I wasn’t able to completely understand.

[...]
parseYAML {
	_String_ParseYAML
	^this.primitiveFailed
}

parseJSON {
	^this.parseYAML
}
[...]

BTW, what does the _String_ParseYAML mean? Where can I find the source code for this “function(?)” ?

Thank you
n

It would help if you would show the actual JSON string/file and the actual error messages.

One thing to watch out is that parseJSON treats all keys and values as Strings. Take for example the following JSON string:

~dict = "{ \"foo\": 123, \"bar\": 5 }".parseJSON;

The key “foo” is a String, not a Symbol, so
~dict[\foo]nil
but
~dict["foo"]123

(Note how 123 is actually a String, not a Number.)

Don’t know if this is related to your problem. Hard to tell without an actual example.

_String_ParseYAML is a call to a primitive. These are C++ functions that are used for efficiency reasons. The “Writing Primitives” Help-Page has more Information.

https://doc.sccode.org/Guides/WritingPrimitives.html

1 Like

Thank you @Spacechild1 for your explanation.
I don’t think this is an error related to my erratic interpretation on types.

Sorry, I forgot to put an example on the actual JSON file I’m using. Please finde below the actual JSON file I’m using as a base for my tests (even if, at least according to my experiments, it seems to me not to be related on the kind ond JSON file).

{
	"myObjects": [
		{	"index":0,"name":"object_A", "value":0.11	},
		{	"index":1,"name":"object_B", "value":0.21	},
		{	"index":2,"name":"object_C", "value":0.31	},
		{	"index":3,"name":"object_D", "value":0.41	}
	]
}

After parsing it and getting a corresponding dictionary on the language side, every time I try to add new associations (like this ~myDict.put(\cat, 10) ) it raises an error like the one shown below:

ERROR: Primitive '_BasicPut' failed.
Index out of range.
RECEIVER:
Instance of Array {    (0x55750c027758, gc=BC, fmt=01, flg=00, set=02)
  indexed slots [2]
      0 : "myObjects"
      1 : instance of Array (0x55750c027608, size=4, set=2)
}
PATH: /home/nicola/Documenti/sketchbooks/SC_sketchbook/Dictionary_tests/01_test_normal_dict_and_json_dict.scd
CALL STACK:
	MethodError:reportError
		arg this = <instance of PrimitiveFailedError>
	Nil:handleError
		arg this = nil
		arg error = <instance of PrimitiveFailedError>
	Thread:handleError
		arg this = <instance of Thread>
		arg error = <instance of PrimitiveFailedError>
	Object:throw
		arg this = <instance of PrimitiveFailedError>
	Object:primitiveFailed
		arg this = [*2]
	Dictionary:put
		arg this = <instance of Dictionary>
		arg key = 'cat'
		arg value = 10
		var atKey = nil
		var index = -2
	Interpreter:interpretPrintCmdLine
		arg this = <instance of Interpreter>
		var res = nil
		var func = <instance of Function>
		var code = "~myDict.put(\cat, 10);"
		var doc = nil
		var ideClass = <instance of Meta_ScIDE>
	Process:interpretPrintCmdLine
		arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Primitive '_BasicPut' failed.
Index out of range.
RECEIVER: [ myObjects, [ Dictionary[ (name -> object_A), (value -> 0.11	), (index -> 0) ], Dictionary[ (name -> object_B), (value -> 0.21	), (index -> 1) ], Dictionary[ (index -> 2), (name -> object_C), (value -> 0.31	) ], Dictionary[ (name -> object_D), (value -> 0.41	), (index -> 3) ] ] ]

I’ve also tried adding association using string instead of symbol (~myDict.put("cat", 10) ) I’m getting the same error ( '_BasicPut' failed. Index out of range. )

ERROR: Primitive '_BasicPut' failed.
Index out of range.
RECEIVER:
Instance of Array {    (0x55750c027758, gc=BC, fmt=01, flg=00, set=02)
  indexed slots [2]
      0 : "myObjects"
      1 : instance of Array (0x55750c027608, size=4, set=2)
}
PATH: /home/nicola/Documenti/sketchbooks/SC_sketchbook/Dictionary_tests/01_test_normal_dict_and_json_dict.scd
CALL STACK:
	MethodError:reportError
		arg this = <instance of PrimitiveFailedError>
	Nil:handleError
		arg this = nil
		arg error = <instance of PrimitiveFailedError>
	Thread:handleError
		arg this = <instance of Thread>
		arg error = <instance of PrimitiveFailedError>
	Object:throw
		arg this = <instance of PrimitiveFailedError>
	Object:primitiveFailed
		arg this = [*2]
	Dictionary:put
		arg this = <instance of Dictionary>
		arg key = "cat"
		arg value = 10
		var atKey = nil
		var index = -2
	Interpreter:interpretPrintCmdLine
		arg this = <instance of Interpreter>
		var res = nil
		var func = <instance of Function>
		var code = "~myDict.put("cat", 10);"
		var doc = nil
		var ideClass = <instance of Meta_ScIDE>
	Process:interpretPrintCmdLine
		arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Primitive '_BasicPut' failed.
Index out of range.
RECEIVER: [ myObjects, [ Dictionary[ (name -> object_A), (value -> 0.11	), (index -> 0) ], Dictionary[ (name -> object_B), (value -> 0.21	), (index -> 1) ], Dictionary[ (index -> 2), (name -> object_C), (value -> 0.31	) ], Dictionary[ (name -> object_D), (value -> 0.41	), (index -> 3) ] ] ]

By the way, I’ve also tried parsing your JSON string instead of a file and I get same errors

~dict = "{ \"foo\": 123, \"bar\": 5 }".parseJSON;
~dict.put(\cat, 10);   // --> doesn't work
~dict.add(\cat -> 1);  // --> doesn't work
~dict.put("cat", 10);  // --> doesn't work
~dict.add("cat" -> 1); // --> doesn't work

Do you know why?


Thank you @mstep for your explanation, I’ve actually found this primitive definition inside the lang/LangPrimSource/PyrStringPrim.cpp source code file. I will dig deep on this.

i-d suspect the problem has something to do with index being “-2”.

1 Like

great @mstep,
but why would the index be -2?
is something I did not specify myself :thinking:

And, fun fact, this is always -2 regardless of the value or key to be added.
Is this a bug?

Last post for at least a month, I’m out.

hjh

2 Likes

Thank you @jamshark70 :pray: