I have the following JSON response from a ajax-request.
var json = {
\"response\": {
\"freeOfChargeProduct\": {
\"description\": \"Prod
if(x && typeof x.y != 'undefined') {
...
}
// or better
function isDefined(x) {
var undefined;
return x !== undefined;
}
if(x && isDefined(x.y)) {
...
}
This will work for any data type in JavaScript, even a number that is zero. If you are checking for an object or string, just use x && x.y
within the if statement, or if you already know that x is an object, if(x.y) ...
This is not a syntax issue as it is a design pattern issue.
Question A. * Do you have control of the json server?
If the answer to this is no, which I assume, the situation will be all on the client.
Please read this: http://martinfowler.com/eaaDev/PresentationModel.html
As the server is the source, in this case it will provide the model. This pattern specifies an additional artifact: The presentation model (PM). In javascript i would suggest two artifacts, a additional for the convertor code.
According to this design pattern the PM is responsible for converting the model to the PM, and back again if necessary. In your case no conversion from PM to M will ever occur.
This means that a js object has a method or constructor that digest the model and translate itself, with the help of the convertor (below).
Doing this you will end up with a PM looking like this:
var OrderlinePM = {
"hasFreeOfCharge": false | true,
"freeOfCharge" : {...}
`enter code here`
this.getFreeOfCharge = function() {
...
}
this.fromModel = function(jsonEntry, convertor) {
//convert this with the convertor ;) to a for this specific view usable OrderlinePM
// also inwith
...
}
enter code here
"orderLineId":0,
"totalOrderLinePrice":"741.36",
"totalOrderPrice":"1,314.92",
"totalQty":17
};
function mySpecialFunctionPMConvertor {
this.fromModel = function() {
... //do strange stuff with the model and poulate a PM with it.
}
}
Ok, I give up trying to format code in this rich text editor :(
So the problem of the cumbersome reflection code is really not a problem. But cohesion is a issue, expessially in JavaScript.
You could do something like this:
try{
var focp = json.response.freeOfChargeProduct
var text = "You get " + focp.qty + " of " +
focp.productName +
" for only $" + (focp.qty-focp.details.focQuantity)*focp.details.price +
", You save $" + focp.details.focQuantity*focp.details.price;
$("order_info").innerText = text;
} catch(e) {
// woops, handle error...
}
It would generate a message like this from the provided data in your question if the fields exists:
You get 6 of XYZ for only $277,5, You save $55.5
If the data is non-existing, you'll end up in the catch block. You could always just to a Try, Catch, Forget here if you can't come up with a way to handle the error (Maybe do a new AJAX request for the data?).
Use the guard pattern:
if (json.response && json.response.freeOfChargeProduct && json.response.freeOfChargeProduct.details) {
// you can safely access the price
}
This is how the guard pattern works.
if (a && a.b && a.b.c) { ... } else { ... }
The first check is "Does the property a
exist?". If not, the else-branch gets executed. If yes, then the next check occurs, which is "Does object a
contain the property b
?". If no, the else-branch executes. If yes, the final check occurs: "Does the object a.b
contain the property c
?". If no, the else-branch executes. If yes (and only then), the if-branch executes.
Update: Why is it called "guard pattern"?
var value = a && b;
In this example, the member b
(the right operand) is guarded by the &&
operator. Only if the member a
(the left operand) is truthy ("worthy"), only then the member b
is returned. If, however, the member a
is falsy ("not worthy"), then it itself is returned.
BTW, members are falsy if they return these values: null
, undefined
, 0
, ""
, false
, NaN
. Members are truthy in all other cases.