Discuss Scratch

-EmeraldThunder-
Scratcher
1000+ posts

Parsing the project.json

Recently I have been trying to make a project that involves parsing a certain blockstack from the project.json.
The only problem is the json is terribly cryptic
{"targets":[{"isStage":true,"name":"Stage","variables":{},"lists":{},"broadcasts":{},"blocks":{"UWAQRO#JH($,v]k]*%t-":{"opcode":"procedures_definition","next":null,"parent":null,"inputs":{"custom_block":[1,"eGs#PRQt$[c{JaBw.Ycy"]},"fields":{},"shadow":false,"topLevel":true,"x":44,"y":-814},"eGs#PRQt$[c{JaBw.Ycy":{"opcode":"procedures_prototype","next":null,"parent":"UWAQRO#JH($,v]k]*%t-","inputs":{"6*`%0%3taVb_0K@8S6j{":[1,"FVjWl{@Q7{EKrqu^BM[a"]},"fields":{},"shadow":true,"topLevel":false,"mutation":{"tagName":"mutation","children":[],"proccode":"Add text %s","argumentids":"[\"6*`%0%3taVb_0K@8S6j{\"]","argumentnames":"[\"text\"]","argumentdefaults":"[\"\"]","warp":"true"}},"FVjWl{@Q7{EKrqu^BM[a":{"opcode":"argument_reporter_string_number","next":null,"parent":"eGs#PRQt$[c{JaBw.Ycy","inputs":{},"fields":{"VALUE":["text",null]},"shadow":true,"topLevel":false},":F#RYjH/Z`PLC4{HVquV":{"opcode":"procedures_call","next":null,"parent":null,"inputs":{"6*`%0%3taVb_0K@8S6j{":[1,[10,"Scratch!"]]},"fields":{},"shadow":false,"topLevel":true,"x":49,"y":-667,"mutation":{"tagName":"mutation","children":[],"proccode":"Add text %s","argumentids":"[\"6*`%0%3taVb_0K@8S6j{\"]","warp":"true"}}},"comments":{},"currentCostume":0,"costumes":[{"assetId":"cd21514d0531fdffb22204e0ec5ed84a","name":"backdrop1","md5ext":"cd21514d0531fdffb22204e0ec5ed84a.svg","dataFormat":"svg","rotationCenterX":240,"rotationCenterY":180}],"sounds":[{"assetId":"83a9787d4cb6f3b7632b4ddfebf74367","name":"pop","dataFormat":"wav","format":"","rate":48000,"sampleCount":1123,"md5ext":"83a9787d4cb6f3b7632b4ddfebf74367.wav"}],"volume":100,"layerOrder":0,"tempo":60,"videoTransparency":50,"videoState":"on","textToSpeechLanguage":null}],"monitors":[],"extensions":[],"meta":{"semver":"3.0.0","vm":"0.2.0-prerelease.20210811102104","agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67"}}
How can I decode the when flag clicked blockstack from this into a javascript object with an operation key as the name of each custom block and an inputs array with the decoded text of each input. How can I achieve this using vanilla javascript.
The code this represents is simply:

Last edited by -EmeraldThunder- (Aug. 13, 2021 07:02:04)

Pufferfish_Test
Scratcher
500+ posts

Parsing the project.json

Take a look at https://en.scratch-wiki.info/wiki/Scratch_File_Format for the sb3 ‘specification’ and https://github.com/LLK/scratch-vm/blob/develop/src/serialization/sb3.js for an example of how scratch parses the project.json.
-EmeraldThunder-
Scratcher
1000+ posts

Parsing the project.json

Pufferfish_Test wrote:

Take a look at https://en.scratch-wiki.info/wiki/Scratch_File_Format for the sb3 ‘specification’ and https://github.com/LLK/scratch-vm/blob/develop/src/serialization/sb3.js for an example of how scratch parses the project.json.
Thank you these resources seem to be rather helpful, I will read them properly later.
imfh
Scratcher
1000+ posts

Parsing the project.json

Well, first of all you’ll want to prettify the json. That should help you make a little more sense of the garbled mess:
{
    "targets":[
        {
            "isStage":true,
            "name":"Stage",
            "variables":{
                
            },
            "lists":{
                
            },
            "broadcasts":{
                
            },
            "blocks":{
                "UWAQRO#JH($,v]k]*%t-":{
                    "opcode":"procedures_definition",
                    "next":null,
                    "parent":null,
                    "inputs":{
                        "custom_block":[
                            1,
                            "eGs#PRQt$[c{JaBw.Ycy"
                        ]
                    },
                    "fields":{
                        
                    },
                    "shadow":false,
                    "topLevel":true,
                    "x":44,
                    "y":-814
                },
                "eGs#PRQt$[c{JaBw.Ycy":{
                    "opcode":"procedures_prototype",
                    "next":null,
                    "parent":"UWAQRO#JH($,v]k]*%t-",
                    "inputs":{
                        "6*`%0%3taVb_0K@8S6j{":[
                            1,
                            "FVjWl{@Q7{EKrqu^BM[a"
                        ]
                    },
                    "fields":{
                        
                    },
                    "shadow":true,
                    "topLevel":false,
                    "mutation":{
                        "tagName":"mutation",
                        "children":[
                            
                        ],
                        "proccode":"Add text %s",
                        "argumentids":"[\"6*`%0%3taVb_0K@8S6j{\"]",
                        "argumentnames":"[\"text\"]",
                        "argumentdefaults":"[\"\"]",
                        "warp":"true"
                    }
                },
                "FVjWl{@Q7{EKrqu^BM[a":{
                    "opcode":"argument_reporter_string_number",
                    "next":null,
                    "parent":"eGs#PRQt$[c{JaBw.Ycy",
                    "inputs":{
                        
                    },
                    "fields":{
                        "VALUE":[
                            "text",
                            null
                        ]
                    },
                    "shadow":true,
                    "topLevel":false
                },
                ":F#RYjH/Z`PLC4{HVquV":{
                    "opcode":"procedures_call",
                    "next":null,
                    "parent":null,
                    "inputs":{
                        "6*`%0%3taVb_0K@8S6j{":[
                            1,
                            [
                                10,
                                "Scratch!"
                            ]
                        ]
                    },
                    "fields":{
                        
                    },
                    "shadow":false,
                    "topLevel":true,
                    "x":49,
                    "y":-667,
                    "mutation":{
                        "tagName":"mutation",
                        "children":[
                            
                        ],
                        "proccode":"Add text %s",
                        "argumentids":"[\"6*`%0%3taVb_0K@8S6j{\"]",
                        "warp":"true"
                    }
                }
            },
            "comments":{
                
            },
            "currentCostume":0,
            "costumes":[
                {
                    "assetId":"cd21514d0531fdffb22204e0ec5ed84a",
                    "name":"backdrop1",
                    "md5ext":"cd21514d0531fdffb22204e0ec5ed84a.svg",
                    "dataFormat":"svg",
                    "rotationCenterX":240,
                    "rotationCenterY":180
                }
            ],
            "sounds":[
                {
                    "assetId":"83a9787d4cb6f3b7632b4ddfebf74367",
                    "name":"pop",
                    "dataFormat":"wav",
                    "format":"",
                    "rate":48000,
                    "sampleCount":1123,
                    "md5ext":"83a9787d4cb6f3b7632b4ddfebf74367.wav"
                }
            ],
            "volume":100,
            "layerOrder":0,
            "tempo":60,
            "videoTransparency":50,
            "videoState":"on",
            "textToSpeechLanguage":null
        }
    ],
    "monitors":[
        
    ],
    "extensions":[
        
    ],
    "meta":{
        "semver":"3.0.0",
        "vm":"0.2.0-prerelease.20210811102104",
        "agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67"
    }
}
Then you’ll need to loop through each target and find the sprite you want. Then you’ll need to loop through the targets blocks until you find the green flag. Then you’ll need to loop through each block under the green flag and parse it. Roughly in pseudo code:
for target in sb3.targets:
if target.name == "my name":
break

doesn't check if the target was actually found

for block in target.blocks:
if block.opcode == "event_whenflagclicked":
break

doesn't check if the green flag was actually found

blockid = block.next
while blockid is not None:
block = target.blocks[blockid]

doesn't check if the block is actually a custom block call

get all of the name up to the first argument
name = block.mutation.proccode.split("%")
name will probably have a space on the end you’ll want to remove

input_names = decode_json(block.mutation.argumentnames)

do something with all this info

blockid = block.next

Last edited by imfh (Aug. 13, 2021 12:12:58)

-EmeraldThunder-
Scratcher
1000+ posts

Parsing the project.json

What encoding format are the block names and inputs using, anything I try to decode them fails.
imfh
Scratcher
1000+ posts

Parsing the project.json

-EmeraldThunder- wrote:

What encoding format are the block names and inputs using, anything I try to decode them fails.
The argument names lists is encoded with json. Did you try the JavaScript function JSON.parse()?

Edit: The custom block arguments, that is. If you’re talking about block opcodes and inputs, not custom blocks arguments, the blocks should already be decoded.

Last edited by imfh (Aug. 13, 2021 12:45:49)

Powered by DjangoBB