0

The situation I'm dealing with is taking the the data from a JSON object (represented as a JavaScript object) extracting some of the data and with that data producing a new object, using JavaScript. The new object will also consist of new added data.

Lets say I have the following object:

sprite_set = {
    "frames": {
        "grass.png": {
            "frame": {
                "x": 1766,
                "y": 202
            },
            "rotated": false,
            "sourceSize": {
                "w": 128,
                "h": 128
            }
        },
        "dirt1.png": {
            "frame": {
                "x": 1766,
                "y": 202
            },
            "rotated": false,
            "sourceSize": {
                "w": 128,
                "h": 128
            }
        },
        "dirt2.png": {
            "frame": {
                "x": 2766,
                "y": 402
            },
            "rotated": false,
            "sourceSize": {
                "w": 128,
                "h": 128
            }
        }                
    }
};

From this object I want to form a new object of the from:

sprite_set = {
    "frames": {
        "grass": {
            "frame": {
                "x": 1766,
                "y": 202
            },
            "sourceSize": {
                "w": 128,
                "h": 128
            }
        },
        "dirt": {
            "multi_frames": {
                "frame1": {
                    "x": 1766,
                    "y": 202
                },
                "frame2": {
                    "x": 2766,
                    "y": 402
                }
             },
            "sourceSize": {
                "w": 128,
                "h": 128
            }
        }       
    }
};

So I need to construct a function that takes the raw object and spits out the new object using the following rules:

  1. Remove all "rotated" properties from each "frames"
  2. Rename each sub-object in "frames" to remove the .png so "grass.png" will be changed to "grass"
  3. If a "frames" sub-objects name contains no leading number then just place it unchanged in the new object
  4. If a "frames" sub-objects name does contains a leading number then break each subsequent number into a new subobject whos parent is "multi_frames"

I am really completely new to JSON so any help on just how to start with this would be great. I wan't to learn so as I get some help I will tackle this problem and constantly give an update to how I'm doing it at the bottom of this answer.

One further question, is there a JavaScript library that can make this process a lot easier?

Thanks for anyone's help.

Update

From help from people comments this is that I have so far:

HTML

<input type="file" id="files" name="files[]" />

*JavaScript*

var JsonObj = null;

function handleFileSelect(evt) {
    var files = evt.target.files; // FileList object
    f = files[0];
    var reader = new FileReader();

    // Closure to capture the file information.
    reader.onload = (function (theFile) {
        return function (e) {
            JsonObj = e.target.result
            console.log(JsonObj);
            var parsedJSON = JSON.parse(JsonObj);

            var oldframes = parsedJSON.frames,
                newframes = {};
            for (var framename in oldframes) {
                // var m = framename.match(/(.*)\.[^.]+$/);
                var m = framename.match(/^(.+?)(\d*)\.png$/);
                var newname = m[1];
                var frame = oldframes[framename];
                if (newname in newframes) newframes[newname].multi_frames["frame" + m[2]] = frame.frame;
                else newframes[newname] = {
                    frame: frame.frame,
                    sourcesize: frame.sourcsize
                };
                // or, if it's OK to mutate the old objects, just:
                // delete frame.rotated;
                // newframes[newname] = frame;
            }
            parsedJSON.frames = newframes;

            JsonObj = JSON.stringify(parsedJSON, null, 4)
            console.log(JsonObj);

        };
    })(f);

    // Read in JSON as a data URL.
    reader.readAsText(f, 'UTF-8');
}



document.getElementById('files').addEventListener('change', handleFileSelect, false);

I use the HTML5 File Api to get the JSON file. I get the following error

Uncaught TypeError: Cannot set property 'frame2' of undefined fiddle > (anonymous function)

in reference to the line:

if (newname in newframes) newframes[newname].multi_frames["frame" + m[2]] = frame.frame;

I can't see what the problem is, any ideas anyone?

I have a live JSFiddle here: http://jsfiddle.net/jamiefearon/8kUYj/48/

Now fixed: Fiddle here: http://jsfiddle.net/jamiefearon/8kUYj/50/

1
  • underscoreJs has many great functions for dealing with array and object manipulation. Commented Feb 7, 2013 at 17:39

1 Answer 1

1

This should do it:

var oldframes = sprite_set.frames,
    newframes = {};
for (var framename in oldframes) {
    var m = framename.match(/^(.+?)(\d*)\.png$/); // not assuming it would not match
    var newname = m[1];
    var frame = oldframes[framename];
    if (! (newname in newframes)) {
        newframes[newname] = {
            sourceSize: frame.sourceSize
        };
        if (m[2])
            newframes[newname].multi_frames = {};
    }
    if (m[2])
        newframes[newname].multi_frames["frame"+m[2]] = frame.frame;
    else
        newframes[newname].frame = frame.frame;
}
sprite_set.frames = newframes;
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your answer, running it I get the following error: Uncaught TypeError: Cannot read property '1' of null on the 5th line of your code.
Should be fixed. The regex did not match "grass.png", it always expected a number.
Thanks Bergi. I get a different error now using your regex: Uncaught TypeError: Cannot set property 'frame2' of undefined - I have created a fiddle here: jsfiddle.net/jamiefearon/8kUYj/47
Yeah, the regex was not the only fix needed… See edits

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.