How to unescape json.stringify output inside a object array - javascript

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.

Related

Accessing JSON nested via key with no value using Javascript / jQuery

I'm trying to return the values of JSON objects which are nested within a complex array of objects. Unfortunately I've not been able to do it easily as the structure of the JSON seems unusual; for example:
var cartContents = {
"contents":
{
"ed2be4abf6cc927dd670b567efd42fc3":
{
"id": "1288785070733722605",
"quantity":2,
"limit":10,
"offset":0,
"order":null,
"created_at":"2016-07-06 12:18:10",
"updated_at":"2016-07-06 12:18:34",
"sku":"006",
"title":"Fishing Rod",
"slug":"fishing-rod-lara-fluorescent-print",
"sale_price":0,
"status":{
"value":"Draft",
"data": {
"key":"0",
"value":"Draft"
}
},
"category":
{
"value":"Bottom",
"data":
{
"1228355758422329063":
{
"id":"1238352758122309063",
"order":null,
"created_at":"2016-07-06 11:23:54",
"updated_at":"2016-07-06 11:38:23",
"parent":
{
"value":"All Sports",
"data":
{
"id":"2288364532150634121",
"order":null,
"created_at":"2016-07-06 11:37:25"...
}
}
}
}
}
}
}
}
The following code produces the correct result ("Fishing Rod"):
var x = cartContents.contents;
console.log(x.ed2be4abf6cc927dd670b567efd42fc3.title);
However the whole point is that the 32 character string ('ed2be4abf6cc927dd670b567efd42fc3') represents one of many products, each with a random 32 bit string and therefore they can't be individually coded into the JS.
I've tried a very great deal of different ways. The latest is the following code (where 'carts' is an array of unique 32 character strings:
var x = cartContents.contents;
$.each(carts, function() {
console.log(x.this.title);
});
The result is "jQuery.Deferred exception: Cannot read property 'title' of undefined TypeError: Cannot read property 'title' of undefined".
Would greatly appreciate help accessing the following keys and their values:
"title":"Fishing Rod"
"id":"1238352758122309063"
"created_at":"2016-07-06 11:37:25"
Also worth mentioning that I can't touch the server, therefore I can't change the data structure at all.
Many thanks in advance.

Regular Expressions on array

I am trying to edit the first entry in a array before it placed in another file.
This is it:
(["\"NAMES\":\"cs.js\"},[
I want to turn it into this:
([{"NAMES":"cs.js"},[
I'm using an online regex generator, but so far I've only managed to edit to this point with /.["[\]/ and substituting with ([{:
([{"NAMES\":\"cs.js\"},[
Any help given will be appreciated.
EDIT:
Here is some of the code:
var initialCourseArray = new Array()
initialCourseArray.push(["\"NAMES\":\"cs.js\"},[
{"COURSE_ID":"ENGL 1013"},
{"COURSE_ID":"FAH1"},
{"COURSE_ID":"USHG1"},
{"COURSE_ID":"TECH 1001"},
{"COURSE_ID":"COMS 1403"},
{"COURSE_ID":"COMS 1411"},
{"COURSE_ID":"ENGL 1023"},
{"COURSE_ID":"SS1"},
{"COURSE_ID":"MATH 2914"},
The stuff after is the rest of the values in the array and they do not look like this one so I'm not worried about them.
Second EDIT:
Since there is some confusion about the code that I honestly should have placed in here first, I am using a php file to retreive course data from a test database and then encoding it into JSON, formatting it, and then using fopen and fprintf to place it inside a javascript file. The part I'm giving you is what ends up inside the javascript file.
Third EDIT:
here is the code I am using to format the array. It is very messy because my leader keeps changing the format he wants the result to be in:
$row1 = "\"NAMES\"";
$colon = ":";
$row2 = "\"".$major.".js\"";
$major_name = $row1.$colon.$row2;
//The course data is already loaded into the table. This why I am using array_unshift to place the major_name inside.
array_unshift($major_array, $major_name);
array_push($major_array, "false");
$json_string = json_encode($major_array);
$re = "/.,/";
$subst = "},\r\n";
$json_string = preg_replace($re, $subst, $json_string);
$re2 = "/\,(?=[^.]*$)/";
$subst2 = ",[";
$json_string = preg_replace($re2, $subst2, $json_string, 1);
$first_string = "var initialCourseArray = new Array()";
$second_string = "initialCourseArray.push(";
$end_bracket = "]";
$end_parentheses =")";
There are several issues:
1. Don't manipulate JSON strings
You should never manipulate a string that is the result of json_encode, because you will very likely make the JSON text invalid, which is actually happening in your case.
So using this kind of statements:
$json_string = preg_replace($re, $subst, $json_string);
is asking for trouble. Once you have a $json_string, it should be final. Anything you want to happen to the structure must happen before you call json_encode.
Even if you just want to add line breaks inside a JSON string, don't do it that way. json_code provides a "pretty print" option which will do it for you:
json_encode(...., JSON_PRETTY_PRINT);
2. JavaScript does not have associative arrays
A second problem is that in JavaScript you cannot have something like
["NAMES":"cs.js" ...]
So json_encode will never generate anything like that. If you want named keys in JavaScript (like "NAMES"), you cannot define it as an array, but should define it as an object:
{"NAMES":"cs.js" ...}
json_encode will do that for you if you provide it the corresponding PHP structure (i.e. an associative array) and let it do its job without tampering.
3. Don't add "false"
It does not seem useful to add "false" as an element to the courses array. In JavaScript you can easily check how many elements there are in an array, so there is no need to put a kind of stop-sign at the end.
Anyway, if in JavaScript you refer to an element in an array that does not exist, you get undefined, which you can verify, much like verifying for the value "false".
I would strongly suggest to leave that out.
Suggested code
The PHP code you provided in your question could be replaced with this:
// Add the names element as a separate item next to the courses array,
// which we put in the "courses" property.
$major_array = array(
"names" => $major,
"courses" => $major_array
);
// Turn into JSON text with added line breaks and indentation:
$json_string = json_encode($major_array, JSON_PRETTY_PRINT);
// Don't touch the JSON text anymore, but output it:
echo "var initialCourse = $json_string;";
The output (JavaScript) would be something like:
var initialCourse = {
"names": "cs",
"courses": [
{
"COURSE_ID": "ENGL 1013"
},
{
"COURSE_ID": "FAH1"
},
{
"COURSE_ID": "USHG1"
},
{
"COURSE_ID": "TECH 1001"
},
{
"COURSE_ID": "COMS 1403"
},
{
"COURSE_ID": "COMS 1411"
},
{
"COURSE_ID": "ENGL 1023"
},
{
"COURSE_ID": "SS1"
},
{
"COURSE_ID": "MATH 2914"
}
]
};
As I mentioned above, this is an object structure, not an array structure, because JavaScript does not allow named keys in an array notation. If in JavaScript you need to iterate over the courses in the above structure, you would address the courses property (which is an array), like this:
for (var course of initialCourse.courses) {
console.log('course id: ' + course.COURSE_ID);
}
More concise structure
I must say it is a bit of an over-kill to have objects with just one property. This structure would be more concise and efficient:
var initialCourse = {
"names": "cs",
"courses": [
"ENGL 1013",
"FAH1",
"USHG1",
"TECH 1001",
"COMS 1403",
"COMS 1411",
"ENGL 1023",
"SS1",
"MATH 2914"
]
};
In JavaScript you would iterate over these courses like this:
for (var course of initialCourse.courses) {
console.log('course id: ' + course);
}
If this interests you, you should just add this line to your PHP code, before any of the PHP code I suggested above:
$major_array = array_map(function ($course) { return $course["COURSE_ID"]; }, $major_array);
If you just want to apply it to that line,
find /"?\\"/ and replace " will do it.

How to remove extra layer in JSON data from Firebase?

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);

Convert String to Array of JSON Objects (Node.js)

I'm using Node.js and express (3.x). I have to provide an API for a mac client and from a post request I extract the correct fields. (The use of request.param is mandatory) But the fields should be composed back together to JSON, instead of strings.
I got:
var obj = {
"title": request.param('title'),
"thumb": request.param('thumb'),
"items": request.param('items')
};
and request.param('items') contains an array of object but still as a string:
'[{"name":"this"},{"name":"that"}]'
I want to append it so it becomes:
var obj = {
"title": request.param('title'),
"thumb": request.param('thumb'),
"items": [{"name":"this"},{"name":"that"}]
};
Instead of
var obj = {
"title": request.param('title'),
"thumb": request.param('thumb'),
"items": "[{\"name\":\"this\"},{\"name\":\"that\"}]"
};
Anyone who can help me with this? JSON.parse doesn't parse an array of object, only valid JSON.
How about this:
var obj = JSON.parse("{\"items\":" + request.param('items') + "}");
obj.title = request.param('title');
obj.thumb = request.param('thumb');
JSON.stringify(obj);
Perhaps I'm missing something, but this works just fine:
> a = '[{"name":"this"},{"name":"that"}]';
'[{"name":"this"},{"name":"that"}]'
> JSON.parse(a)
[ { name: 'this' }, { name: 'that' } ]
Node#0.10.13
May be you have old library Prototype. As I remove it, bug has disappeared.
You can try the same code. Once in page with Prototype.js. Second time in new page without library.

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];
}

Categories