Parse JSON with mxj net.udp.recv and dict.deserialize

Philip's icon

I'm trying to grab a JSON stream in Max and modify it before passing it on. I've used [mxj net.udp.recv] to grab the stream (stripped down to a very basic example), and this prints something JSONy to the console:

print: {"number": 0}

I patched the output of [mxj net.udp.recv] into [dict.deserialize obj], and expected this to put the JSON stream in to a dictionary, as stated in the documentation. However, I can't find any evidence of this from [dict.view], [dict.print] etc. If I patch [dict.deserialize obj] into [dict.print] I get:

dict.print: dictionary obj

Any thoughts welcome

read_json_stream.maxpat
Max Patch
Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

this seems to work (adapted from help file):

Although depending on the structure of the json stream, you may have to save the stream to file first then import the file into a dict...(just a guess)

Philip's icon

Thanks for your answer. The example works fine, but this is using Max's message format rather than JSON?

If I pass (via UDP) the string "objects : 3" (i.e. the equivalent of the max message) then the dict objects work ok. Yet, if I pass the same string in JSON format "{\"objects\" : 3}" it completely fails. Are there peculiarities in the JSON interpreter for dicts in Max?

Philip's icon

I should probably add that the strings are written from a python script hence the escape characters in the JSON.

Pc

Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

OK philip, thanks for the question, because it forces me to figure it out:
[tosymbol] is your magic bullet:

Philip's icon

Ah, thanks! It's magic-ish, although it falls over with more complicated JSON e.g.
{"position": {"x": 1.000000, "y": 1.000000, "z": 0.0 } }

I'm looking into splitting the input with regexp then parsing further, but if you have any other ideas I'd be very glad to hear them.

Many thanks

Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

it actually does work, it's just you need to escape the double quotes with a backslash, when a json string is represented in a message box:
"{\"position\": {\"x\": 1., \"y\": 1., \"z\": 0. } }"
(except for the enclosing double quotes at the start and end which tell max to treat the whole thing as a symbol)
but this is not relevant to any environment outside of max's message box, so if you try to send a standard json string to your max patch via udp from another environment it should work as expected... best thing to do is try to break it again to prove me wrong...;-)

Philip's icon

hmm, does the message modified from my post above work in your patch? It doesn't seem to work here, although the animal-based message is fine. It seems to struggle with the nested {}

read_json_stream1.maxpat
Max Patch
Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

I don't know-- it works on my version of max... try dict.print instead of print object:

Philip's icon

How odd. Thanks for the tip on [tosymbol]. Here's what I ended up with - nesting the dicts seemed to do the trick. Attached patch reads a JSON message, modifies a value and passes it on as JSON. It's a bit manual and would fall over if the keys in the stream changed, but it's not likely to change too much (or at least, too often) in my case.

read_json_stream2.maxpat
Max Patch
mlucenkiw's icon

Floating Point, you saved my life. That little chunk of code was the missing link! THANK YOU!