1

I have a valid JSON object like this:

{
    "reasons": {
        "options": [
            {
                "value": "",
                "label": "Choose a reason",
                "selected": true,
                "requiresValidation": false
            },
            {
                "value": "small",
                "label": "Too little",
                "selected": false,
                "requiresValidation": false
            },
            {
                "value": "big",
                "label": "Too big",
                "selected": false,
                "requiresValidation": false
            },
            {
                "value": "unsuitable",
                "label": "I don't like it",
                "selected": false,
                "requiresValidation": true
            },
            {
                "value": "other",
                "label": "Other",
                "selected": false,
                "requiresValidation": true
            }
        ]
    }
}

and I have a variable which stores one value (e.g. unsuitable) of an option available in options. How can I retrieve the value of requiresValidation field for the value stored in the variable without having to loop through all of the objects values inside options?

For instance, if the var content is other I'd like to access to requireValidation field of the object whose value is other (which is true). Is it possible? Thank you.

Quirico
  • 23
  • 1
  • 5
  • 3
    Either redesign the JSON to a different object structure or you will have to loop. – epascarello Feb 27 '13 at 21:33
  • 3
    you don't deal with json directly. it's just a transport format. you convert the json back to a native data structure, then deal with the native structure only. e.g. decode the json to a javascript object, then it's just `obj.reasons.options[i].requiresValidation` – Marc B Feb 27 '13 at 21:33
  • What is the justification for avoiding a for loop? – Jason Sperske Feb 27 '13 at 21:51
  • Thanks to @epascarello, redesigning JSON is the best trade-off. Marc: I'd like to achieve the goal with no conversion. Jason: it's just a matter of optimization. The real JSON is longer and inside the page I'd have to loop many times. – Quirico Feb 28 '13 at 11:27

4 Answers4

2

You aren't really dealing with JSON here, you are dealing with a JS object. JSON is just a format for sending JS objects.

options is an array. The only way to access it is by index, which means you will have to do a search, one item at a time. There are functions, such as indexOf() which will return the first index of a value in an array, however, you have an array of objects, so that will not work in this case. (And internally, it is still doing a search).

function getReqVal(val) {
    for (var item in mydata.reasons.options) {
       if(item.value == val) {
           return item.requiresValidation;
       }
    }
}

getReqVal("other");

The caveat is that this will return on the first one, so if you have more than one other, you won't get them.

If the options are indeed unique values, I would rearrange your object to be an associative array, with the keys being the "value" items, and the values being an object with the rest of the data:

{
    "reasons": {
        "options": {
            "" : {
                "label": "Seleziona una voce",
                "selected": true,
                "requiresValidation": false
            },
            "small" : {
                "label": "Too little",
                "selected": false,
                "requiresValidation": false
            },
            "big" : {
                "label": "Too big",
                "selected": false,
                "requiresValidation": false
            },
            "unsuitable" : {
                "label": "I don't like it",
                "selected": false,
                "requiresValidation": true
            },
            "other" : {
                "label": "Other",
                "selected": false,
                "requiresValidation": true
            }
        }
    }
}
Jeff B
  • 29,943
  • 7
  • 61
  • 90
0

If you are (or could be) using underscore.js you could use the find method:

var item = _.find(myObj.reasons.options, 
                  function(option){ return option.value == 'some value' });
Abe Miessler
  • 82,532
  • 99
  • 305
  • 486
0

Assuming you can't change the JSON structure itself (because perhaps you're getting it from an external source?), you can read it into a new object of your design per Marc B's suggestion. Ideally, this new object would let you index into your options array using the value key. Let's do that:

function MyOptions(optionsJSON) {
    this.original_json = optionsJSON;
    this.length = optionsJSON.reasons.options.length;
    var original_options = optionsJSON.reasons.options;
    for(var i = 0; i < this.length; i++)
       this[original_options[i].value] = original_options[i];
}

var my_opts = new MyOptions(original_JSON);

var item_requiresValidation = my_opts["unsuitable"].requiresValidation;
console.log(item_requiresValidation); // should log "true"

The trade-off here is that your code will need to loop through the entire options array once, but after that you can index into the objects using the value key without searching. Validate with this jsfiddle.

Austin Mullins
  • 7,307
  • 2
  • 33
  • 48
  • A valid proposal, Austin!. I've opted for the solution submitted by Jeff B. since I could modify JSON structure a little bit. – Quirico Feb 28 '13 at 11:40
0

You could use array filter. Some variation of this:

var $reasons = //Your JSON

function checkVal(element, index, array) {

    return (element.value == "other");
}

var filtered = $reasons.reasons.options.filter(checkVal);

alert(filtered[0].requiresValidation);

Or jQuery grep might help you with the filter without looping: http://api.jquery.com/jQuery.grep/

Simon C
  • 9,458
  • 3
  • 36
  • 55