0

Problem: When sending data to MongoDB via AJAX, the subarry name points[0][x] is becoming a single string: "points[0][x]". How do I prevent the key from becoming a single string?

I added an object into MongoDB using Ajax post like this:

if(errorCount === 0) {
    var newDesign = {
        filename: 'designs/documents-desktop.jpg',
        title: 'Tester',
        slug: 'tester',
        pos: '1',
        points: [
            {
                x: '0.40',
                y: '0.211',
                title: 'test',
                content: 'Blank for now'
            },
            {
                x: '0.295',
                y: '0.090',
                title: 'Another Test',
                content: 'Blank for now again'
            }
        ]
    }

    $.ajax({
        type: "POST",
        data: newDesign,
        url: "/data/add-design",
        dataType: 'JSON',
    }).done(function(response) {
        if(response.msg === '') {

        } else {
            alert("ERROR: " + response.msg);
        }
    });
}

Then I use getJSON to GET this, and use console.log to output this.points[0][x]:

$.getJSON('/data', function(data) {
    $.each(data, function() {
        console.log(this.points[0][x])
    });
});

But it doesn't work and I get this error:

 Uncaught TypeError: Cannot read property '0' of undefined

You can see that all of the data is there when your console.log the entire object, but each subarray key is a single string:

{"_id":"54bcb74584a4c8bd05e3d772","filename":"designs/documents-desktop.jpg","title":"Tester","slug":"tester","pos":"1","points[0][x]":"0.40","points[0][y]":"0.211","points[0][title]":"test","points[0][content]":"Blank for now","points[1][x]":"0.295","points[1][y]":"0.090","points[1][title]":"Another Test","points[1][content]":"Blank for now again"}

You can also see in a mongo terminal that points[0][x] is becoming a single string:

 db.filelist.find().pretty();
{
    "_id" : ObjectId("54bcc85384a4c8bd05e3d777"),
    "filename" : "designs/documents-desktop.jpg",
    "title" : "Tester",
    "slug" : "tester",
    "pos" : "1",
    "points[0][x]" : "0.40",
    "points[0][y]" : "0.211",
    "points[0][title]" : "test",
    "points[0][content]" : "Blank for now",
    "points[1][x]" : "0.295",
    "points[1][y]" : "0.090",
    "points[1][title]" : "Another Test",
    "points[1][content]" : "Blank for now again"
}

Is there something I'm missing here? I don't seemingly have any mistakes in the server side with NodeJS and Express. What could be the problem?

Erick Maynard
  • 731
  • 6
  • 18
  • What does your `data` object look like? Is it really an array that you need to iterate through, or is it an object like the one you post? If it is an object then you should be able to access _without_ the `each` function. For example, `data.points[0][x]` – My Head Hurts Jan 19 '15 at 08:54
  • This all seems to have gone wrong when you "added the object" from "AJAX Post" as you say. This has serialized incorrectly and nested structures have ended up as strings. That's the part of your code that has caused the real problem. We need to see what happened on "create". Edit to show that code. – Neil Lunn Jan 19 '15 at 08:54
  • It's the serverside code that is messing up, and that's what's interesting. What does the schema/model look like, and how are you getting and returning the data to the ajax call – adeneo Jan 19 '15 at 09:07
  • @ErickMaynard I don't need to "tag" you ( which is what the whole @ thing is about here ) but you need to "tag" the person you are responding to (welcome to StackOverflow). Couple of things. I really think you should be calling `JSON.stringify` on your ajax post request. I'm sure the `dataType` from jQuery(or lite via angular) actually means on the "return response" and not the serialize of the post. Mainly though we need to see your "server code" that is accepting the post. And whether you have the "body parser" middle-ware set up correctly. Check those and insert console.log before editing. – Neil Lunn Jan 19 '15 at 09:16
  • Point is check your `req.body` if the body parser is set up correctly then this will be a JavaScript Object and not a string. But first fix your ajax POST to stringify the object first. Http only understands "strings" – Neil Lunn Jan 19 '15 at 09:24
  • And again, what does the schema look like? Mongo is clearly not accepting `points` as an array, but is converting the array into strings for keys and values – adeneo Jan 19 '15 at 09:35
  • @adeneo Are you now convinced that your thinking is in the wrong area. So Erick. Please make sure that your jQuery code sets the "body" or "data" for the request via `JSON.stringify(newDesign)` as was pointed out already. – Neil Lunn Jan 19 '15 at 09:51
  • @NeilLunn - maybe, jQuery parses objects as data just fine, but it does create `form/www encoded` data, not JSON, and that probably won't work when inserting the data directly in the DB (which is a terrible idea btw). Stringifying could perhaps work, but just sticking `req.body` in the DB should be changed to something safer. – adeneo Jan 19 '15 at 09:58
  • @NeilLunn Ok I tried doing JSON.stringify(newDesign) and that did not fix the problem. – Erick Maynard Jan 19 '15 at 10:00
  • @adeneo Actually it doesn't and it shouldn't, and furthermore that has nothing to do with jQuery specifically outside of posting the correct form of request. As you should know, the correct mime type is "application/json" on the post request and the content is delivered as a String. – Neil Lunn Jan 19 '15 at 10:01
  • Then again, Mongo's `insert` expects a document, or an array of documents, and documents are objects, not JSON strings, so you'd have to parse that string back again on the server – adeneo Jan 19 '15 at 10:01
  • @ErickMaynard and still not posting a check of the `req.body` content as you were asked to many comments ago. Good advice only works when you listen. – Neil Lunn Jan 19 '15 at 10:02
  • @NeilLunn ok I did a console.log of req.body and it did indeed return it as a string: 'points[0][x]': '0.40'. And I do greatly appreciate your help Neil, sorry for my mistakes. – Erick Maynard Jan 19 '15 at 10:08
  • @ErickMaynard Your body parser middleware is not set up properly. Also check submission of headers on your POST request are "application/json" which is what should trigger the correct de-serialize. The objective it to get a JavaScript Object in `req.body` to make everything else work as expected. – Neil Lunn Jan 19 '15 at 10:16
  • jQuery will always send `application/x-www-form-urlencoded` data, unless you tell it otherwise. If you're going to stringify the object, you have to do it like this -> **http://jsfiddle.net/e6or87L4/** – adeneo Jan 19 '15 at 10:22
  • @adeneo Thanks for the jsfiddle. That did it, setting contentType to contentType: 'application/json; charset=utf-8'. I was looking around to see examples using Google and they all just labeled it "json". As soon as I used that in my AJAX request it added the data to MongoDB correctly. For the record NeilLunn, the headers were showing accept: 'application/json', but content-type was set to 'application/x-www-form-urlencoded', which is ultimately what confused me. My lack of ability in understanding my HTML headers did me in here. – Erick Maynard Jan 19 '15 at 10:29

1 Answers1

0

Thanks to @adeneo and @NeilLunn we solved the problem. The AJAX request was specifying the contentType as "json", when what it really needed to be is "application/json; charset=utf-8". Now the subarray key is being included correctly in MongoDB:

$.ajax({
        type: "POST",
        data: JSON.stringify(newDesign),
        url: "/data/add-design",
        contentType: 'application/json; charset=utf-8',
    }).done(function(response) {
        if(response.msg === '') {

        } else {
            alert("ERROR: " + response.msg);
        }
    });
Erick Maynard
  • 731
  • 6
  • 18