JSON.parse giving only the last element as output - javascript

I am using JSON to carry information from NodeJS (server side) to my client side. When I try to parse the JSON in the client side, it outputs only the last element, in this case, 'name: "Sam"'. I want all the elements to be outputted.
I have tried using an array and a variable to be assigned the parsed data. I have also directly tried logging it to the console with: [console.log(JSON.parse(this.response));]. All three gave the same result.
The first console.log returns all the elements in JSON form. The second one returns only the last one. There are 3 elements in total.
I expect all the elements to be assigned to the variable.
request.open('GET', 'http://localhost:3000/listofvoted', true);
request.onload = function () {
console.log(this.response)
console.log(JSON.parse(this.response));
}
request.send();
The JSON I receive:
{
"name": "Bran",
"name": "Ram",
"name": "Sam"
}

Although JSON (which is just a notation) allows for duplicate key names, the guidance is that that they SHOULD be unique. If you want to use JSON to create a JavaScript Object, then you are constrained by the fact that a JavaScript Object cannot have duplicate keys. So although you have valid JSON, it cannot be represented by a JavaScript Object and therefore it will not survive a round trip of being parsed (JSON converted to a JavaScript Object) by JSON.parse and then converted back to JSON.
For your own convenience of working in JavaScript, you could consider changing the JSON representation of your information so that it can be represented as a JavaScript Object.
Here are some alternative ways of representing what you have that may work:
Use an array of discrete objects:
[
{ "name": "Bran" },
{ "name": "Ram" },
{ "name": "Sam }"
]
Use an array of names:
{
"names": [ "Bran", "Ram", "Sam" ]
}
As a final, heavy-handed approach, you don't have to convert your JSON to a JavaScript object. You can parse it using a parser that allows you to provide your own handlers for the syntactic elements that occur in the JSON string and you can handle the duplicate keys in whatever way you wish. May I suggest the clarinet library for doing so.
See also, How to get the JSON with duplicate keys completely in javascript

Related

parse “application/x-www-form-urlencoded” response with javascript

How do you parse a x-www-form-urlencoded string with JavaScript?
I tried to parse to JSON and able to iterate the keys using Object.Keys()
my responseText = {
"response": {
"header": {
"error_code": 0
},
"body": {
"foo": "foobar",
"date": "2018-04-27"
}
}
}
Url encoded forms have the structure key=value&key2=value2&.......
The keys and values are encoded, for more info on url encoding: https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
In case any value is an object with more keys and values inside it, the form will contain each of the keys inside said object as a description of their path relative to the root, using [].
Your example would look like:
response[header][error_code]=0&response[body][foo]=foobar&response[body][date]=2018-04-27
I think with this info you can probably figure it out, just keep in mind that the text is encoded, unlike in my example.

How to access an attribute from a JSON line saved in a position from an array?

This may be a very simple question but I really can't seem to make it work.
I have several JSON lines and a notes array.
Using notes.push(JSONline) I am saving one JSON line per array position, I assume, so in the following manner:
//notes[1]
{"id":"26","valuee":"20","datee":"2016-04-05T15:15:45.184+0100","id2":51}
//notes[2]
{"id":"27","valuee":"134","datee":"2016-04-05T15:15:47.238+0100","id2":53}
//notes[3]
{"id":"26","valuee":"20","datee":"2016-04-05T15:15:45.184+0100","id2":52}
Here is my problem: I want to print one specific attribute, for example id from one specific JSON line in the array. How can I do this?
When I do console.log(notes) it prints all the JSON lines just as expected. But if I do console.log(notes[1]) it prints the first character of the JSON line in that position, not the whole line.
Similarly console.log(notes[1].id) does not print the id from the first JSON line, in fact it prints 'undefined'.
What am I doing wrong?
Thank you so much.
I'd recommend that you parse all the json when you are pushing to notes, like:
notes.push(JSON.parse(JSONLine))
If you are somehow attached to having json strings in an array instead of objects, which I wouldn't recommend, you could always just parse once you have the jsonLine id
JSON.parse(notes[id]).id
Basically, you want to use JSON.parse for either solution and I'd strongly recommend converting them to objects once at the beginning.
You need to remember that JSON is the string representation of a JS object. JS strings have similar index accessor methods to arrays which is why you can write console.log(notes[0]) and get back the first letter.
JavaScript doesn't allow you to access the string using object notation, however, so console.log(notes[0].id) will not work and the reason you get undefined.
To access the data in the string using this method you need to parse the string to an object first.
var notes = ['{"id":"26","valuee":"20","datee":"2016-04-05T15:15:45.184+0100","id2":51}'];
var note0 = JSON.parse(notes[0]);
var id = note0.id;
DEMO
This leaves the question of why you have an array of JSON strings. While it's not weird or unusual, it might not be the most optimum solution. Instead you could build an array of objects and then stringify the whole data structure to keep it manageable.
var obj0 = {
"id": "26",
"valuee": "20",
"datee": "2016-04-05T15:15:45.184+0100",
id2: 51
};
var obj1 = {
"id": "27",
"valuee": "134",
"datee": "2016-04-05T15:15:47.238+0100",
"id2": 53
}
var arr = [obj0, obj1];
var json = JSON.stringify(arr);
OUTPUT
[
{
"id": "26",
"valuee": "20",
"datee": "2016-04-05T15:15:45.184+0100",
"id2": 51
},
{
"id": "27",
"valuee": "134",
"datee": "2016-04-05T15:15:47.238+0100",
"id2": 53
}
]
You can then parse the JSON back to an array and access it like before:
var notes = JSON.parse(json);
notes[0].id // 26
That's because you have {"id": "value"... as a string in your key value pairs. "id" is a string so you can't reference it like a property. 1. use
var notes = JSON.parse(notes);
as mentioned in the comments by The alpha
or remove the quotes try
{id:"26", ...}
that's why notes[i].id is returning undefined

make mongoDB replace single value array with string

I'm very new to mongoDB and am trying to insert an object to the database. (Wow, much more fun than mySQL...). I'm using strongloop's loopback framework and its mongoDB connector.
The object is a xml2js parsed xml message I receive, after parsing and inserting to mongo it looks like this:
{
"_id": ObjectID("55c61ee9391da88435c5753f"),
"offerChange": [
{
"foo": [
"bar"
],
"baz": [
"foo"
]
}
]
}
as you can see, all the key's values are arrays, though all of them contain only one value. Obviously I can convert them to strings before the insert or during xml parsing, but that would require looping over all the object's keys or more work for the worker in the first place, which I'd like to avoid. The real object is much bigger than above shown.
Is there a way to tell mongoDB to automatically convert arrays that have only one value to a string before or after the document gets created?
You need not loop through and convert from array to string in application/database. xml2js provide a neat way to return string if there is only one item and array if there are more items.
explicitArray (default: true): Always put child nodes in an array if
true; otherwise an array is created only if there is more than one.
Initiate your parser as follows
parseString(xml, {explicitArray: false}, function (err, result) {
});

JSON object creation error

I am trying to create a JSON object in the particular format
{ "id": 12234 , "name": "Alex" , "gender": "Male"}
// My code starts here
var number = userid; // alert(userid) is 12345
var name= nameuser; // alert(nameuser) is Alex
var g= gender; // alert(gender) is male
var userObj = { "id": number , "name": name , "gender":g}
I tried `JSON.stringify(userObj); ,
that returns the object type as
{"id":"12345" , "name":"Alex" , "gender":"Male"}
but this is not what I want as I want the number to be 12345 and not "12345".
also tried stringifying the fields inside the object like
{ "id": number , "name":JSON.stringify(name) ,gender: JSON.stringify(g)}
but when I do alert(userObj) my object type is Object object and this is not a format the server recognises.
I am sure there is a workaround for this but I am unable to figure one out
JSON works with strings exclusively. It's invalid to have anything other than a string, array, or other JSON object in JSON. That said, a "number" is not allowed; it needs to be a string. Whatever you are working with with the JSON later needs to be able to change the string back it to a number, if necessary. JavaScript usually does a good job of coercing these.
On the server side you can just do something like
obj = json_decode(source)
obj.id = (int)obj.id
I think that your solution will come down to what you want to DO with the JSON, rather than how you want it to be formatted.
If you're using it in other JavaScript code, then the JSON.parse method is going to take care of most of your issue on the other side (with automatic type-casting dealing with the rest).
If you're using it on the server-side, again, PHP or similar will decode the object appropriately.
And if it's a more-strict language on your server, all you need to do is remember which parameters need to be cast to boolean or to int/float.
The below code from your question is valid JSON.
{ "id": 12234 , "name": "Alex" , "gender": "Male"}
I am guessing that the problem you have is that your userid variable is a string, not a number. If so, try
var number = parseInt(userid, 10);
(The 10 parameter indicates that you are using base 10 numbers as opposed to something like binary or hex).
store the object type as one of the property and use it to convert the way you want.

Generating Tree Structure from Flat Array in JavaScript (without using object references)

I'm trying to generate a tree structure in JavaScript from a flat array. This would usually be a fairly straightforward proposition - simply retain a 'stack' array with references to ancestor objects of the current working scope ordered by nesting depth - push a new element onto the stack when entering another nested level, and pop it off when leaving one, replacing the current working element with the object referenced by the (new) last array item.
Unfortunately this requires the capability to pass-by-reference, which JavaScript doesn't have (well, doesn't have in any meaningful way that I know how I could use for this problem.)
To give a bit of background, I'm trying to turn an arbitrarily long/complicated string containing nested XML-style (but not XML, so an XML parser can't be used instead) tokens into a structure similar to the one below:
Expected Input:
[
"<token>",
"<my non compliant token>",
"some text at this level",
"<some other token>",
"some more text",
"<yet another token>",
"more text",
"</yet another token>",
"blah!",
"</some other token>",
"</token>",
"more text"
]
Expected Output
[
{
"token": "<token>",
"children": [
{
"token": "<my non compliant token>",
"children": [
"some text at this level",
{
"token": "<some other token>",
"children": [
"some more text",
{
"token": "<yet another token>",
"children": [ "more text" ]
},
"blah!"
]
}
]
}
]
},
"more text"
]
To clarify - I'm not after an entire algorithm (but I'd be interested if you want to provide your implementation) - just a good method for maintaining current position in the outputted tree (or an entirely different/better way of generating tree objects!) Don't get too caught up on how the tokens work - they're not XML and for the purpose of the exercise could be formatted entirely differently.
Any input would be greatly appreciated!
Your strings look easy to parse. I think I would do something like this:
var stack = [];
var array = [];
for (var i in strings) {
var s = strings[i];
if (s.indexOf("</") == 0) {
array = stack.pop();
} else if (s.indexOf("<") == 0) {
var obj = {token: s, children: []};
array.push(obj);
stack.push(array);
array = obj.children;
} else {
array.push(s);
}
}
Idea #1
Here's an answer you probably weren't anticipating.
Looking at your expect output, I was wondering if it's easiest to just generate JSON and then eval it when you're done. No references at all.
When going through your flat array, you basically have three operations:
You add more data to the current object
You close off the current object
You create a new child object
You can do all three of those fairly easily by just appending the appropriate text onto a JSON string you're building as you iterate through your source array to literally just generate the text you show in your expected output. When done, run that JSON string through eval. You may need a few safety checks to verify that each array and object is closed properly if there are errors in the input, but it should work fine.
Idea #2
You can still use your stack array. I'm not sure exactly why you need to pass by reference, but you can just pass an index into the array around and have everyone modify the master copy of the array that way via index. Using local functions, the master array can be a common data value that is local to your main function, but essentially global to all your sub-functions so they can all shared access to it.
This would look something like this:
function ParseRawData(rawData)
{
var parentScopeArray = []; // main parent scope of objects
function processTag(x)
{
// you can access parentScopeArray directly here and
// and be accessing it by reference
}
// other code or local functions here
}
Idea #3
If you want to pass the array into a function and have the master copy modified (perhaps the reason you're thinking of pass by reference), the javascript design pattern is to pass the array in and return a modified array, replacing the entire original array with the modified one that is returned.

Categories

Resources