make mongoDB replace single value array with string - javascript

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

Related

JSON.parse giving only the last element as output

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

JSON array with single element

I am working on a project that has JSON format output. I need a clarity on the JSON array structure. So There are fields that are multiple entry like an array. If an element is an array but has only one value, does it still include an array node '[' in the structure?
Example:
This is a sample JSON element which is an array and has multiple values.
"Talents": [
{
"Items": "test"
},
{
"Items": "test"
}
]
If this element does not have multiple values, will it appear as below?
"Talents":
{
"Items": "test"
}
The '[' does not appear for an array type element with single value. Can someone Pls clarify this?
Single-item arrays will still include the array brackets in JSON format, as they are still arrays. In other words, there is no such native mechanism which converts single-item arrays to a non-array representation. So with your single-item example, it would be represented like this:
"Talents": [
{
"Items": "test"
}
]
You can easily test this out with some simple code:
let jsonSingleItem = { "Talents": [ {"Items": "item1"} ] };
let arraySingleItem = [ {"Items": "item1"} ];
console.log(JSON.stringify(jsonSingleItem));
console.log(jsonSingleItem);
console.log(arraySingleItem);
Which yields the following output:
{"Talents":[{"Items":"item1"}]}
{ Talents: [ { Items: 'item1' } ] }
[ { Items: 'item1' } ]
So in all cases (a stringified JSON object, native JSON, and a javascript array) the single item is still in an array.
Note: It is not uncommon that a consumer of an API will send data (i.e. JSON) in ways which are outside the agreed-upon contract/schema that API defines, and this (sending an object instead of a single-object array when there is just one item) is one example I have seen before. It would be up to the owner/developer of the API as to whether they build in flexibility to handle input which deviates from the API schema.
Square brackets ("[]") denotes JSONArray which in your case can access like
Talents[0]
will return
{
"Items": "test"
}
In second case, curve brackets denotes an JSON object. If you want to access value of items. Than you can by
Talents.Items
OR
Talents["Items"]
will return
"Test"
for complete reference,
JSON Syntax

Accessing Elements of JS Object

I have created array in a object,
var obj_report_dailog = { array_report_dailog : [] }
Then push data to object,
obj_report_dialog.array_report_dialog.push({from: fromDate})
obj_report_dialog.array_report_dialog.push({to: toDate})
obj_report_dialog.array_report_dialog.push({fabrika: fabrika})
Then,
var json = JSON.stringify(obj_report_dialog);
How can I access to elements of that object?
console.log("işte bu: " + json);
output:
işte bu: {"array_report_dialog":[{"from":"2017-08-01"},{"to":"2017-09-21"},{"fabrika":["Balçova"]}]}
Two things:
You don't want to JSON.stringify unless you're sending the resulting string somewhere that will parse it. Remember, JSON is a textual notation for data exchange; JSON.stringify gives you a string to send to some receiver. When you have the JSON string, you don't access the properties of the objects in it.
If you're receiving that JSON string, you'd parse it via JSON.parse and then access the properties on the result.
Leaving aside the JSON thing, you probably don't want to add data the way you're adding it. You're adding three separate objects as three entries in the array, each with one property. You probably want to push one object with all three properties:
obj_report_dialog.array_report_dialog.push({
from: fromDate,
to: toDate,
fabrika: fabrika
});
Then you'd access them as obj_report_dialog.array_report_dialog[0].from, obj_report_dialog.array_report_dialog[0].to, and obj_report_dialog.array_report_dialog[0].fabrika. Or more likely, you'd have a loop like this:
obj_report_dialog.array_report_dialog.forEach(function(entry) {
// Use entry.from, entry.to, and entry.fabrika here
});
(See this answer for more options for looping through arrays.)
But, if you really want to push them as separate objects, you'd access them as obj_report_dialog.array_report_dialog[0].from, obj_report_dialog.array_report_dialog[1].to, and obj_report_dialog.array_report_dialog[2].fabrika (note the indexes going up).
If you stringify a json, it's gonna create a string representation of your object.
To access data in a string like that we usually use JSON.parse that create an json object from a string. Which is the obj_report_dailog you had at start.
You can make object from json by using JSON.parse()
JSON.parse(json).array_report_dialog

How to convert a string to JSON format?

I was getting list in array form. So at first place i converted array list to string-
var myJsonString = JSON.stringify(result);
myJsonString="[{"productId":"PI_NAME",
"firstName":null,
"lastName":null,
"customer":null
},
{"productId":"PI_NAME",
"firstName":null,
"lastName":null,
"customer":null
}]"
But again i need to convert myJsonString to Json format, What i need to do? I mean i need to replace 1st" and last ", I guess
You need to call parse now.
JSON.parse(myJsonString)
First, if you ever find yourself building a JSON string by concatenating strings, know that this is probably the wrong approach.
I don't really understand how the first line of your code relates to the second, in that you are not doing anything with JSON-encoded string output from result, but instead just overwriting this on the following line.
So, I am going to limit my answer to show how you could better form JSON from an object/array definition like you have. That might look like this:
// build data structure first
// in this example we are using javascript array and object literal notation.
var objArray = [
{
"productId":"PI_NAME",
"firstName":null,
"lastName":null,
"customer":null
},{
"productId":"PI_NAME",
"firstName":null,
"lastName":null,
"customer":null
}
];
// now that your data structure is built, encoded it to JSON
var JsonString = JSON.stringify(objArray);
Now if you want to work with JSON-encoded data, You just do the opposite:
var newObjArray = JSON.parse(JsonString);
These are really the only two commands you should ever use in javascript when encoding/decoding JSON. You should not try to manually build or modify JSON strings, unless you have a very specific reason to do so.

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