How to remove extra layer in JSON data from Firebase? - javascript

I'm trying to use Underscore.js to get some data from the JSON returned from Firebase but there are a lot of null values returned. The JSON being returned from Firebase currently looks like this:
{
"-JFnc68gIRFohkWKBP05":
{
"date":"2014-02-15T03:39:16.954Z",
"description":"Thanks so much!",
"name":"Rob",
"role":"Give"
},
"-JFncNSO4G_hNm0YySTA":
{
"date":"2014-02-15T03:40:27.858Z",
"description":"This is fun!",
"name":"Cobie",
"role":"Received"
},
"-JFrhlpgCWxJnDETM1gg":
{
"date":"2014-02-15T22:42:31.013Z",
"description":"Brought over some really delicious cookies",
"name":"John Smith",
"role":"Gave"
},
"-JFrjHlV-fsOVHyTXHZJ":
{
"date":"2014-02-15T22:49:08.448Z",
"description":"Charles was wonderfully patient.",
"name":"Charles Darwin",
"role":"Received"
},
"-JFsWZPbL6_j-9nQwP29":
{
"date":"2014-02-16T02:28:47.950Z",
"description":"On the Origin of Species... yaddi daddi da....",
"name":"Charles Darwin",
"role":"Gave"
},
"-JFsWdH61Y-I01-rqn_n":
{
"date":"2014-02-16T02:29:07.887Z",
"description":"Let me off to do my computer work without bugging me.",
"name":"Cobie",
"role":"Gave"
}
}
When I use Underscore.js to extract data, these are samples of how it comes out:
javascript:
$scope.allNames = _.pluck($scope.data, 'name');
output:
["","","","","","","","","","","","Rob","Cobie","John Smith","Charles Darwin","Charles Darwin","Cobie"]
javascript:
$scope.something = _.groupBy(userRef, 'userRef.name');
output:
{"undefined":[null,null,null,null,null,null,null,null,null,null,null,{"date":"2014-02-15T03:39:16.954Z","description":"Thanks so much!","name":"Rob","rating":5,"role":"Give"},{"date":"2014-02-15T03:40:27.858Z","description":"This is fun!","name":"Cobie","rating":4,"role":"Received"},{"date":"2014-02-15T22:42:31.013Z","description":"Brought over some really delicious cookies","name":"John Smith","rating":3,"role":"Gave"},{"date":"2014-02-15T22:49:08.448Z","description":"Charles was wonderfully patient.","name":"Charles Darwin","rating":"2","role":"Received"},{"date":"2014-02-16T02:28:47.950Z","description":"On the Origin of Species... yaddi daddi da....","name":"Charles Darwin","role":"Gave"},{"date":"2014-02-16T02:29:07.887Z","description":"Let me off to do my computer work without bugging me.","name":"Cobie","role":"Gave"}]}
How do I get deep enough into the JSON to not return the nulls? Or, If there is a better way to remove the headers from the JSON entirely?

Resolved the issue with first removing the empty strings using underscore's _.without function.
$scope.allcontacts = _.without(messy_contacts, "")

You can use underscore compact for this.
$scope.allcontacts = _.compact(messy_contacts);

Related

Finding the latest index of a particular key with inconsistent JSON?

Suppose I have some JSON like below:
[
{
"date": "2020-12-25",
"total_cases": 469482.0,
"new_cases": 2260.0,
"new_cases_smoothed": 2115.571,
"total_deaths": 9816.0,
"new_deaths": 63.0,
"new_deaths_smoothed": 80.857,
"total_cases_per_million": 2125.388,
"new_cases_per_million": 10.231,
"new_cases_smoothed_per_million": 9.577,
"total_deaths_per_million": 44.438,
"new_deaths_per_million": 0.285,
"new_deaths_smoothed_per_million": 0.366,
"new_tests": 54649.0,
"total_tests": 6482889.0,
"total_tests_per_thousand": 29.349,
"new_tests_per_thousand": 0.247,
"new_tests_smoothed": 38118.0,
"new_tests_smoothed_per_thousand": 0.173,
"positive_rate": 0.056,
"tests_per_case": 18.0,
"tests_units": "tests performed"
},
{
"date": "2020-12-26",
"total_cases": 471335.0,
"new_cases": 1853.0,
"new_cases_smoothed": 2006.714,
"total_deaths": 9874.0,
"new_deaths": 58.0,
"new_deaths_smoothed": 77.714,
"total_cases_per_million": 2133.777,
"new_cases_per_million": 8.389,
"new_cases_smoothed_per_million": 9.085,
"total_deaths_per_million": 44.701,
"new_deaths_per_million": 0.263,
"new_deaths_smoothed_per_million": 0.352,
"new_tests": 40953.0,
"total_tests": 6523842.0,
"total_tests_per_thousand": 29.534,
"new_tests_per_thousand": 0.185,
"new_tests_smoothed": 37101.0,
"new_tests_smoothed_per_thousand": 0.168,
"positive_rate": 0.054,
"tests_per_case": 18.5,
"tests_units": "tests performed"
},
{
"date": "2020-12-27",
"total_cases": 473309.0,
"new_cases": 1974.0,
"new_cases_smoothed": 2048.714,
"total_deaths": 9929.0,
"new_deaths": 55.0,
"new_deaths_smoothed": 76.714,
"total_cases_per_million": 2142.714,
"new_cases_per_million": 8.936,
"new_cases_smoothed_per_million": 9.275,
"total_deaths_per_million": 44.95,
"new_deaths_per_million": 0.249,
"new_deaths_smoothed_per_million": 0.347,
"new_tests": 33270.0,
"total_tests": 6557112.0,
"total_tests_per_thousand": 29.685,
"new_tests_per_thousand": 0.151,
"new_tests_smoothed": 36539.0,
"new_tests_smoothed_per_thousand": 0.165,
"positive_rate": 0.056,
"tests_per_case": 17.8,
"tests_units": "tests performed"
},
{
"date": "2020-12-28",
"new_tests": 32205.0,
"total_tests": 6589317.0,
"total_tests_per_thousand": 29.83,
"new_tests_per_thousand": 0.146,
"new_tests_smoothed": 36172.0,
"new_tests_smoothed_per_thousand": 0.164,
"tests_units": "tests performed"
}
]
Out of this array of records in the JSON, I'm looking to grab the most recent instance of "total_cases". Here is the JavaScript I wrote to satisfy this:
const total_cases = (data[data.length - 1].total_cases);
Obviously, this doesn't work, because the last record in the array doesn't contain an instance of the "total_cases" key. I'm fetching from the source using HTTP GET, and it is updated daily, so sometimes the latest record has the keys I'm looking for, but other times I get a TypeError.
My question is if there is any way to find the index of the latest record that has a particular key I'm looking for, when the JSON has some inconsistencies like this. The alternative is to say hell with it and look for another source. I'm considering that option, because this is too much of a hassle to work with, but I'm still curious as to what could be done. Hope that makes sense.
You could reverse the array and then use the Array.find method.
const total_cases = data
.slice() // Since reverse() changes the array in place, we need a copy of the original array
.reverse()
.find(record => record.total_cases !== undefined)
.total_cases;
A possible way to do that would be by reversing the array and then use Array.prototype.find() to search for the most recent record with total cases.
data.reverse().find(r => r.total_cases);
You can do something like this, that I find easy to understand for you and for the next dev reading your code
data
.sort((i1, i2) => i1.date > i2.date ? -1 : 1)
.filter(item => Boolean(item.total_cases))
[0].total_cases

How to unescape json.stringify output inside a object array

I'm getting a bad response when i post a json.stringify via fetch, and the problem is from escaped quotes that json.stringify is producing. It works when I remove them manually, but I need this to be done automatically.
var order = {
"from_country": "US",
"line_items": [
{
"quantity": 1,
"unit_price": 19.95
}
],
"to_country": "US"
};
var body = JSON.stringify(order);
var body will display as:
{"from_country":"US","line_items":"[{\"quantity\": 1, \"unit_price\": 19.95}]","to_country":"US"}
I'd like it to display as:
{"from_country":"US","line_items":"[{"quantity": 1, "unit_price": 19.95}]","to_country":"US"}
The issue was that my file includes the prototype library.
I fixed the conflict, while still maintaining the functionality(I think) of prototype by adding this code -
JSON = JSON || {};
JSON.stringify = function(value) { return Object.toJSON(value); };
JSON.parse = JSON.parse || function(jsonsring) { return jsonsring.evalJSON(true); };
I first stumbled on this being the problem here:https://stackoverflow.com/a/20331694/8326722
which led me to https://stackoverflow.com/a/1327371/8326722 and then I added the bit from a comment to get it to work with objects.
If someone can explain how the code I'm using works, that would be nice.

angular, strip unused data before doing a lodash _.isEqual

So I have am trying to compare 2 objects using lodash's _.isEqual method, I have pretty straight forward function that checks like so
function findMatchingQuery(savedSearch) {
if (_.isEqual(savedSearch.data.document.query, $scope.searchResults.minify())) {
return true;
}
}
The data has changed a bit and I need to pull out a piece of data inside before I do a compare.
So the each of those objects has this format -
{
"name": "item name",
"showMore": boolean,
"filters": []
}
And what I would like to do is strip out the showMore node. I tried to add the some vars using _.remove, however it seems this does not work because remove is looking for a key and value.
var modifiedSavedSearch = _.remove(savedSearch.data.document.query, { "showMore" });
var modifiedCurrentSearch = _.remove($scope.searchResults.minify(), { "showMore" });
Is there a simple way to strip away those parts of the object before running the _.isEqual on them? Doesn't have to be lodash. Thanks!
You can delete the attribute, like:
delete savedSearch.data.document.query.showMore
You can use _.omit to remove it, or you can use _.pick to pick the rest of the attributes
Yeah, omit should do what you are looking for:
var modifiedSavedSearch = _.omit(savedSearch.data.document.query, { "showMore" });
If you want to get rid of it completely, you can do the following:
// assuming this is your variable
var myVar = {
"name": "item name",
"showMore": boolean,
"filters": []
};
// delete the unwanted property
delete myVar.showMore;

JavaScript JSON parse by a given key without looping

Given a JSON string as this:
{
"__ENTITIES": [
{
"__KEY": "196",
"__STAMP": 1,
"ID": 196,
"firstName": "a",
"middleName": "b",
"lastName": "c",
"ContactType": {},
"addressCollection": {
"__deferred": {
"uri": "/rest/Contact(196)/addressCollection?$expand=addressCollection"
}
},
"__ERROR": [
{
"message": "Cannot save related entity of attribute \"ContactType\" for the entity of datastore class \"Contact\"",
"componentSignature": "dbmg",
"errCode": 1537
}
]
}
]
}
Is there a method to get just the __ERROR record, I know I can use
var mydata = json.parse(mydata) and then find it from the mydata object. But I was hoping there was a method to only return the ERROR field something like
json.parse(mydata, "__ERROR") and that gets only the information in the __ERROR field without turning the whole JSON string into an object
"Is there a method to get just the __ERROR record, I know I can use var mydata = json.parse(mydata) ... But I was hoping there was ... something like json.parse(mydata, "__ERROR")"
There may be libraries that do this, but nothing built in. You need to write code that targets the data you want.
The closest you'll get will be to pass a reviver function to JSON.parse.
var errors = [];
var mydata = JSON.parse(mydata, function(key, val) {
if (key === "__ERROR")
errors.push(val);
return val
});
without turning the whole json string into an object
That's hardly possible, you would need some kind of lazy evaluation for that which is not suitable with JS. Also, you would need to write your own parser for that which would be reasonable slower than native JSON.parse.
Is there a method to get just the __ERROR record
Not that I know. Also, this is an unusual task to walk the whole object tree looking for the first property with that name. Better access __ENTITIES[0].__ERROR[0] explicitly.
If such a function existed, it would have to parse the whole thing anyway, to find the key you're looking for.
Just parse it first, then get the key you want:
var mydata = JSON.parse(mydata);
var errorObj = mydata.__ENTITIES[0].__ERROR[0];
If you want, you may create your own function:
function parseAndExtract(json, key) {
var parsed = JSON.parse(json);
return parsed[key];
}

Number of items in a json array

Looking for a simple bit of JS to count the number of items in a .json file (each item represents, in this case, an instagram photo being pulled into the web app; I want to count the number of photos). Json is structured thusly...
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"geometry":{
"coordinates":[
-79.40916,
43.87767
],
"type":"Point"
},
"properties":{
"longitude":-79.40916,
"latitude":43.87767,
"title":"",
"user":"cmay2400",
"id":"176051485697457528_13947894",
"image":"http:\/\/distilleryimage0.instagram.com\/1d725a3a8d7511e181bd12313817987b_7.jpg",
"images":{
"low_resolution":{
"url":"http:\/\/distilleryimage0.instagram.com\/1d725a3a8d7511e181bd12313817987b_6.jpg",
"width":306,
"height":306
},
"thumbnail":{
"url":"http:\/\/distilleryimage0.instagram.com\/1d725a3a8d7511e181bd12313817987b_5.jpg",
"width":150,
"height":150
},
"standard_resolution":{
"url":"http:\/\/distilleryimage0.instagram.com\/1d725a3a8d7511e181bd12313817987b_7.jpg",
"width":612,
"height":612
}
},
"description":"Today's ride <span class=\"tag\">#zipcar<\/span>",
"instagram_id":"13947894",
"likes":1,
"profile_picture":"http:\/\/images.instagram.com\/profiles\/profile_13947894_75sq_1322267355.jpg"
}
},
{
"type":"Feature", [...]
I just want to loop through the json file and count the number of items. Completely lost on where to begin.
Parse the JSON string into an object and use it as you would any other object in JavaScript:
var o = JSON.parse(jsonstring);
alert(o.features.length); /* number of items in features array */
This is more or less the code you are looking for:
var variable = jQuery.parseJSON( stringThatIsStoringJson );
for(var i=0;i<variable.features.length;i++) {
doStuff(variable.features[i]);
for(var j=0;j<variable.features[i].geometry.coordinates.length;j++) {
doMoreStuff(variable.features[i].geometry.coordinates[j]);
}
}
Assuming you are using jQuery. You can parse the JSON with whatever library you want. Just avoid eval(), which opens your site to XSS vulnerabilities.
Of course, the first thing you must transform the json string into js object. by use JSON.parse()(IE6\7 not support) or include the Crockford's JSON2 parser in order to support it on IE < 8.
var obj = JSON.parse(jsonstr);
// loop the obj to find out what you want
Or another way, you can try to use some lib like jsonSelect (CSS-like selectors for JSON.) or something like JSONPath, then you can easy to manipulate your data like:
var reslut = JSONSelect.match('css selector', obj);

Categories