In my node (express) app, I want to send a json response back to the client.
It would look something like this.
{"someTshirt":
{small : 'available'},
{med : 'available'},
{large : 'not available'}
}
I'd reiterate through the sizes and append to the response set with its availability. How would I create this object to begin with in plain javascript within app.js? how would I add the 'someTshirtName' to the beginning of this object as well as appending each size's availability to it after the object has been created?
You can build your object like this:
var availability = {"someTshirt":
{
'small': 'available',
'med' : 'available',
'large' : 'not available'
}
};
Then you can access this object with:
availability.someTshirt.small
>>> 'available'
availability.someTshirt.large
>>> 'not available'
However I'd recommend you to use booleans instead of strings, which are easier to manipulate. You can still change the display string later:
var availability = {"someTshirt":
{
'small': true,
'med' : true,
'large' : false
}
};
if (availability.someTshirt.small) {
console.log('available');
}
>>> 'available'
[edit]
Response to the comment:
If you want to create your objects dynamically, you can do the following:
var availability = {};
availability.someTshirt = {};
availability.someTshirt.small = true;
availability.someTshirt.med = true;
availability.someTshirt.large = false;
if (availability.someTshirt.small) {
console.log("available");
} else {
console.log("not available");
}
>>> 'available'
availability.someTshirt.small = false;
if (availability.someTshirt.small) {
console.log("available");
} else {
console.log("not available");
}
>>> 'not available'
If you need to build your object based on JSON string returned to your code, you can use eval statement. for example you have a string variable sJsonResult containing your JSON response. Your code can go something like;
var sJsonResult = "{someTshirt: {small : 'available', med : 'available',large : 'not available'}}";
var o;
eval("o = " + sJsonResult);
alert(o.someTshirt.small);
Related
My Link json test file is the following:
[{"google" : "https://google.com"},{"bing" : "https://bing.com"}]
The javascript requesting the value, using axios:
var Links = './Links'
axios.get(Links)
.then(function(response){
console.log(response.data["google"]);
try {
var Test12 = JSON.stringify(response.data["google"]);
} catch (err) {
var Test12 = 'nothing'
}
The result is undefined.
My goal is to return the value of the input "google" or any input from the JSON and store it in the var as a string.
Since its an array of objects so you should access the values like,
response.data[0].google
OR
response.data[0]["google"]
Your data file is a list with two objects in it.
To access the google item you should access the list element.
var Test12 = JSON.stringify(response.data[0]["google"]);
Although I would change the json file to:
{"google" : "https://google.com", "bing" : "https://bing.com"}
Maybe like this:
var data=[{"google" : "https://google.com"},{"bing" : "https://bing.com"}];
data.forEach(function(el, index) {
Object.keys(el).forEach(function(val) {
console.log(val + " => " + el[val]);
});
});
I'm using const in a function to define a few variables as follows
const printBlock.format({
name : this.matchedData.clientName,
date : this.matchedData.jobDate,
destination : this.matchedData.address,
apartment : this.matchedData.address2,
stateZip : this.matchedData.zipcode
})
From then, I'm printing out all of these things in order that they're declared. However, some of the data doesn't have an apartment number so it'll show up as:
John Doe
6/6/2018
135 Testdemo Avenue
null
NY 11111
Is it possible to use an if function within declaring the consts in order to make it so that:
if (this.matchedData.address2 == null){
//Do nothing
} else {
apartment : this.matchedData.address2,
}
No, but you can use a ternary
var object = {
address: '1111',
apartment : this.matchedData.address2 ? "" : this.matchedData.address2
}
You could use Object.assign and check with property and if not null, take an object for assignment.
printBlock(Object.assign(
{
name: this.matchedData.clientName,
date: this.matchedData.jobDate,
destination: this.matchedData.address,
apartment: this.matchedData.address2,
stateZip: this.matchedData.zipcode
},
this.matchedData.address2 === null || { apartment: this.matchedData.address2 }
));
You can create your object first without the apartment entry and then add the apartment entry if it is not null...
const a = {
name : this.matchedData.clientName,
date : this.matchedData.jobDate,
destination : this.matchedData.address,
stateZip : this.matchedData.zipcode
};
if (this.matchedData.address2 !== null){
a.apartment : this.matchedData.address2;
}
const printBlock({...}) will throw an error because it isn't a valid way to initialize a constant. If printBlock is a function, why not handle null values in the body of printBlock?
function printBlock(obj) {
for (var prop in obj) {
if (obj[prop]) {
console.log(obj[prop]); // or do whatever you mean by 'print'
}
}
}
For instance I have some JSON data like below (The JSON data is just an example, I just want to give out some fake, make up and wrong format JSON as example)
cata :[{
name:test1,
data:['abc1, abc2' , 'abc3,abc4']
}
name:test2,
data:['abc5, abc6' , 'abc7,abc8']
}]
And indeed I need to render it to frontend, therefore I made a new object and try to push data into it
var name = "";
var key= [];
for(var i=0;i<2;i++){
name .push(cata[i].name)
key.push(cata[i].data.join(' + '));
}
var rehandle = {
name : name,
key : key
}
The above is just how i do it now, and which do no provide the desire result, i want to know how could i restore it so i can change the format from
['abc5, abc6' , 'abc7,abc8']
to
abc5+abc6 , abc7+abc8
UPDATE version of the question:
I think i better explain it step by step:
I have some raw data
I have a row of "data" in each set of data
(E.g:data:['abc1, abc2' , 'abc3,abc4'])
I want to change it's format to abc1+abc2 , abc3+abc4 and store it to another variable
I will pass the variable store abc1+abc2 , abc3+abc4 to an object
5.Render it one by one in a table
UPDATE 2
I have seen #pill's answer, am i able to render the data like
for(var i=0;i<cata.length;i++){
var trythis = trythis + '<td>'+name[i]+'</td>' + '<td>'+data[i]+'</td>'
}
To format your data from
['abc5, abc6' , 'abc7,abc8']
to
abc5+abc6 , abc7+abc8
you'd simply use
data.map(k => k.split(/,\s*/).join('+')).join(' , ')
or the ES5 version
data.map(function(k) {
return k.split(/,\s*/).join('+');
}).join(' , ');
For example...
var cata = [{"name":"test1","data":["abc1, abc2","abc3,abc4"]},{"name":"test2","data":["abc5, abc6","abc7,abc8"]}];
var rehandle = cata.reduce(function(o, d) {
o.name.push(d.name);
o.key.push(d.data.map(function(k) {
return k.split(/,\s*/).join('+');
}).join(' , '));
return o;
}, {
name: [],
key: []
});
console.log('rehandle:', rehandle);
Note that I had to fix up your data formatting
With a javascript json object like this:
var data = {
blog : {
title: "my blog",
logo: "blah.jpg",
},
posts : [
{
title: "test post",
content: "<p>testing posts</p><br><p>some html</p>"
},
]
}
var lookup = "blog.title" //this gets generated from a template file
Now I know you can do something like, but these don't quite do what I need:
console.log(data['blog']); //works
console.log(data.blog.title); //works
console.log(data['blog']['title']); //works, but i dont know the depth of the lookup
But I need to be able to do something like the code below because I can't hardcode the structure, it gets generated and stored in lookup each time. Do I have to build this functionality using string cutting and recursion?? I really hope not
console.log(data['blog.title']); //does not work
console.log(data[lookup]); //does not work
EDIT....
Okay, possibly found a workaround. I don't know if this is safe or recommended practice, so comments on that would be great. Or alternative methods. So combining this with the code above.
var evaltest = "var asdf ="+JSON.stringify(data)+";\n"
evaltest += "asdf."+lookup
console.log(eval(evaltest)) //returns correctly "my blog" as expected
You could use dottie https://www.npmjs.org/package/dottie, which allows you to deep traverse an object using strings
var values = {
some: {
nested: {
key: 'foobar';
}
}
}
dottie.get(values, 'some.nested.key'); // returns 'foobar'
dottie.get(values, 'some.undefined.key'); // returns undefined
you could use:
data['blog']['title']
I've experimented with a couple ways of doing this including eval and using a dictionary lookup with switch(exp.length). This is the final version (comments stripped) I created:
var deepRead = function (data, expression) {
var exp = expression.split('.'), retVal;
do {
retVal = (retVal || data)[exp.shift()] || false;
} while (retVal !== false && exp.length);
return retVal || false;
};
//example usage
data = {
a1: { b1: "hello" },
a2: { b2: { c2: "world" } }
}
deepRead(data, "a1.b1") => "hello"
deepRead(data, "a2.b2.c2") => "world"
deepRead(data, "a1.b2") => false
deepRead(data, "a1.b2.c2.any.random.number.of.non-existant.properties") => false
Here's the Gist with full commenting: gist.github.com/jeff-mccoy/9700352. I use this to loop over several thousand items and have had no issues with deep-nested data. Also, I'm not wrapping in try/catch anymore due to the (small) performance hit: jsPerf.
I have the following JSON response from a ajax-request.
var json = {
"response": {
"freeOfChargeProduct": {
"description": "Product",
"orderQty": 5,
"productName": "XYZ",
"qty": 6,
"details": {
"price": 55.5,
"instock": "true",
"focQuantity": 1
}
},
"orderLineId": 4788,
"totalOrderLinePrice": "741.36",
"totalOrderPrice": "1,314.92",
"totalQty": 17
};
The JSON dosen't always return a "freeOfChargeProduct" property. So if I want to get the "freeOfChargeProduct" price, then I have to do the following:
var getFreeOfChargeProductPrice = function() {
var r = json.response;
if (r && r.freeOfChargeProduct && r.freeOfChargeProduct.details) {
return r.freeOfChargeProduct.details.price;
}
return null;
};
No problems. But it's very annoying to check every property in the object, so I created a function that check if a property in a object is defined.
var getValue = function (str, context) {
var scope = context || window,
properties = str.split('.'), i;
for(i = 0; i < properties.length; i++) {
if (!scope[properties[i]]) {
return null;
}
scope = scope[properties[i]];
}
return scope;
};
var price = getValue('json.response.freeOfChargeProduct.details.price');
// Price is null if no such object exists.
Now to my question: Is this a good or bad way to check if a property exists in an object? Any better suggestions/methods?
EDIT:
I don't wan't to use the &&-operator. I am lazy and I'm looking for a reusable method to check if a object (or property of a object) is defined.
:) Thanks!
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.
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) ...
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?).
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 :(
You can have several PM:s for diffrent tasks all depending on the same model object.
In addition this will make the converter object testable in something that could be automatically executed.... err ok maby manually, but anyway.
So the problem of the cumbersome reflection code is really not a problem. But cohesion is a issue, expessially in JavaScript.