Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improper output format for array field form when using AJAX to POST JSON data #605

Open
seanvree opened this issue Feb 15, 2018 · 34 comments

Comments

@seanvree
Copy link

seanvree commented Feb 15, 2018

When using an ajax post to write to a json file, the below form appends unneeded text to the output json string.

The below form will output this to the json file:

{"data":[{"type":"Curl","check url":"afd","link url":"afa"}]}

Why is it appending the " {"data":{ " to the start?

it should look like this:

{"type":"Curl","check url":"afd","link url":"afa"}

I've used this on other forms, and for some reason, particular form appends the unnecessary text.

here is my form:

<div id="field7"></div>

    <script type="text/javascript">
        $(document).ready(function() {

            $("#field7").alpaca({
                "schema": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "type": {
                                "enum": ["Curl", "Ping"]
                            },
                            "check url": {
                                "type": "string",
                                "format": "uri"
                            },
                            "link url": {
                                "type": "string",
                                "format": "uri"
                            }
                        }
                    }
                },
                "options": {
                    "toolbarSticky": true,
                    "items": {
                        "fields": {
                            "type": {
                                "label": "Type",
                                "optionLabels": ["Curl", "Ping"]
                            },
                            "check url": {
                                "label": "Check URL"
                            },
                            "link url": {
                                "label": "Link URL"
                            }
                        }
                    },
                    "form": {
                        "attributes": {
                            "action": "post_receiver.php",
                            "method": "post",
                        },

                        "buttons": {
                            "submit": {
                                type: 'button',
                                "label": "submit",
                                click: function(){

                                    var data = $('#field7').alpaca().getValue();

                                    $.post('post_receiver.php', {
                                        data
                                     })
                                    
                                    alert(JSON.stringify(this.getValue(), null, "  "))
                                
                                }
                            },

                            "view": {
                                "label": "View JSON",
                                "click": function() {
                                    alert(JSON.stringify(this.getValue(), null, "  "));
                                }
                            }
                        }
                    }
                }
            });

        });
    </script>

Thanks!

@ambischof
Copy link
Contributor

It is not a bug with alpaca but with your code

$.post('post_receiver.php', {
                                        data <--- wrapped in brackets
                                     })

you should have $.post('post_receiver.php', data)

@seanvree
Copy link
Author

seanvree commented Feb 15, 2018

@ambischof interesting, because I tried exactly what you suggested changing ONLY that bit of code, it writes to the .json file, but this is all I get:

{"undefined":""}

                            "submit": {
                                type: 'button',
                                "label": "submit",
                                click: function(){

                                    var data = $('#field7').alpaca().getValue();

                                     $.post('post_receiver.php', data)
                                    
                                    alert(JSON.stringify(this.getValue(), null, "  "))
                                
                                }
                            },

image

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof I hate to keep bother you Sir, but this is one of the last bugs I can't get past before integrating this into my project.

Do you have any other ideas?

I've tried the following with many different variations:

$.post('post_receiver.php', data)

which returns " {"undefined":""} "

and I've also tried removing the variable

$.post('post_receiver-services.php', $('#servicesettings').alpaca().getValue())

That also returns " {"undefined":""} "

It's weird because it works on some forms, and other not, and I can't find a pattern. They are all using the same backend php script:

<?php
    $fp = fopen('../data/services_settings-data.json', 'w');
        fwrite($fp, json_encode($_POST));
    fclose($fp);
?>

so I don't get why it's appending the extra " {data} " tag to the JSON output? Even when I try and load that exact same json data source that the form creates, it doesn't load it until I remove that data tag.

@ambischof
Copy link
Contributor

ambischof commented Feb 16, 2018

Don't just try to tweak the code when you have an issue, you need to figure out what your code is actually doing so you can fix it.

Do you know how to use the developer tools in your browser? Specifically the network monitoring where you can view the exact request your browser sends and how it is encoded. It will help you see exactly what your browser is sending to the server, so you can easily identify if the issue is on the front end or the server.

Here is a link of how to do so in Chrome: https://developers.google.com/web/tools/chrome-devtools/network-performance/reference

Also, on your server route, log exactly what it is receiving.

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof thanks for that tip, I am familiare with dev tools and monitoring what's being posted. This is my first project using these types of forms. So, I'm assuming this what I'm looking for:

decoded looks like this:
image

Encoded looks likes this:
image

@ambischof
Copy link
Contributor

Looks fine there, so your issue is something in your server.

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

huh? no that's not fine, that's the wrong format.
Here's a comparison with another form that's using the exact same php post script.

The one on the left is in the correct format, no [data] appended. You'll see that the form on the left IS in the correct format, but the form on the right is appending "data[0]" to each of the strings.

image

@ambischof
Copy link
Contributor

I don't have your code, nor do I have what you're trying to achieve, so if you want me to help you, you'll need to post that.

@seanvree
Copy link
Author

@ambischof dude, really?! it's in the first post man.

@ambischof
Copy link
Contributor

I assumed you tried to fix it, and you posted so many different fixes I don't know which one you're referring to any more.

Your previous post has two different form data values, and I don't know which code maps to which.

Are you trying to get the form to send JSON? because if you are, you can't just the $.post(url, data) signature, as that will encode it as application/x-www-form-urlencoded. You will need to use the object signature:

`$.post({url: 'post_receiver-services.php', data: JSON.stringify(data), contentType: 'application/json'})

I'm guessing the reason that 'data' is being added is because it can't encode an array in application/x-www-form-urlencoded as the base, it can only encode objects, so it adds the data key. Making sure it uses json will fix that.

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof I've only posted two different variations of the code man, which you suggested. Nothing has changed on server side or data. Only the form options.

YES. I"m trying to get the form to send JSON data, which it IS doing, it's just in the wrong format.

1.

$.post('post_receiver-services.php', data)

json data result: " {"undefined":""} "

2.

  $.post('post_receiver-services.php', {
      data
    }) 

json data result: " data[0][serviceTitle]:test "

And here is the 3rd option which you just suggested:

$.post({url: 'post_receiver-services.php', data: JSON.stringify(data), contentType: 'application/json'})

json data result: " [] "

@ambischof
Copy link
Contributor

When you say that is the json data result, is that the what the browser is sending, what the server is receiving, or what is being written to file?

@seanvree
Copy link
Author

@ambischof Both. The snippets above are copied and pasted from the actual json file, but the browser console is almost identical to those strings. Example:

$.post({url: 'post_receiver-services.php', data: JSON.stringify(data), contentType: 'application/json'})

image

@ambischof
Copy link
Contributor

ambischof commented Feb 16, 2018

If that's the case, check what's in your 'data' variable. I just tried that same snippet in my console except replacing data with {foo: 'bar'} and it did exactly what I expected.

EDIT: Please post the entire request page above the 'Form Data' section. Unless your chrome is very different from mine, it should not show 'Form Data' if the encoding is 'application/json', but rather 'Request Payload'.

@seanvree
Copy link
Author

@ambischof

 var data = $('#servicesettings').alpaca().getValue();

@ambischof
Copy link
Contributor

That doesn't really help me. I asked what the value of the data variable is and to post the entire network details of the request. If you can't do that, at least post a fiddle or something if you want me to help you debug this.

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof Appricate your help man. Sorry to get a little testy with ya. Been working on this for a couple days now. I'm sure you know how that is. Also, can't really do a jfiddle with PHP.

Here's the full network output:

You'll notice that the "parent" array that the actual data string is in is BLANK with just a " [ ] " which is why I'm assuming that's all I'm setting in the JSON output?

image

image

image

again, here's the complete form options:

    "submit": {
        type: "button",
        "label": "Submit",
        click: function(){
            var data = $('#servicesettings').alpaca().getValue();

            $.post({
                url: 'post_receiver-services.php', 
                data: JSON.stringify(data), 
                contentType: 'application/json',
                    success: function(data) {
                        alert(JSON.stringify(data));
                        alert("settings saved");
                    },
                error: function(errorThrown){
                    console.log(errorThrown); 
                } 
            });                                        
        }
    },

Here's the back-end PHP code, also, this DOES work on a couple of the other forms from this same site.

<?php
    $fp = fopen('../data/services_settings-data.json', 'w');
        fwrite($fp, json_encode($_POST));
    fclose($fp);
?>

@ambischof
Copy link
Contributor

ambischof commented Feb 16, 2018

If the jsfiddle is only the javascript side, that's fine, I just wanted to see what it was sending.

Okay It looks like the client side is sending the data correctly. That's good. Now we know that the issue is in the php side.

When I said log the server side data, I meant log it in the php function. I don't remember how to do logging in PHP, so you'll have to figure that out.

Before you write to the file, log the contents of $_POST, then log json_encode($_POST) so you can verify that it has the input you think it has.

  • If neither have a value, then there is a problem with your server decoding what the client sent
  • if both have a value, then the issue is with the write function.

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof

I'm somewhat disagreeing with you when you said "client side is sending data correctly" Because I don't think it is. Again, if you see my screenshot, it's putting the data from the form in a "child" array. The other three forms don't have that first array that I marked in red in the screenshot. Also, it MAY be something we need to add to the PHP script because of the way the the alpaca form is sending the data, because like I said, the other 4 forms work fine and are using the exact same php file to get the AJAX post.

So the browser output is like this:

[,…]  <- shouldn't be there
0 : {serviceTitle: "test1", image: "../img/monitorr.png", type: "Both", checkurl: "http://localhost:80",…}
     checkurl :"http://localhost:80"
     image : "../img/monitorr.png"
     linkur :  "http://localhost:80"
     serviceTitle  :   "test1"
     type  :  "Both"

Also, the alert is NOT showing any json data, all it shows is "/r/n"

I know how to write to a log file, I'll get that set up and send you the results.

@ambischof
Copy link
Contributor

ambischof commented Feb 16, 2018

Ahh, I didn't realize you didn't want it to be in an array. It is an array because you told it to be when you set the schema to be type: 'array'.

If that is not what you want, then why did you make it that way?

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof no, I DO want it to be in an array, it needs to be in an array, all the other forms are in an array as well. The problem here is that it IS sending the json data in array format, but it's adding a "top level/ parent" array that's blank, which is why the json output is simply" [ ] "

This is the schema for that form:

{	
	"type": "array",
	"items": {
		"type": "object",
		"properties": {
			"serviceTitle": {
				"type": "string",
				"title": "Service Title",
				"default": "Service Title"
			},
			"image": {
				"type": "string",
				"title": "Serivce Image",
				"format": "uri",
				"default": "../img/monitorr.png"
			},
			"type": {
				"type": "radio",
				"title": "Check Type",
				"enum": ["Both", "Curl Only", "Ping Only"],
				"default": "Both"
			},
			"checkurl": {
				"type": "string",
				"format": "uri",
				"default":"http://localhost:80"
			},
			"linkurl": {
				"type": "string",
				"format": "uri",
				"default":"http://localhost:80"
			}
		}
	}
}

@ambischof
Copy link
Contributor

Ahh, no, it's not sending a top level blank array, that's just how the console shows the parent array. Paste in [{a: '1'}] to the console and hit enter and you'll find it displays it in the same way.

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof humm. okay, I see...

Well, I don't get it then.

So I set up logging on the server site as well as on the form.

so in the form I simply added this after the click: function()

console.log(data);

and I changed the .post to send the entire form's data without json.

    $.post({
        url: 'post_receiver-services.php', 
        data: data, 
        success: function(data) {
            alert(data);
            alert("settings saved");
        },
        error: function(errorThrown){
            console.log(errorThrown); 
        } 
    });

and that logs this into the browser:

image

and on the server side I changed the php script to this:

<?php
    $fp = fopen('../data/log.txt', 'w');
        fwrite($fp, $_POST);
    fclose($fp);
?>

And it does write to the file, but it's blank. It's not receiving ANY data it appears?

@ambischof
Copy link
Contributor

You're still not logging it on the server side. I want you to actually use logging in your php code. That's the only way to know for sure

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof Yes, I had verbose logging turned on for the entire PHP runtime application for the webserver. Again, it logs that there is a POST, but NO data with the POST.

However, if you want to see it in the actual PHP script, this is what I'm using:

<?php

    ini_set('display_errors', 'On');
    error_reporting(E_ALL);
    var_dump($_POST);
    $fp = fopen('../data/services_settings-data.txt', 'w');
        fwrite($fp, var_dump($_POST));
    fclose($fp);

    echo '<pre>'; var_dump($_POST); echo '</pre>'

?>

var_dump($_POST); will write the entire contents of the post to services_settings-data.txt as well as log it to the browser.

The browser alert comes back blank, the file is changed on the server, but it only has " [] "

@ambischof
Copy link
Contributor

I can't really help you with that then, since I don't know all that much about php servers. My advice is to check if your server will automatically parse the request based on the ContentType header.

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

It's not a "PHP" server man. It's MS IIS. It's a pretty standard rig.

I understand you're trying to prove that it's my server. I think I've proven that it's not. I run 20+ applications from this same server half of which parse json data just fine using PHP and various other frameworks.

If you want FURTHER proof, I put together this VERY simple form that uses the SAME php script. It posts JUST fine as you can see.

https://seanvree.com/dev/monitorr-settings-alpaca/ajax.php

There is obviously a bug or something we are BOTH missing with the alpaca script that is not posting proper json data.

image

@ambischof
Copy link
Contributor

ambischof commented Feb 16, 2018

PHP or MS IIS, I know even less of that.

Bottom line is that the developer network tab doesn't lie. If there is a problem in the request being sent, you will find it there. It could be that there was an issue there I missed since it is just an image and I can't interact with it.

The example you sent encodes the data as application/x-www-form-urlencoded so I can't verify that the server does in fact correctly parse JSON. To be brutally honest, I'm half doubting that any of those applications actually do send data encoded as 'application/json', seeing as you couldn't figure out how get that form to work until just recently.

If you do have one that already sends data encoded as 'application/json', do send it along.

@seanvree
Copy link
Author

seanvree commented Feb 16, 2018

@ambischof If you don't' know the basics about server side scripting, or webservers in general, then maybe you could point me to someone from Alpaca who does? Like I said in the other thread - displaying data from a pretty form is nice, but all that matters is what you do with that data.

If you look at the screenshot above you can plainly see that it did in fact parse the data correctly.

Figure out how to get what form working until recently? Dude, this is NOT rocket science man. Seriously, it's not. PHP is NOT complicated, ajax is NOT complicated. There's no reason that a simple web form should be this problematic. Maybe you should tell the developers to merge some of their pull requests to fix some bugs. There's some pretty good ones in there...umm...like this one maybe?

#221

I appreciate you taking the time to discuss this, but it's obvious that you're trying to give me the whole line "it works on My machine" silver bullet. We haven't' even "de-bugged" anything, all you've had me do was post re-post a bunch of data to try and prove it's the webserver.

So, with all do respect, do you know anyone who might be knowledgeable of how to make these forms work on an actual webserver?

Thanks,

@ambischof
Copy link
Contributor

ambischof commented Feb 16, 2018

I do know how create servers, but my experience is mostly in Node. If you think you know more than I do on the subject, whatever. I'm not going to argue credentials on the internet.

And no, I can't point you to anyone here who would know more about your specific server framework. But this isn't a place to talk about server frameworks, and it's certainly not stack overflow. It is the alpaca issues channel made to fix issues with the Alpaca and I'm just some random person trying to help you debug your own code when alpaca is working just fine.

Good luck.

@seanvree
Copy link
Author

dude, it's not "my" specific framework. It's PHP! PHP has the native ability to decode json data. I'ts not my server, it's not PHP, it is in fact alpaca.

@seanvree seanvree changed the title "data" tag is appended to JSON output Improper output format for array field form when using AJAX to POST JSON data Feb 18, 2018
@Nj0376
Copy link

Nj0376 commented Feb 19, 2018

Not sure if you sorted this out but you should change the following lines:

                            $.post('post_receiver.php', {
                                data
                            })

to

                            $.post('post_receiver.php', 
                                "=" + JSON.stringify(data, null, "  ")
                            
                            )

placing the "=" prior to because you are posting an object. Give that a try. I haven't got php running on my test server but I changed your code and ran it on my server posting to a web api backend and it fixes the error as you can see below. I was getting your error but not after the fix.

form

Web traffic to and from server
web traffic

Data received at server
server

@seanvree
Copy link
Author

seanvree commented Feb 19, 2018

@Nj0376

Thanks so much for your reply. Yeah, I know this has something to do with it.

Although, I changed my code, but the from data still shows empty for me. All I get back in the json file is " [] "

image

image

image

Now if I remove the " "=" + " I get better results in the browser, but still same results in the json file.

image

Were you using PHP to parse the data by chance? I'd really like to know if this works with PHP. I know there's a bug in the alpaca code as explained in this pull request (#228) as I can get this working on my other forms that don't use an array.

<?php

    $json = json_encode( $_POST, true);
    $fp = fopen('../data/services_settings-data.json', 'w');
        fwrite( $fp, $json);
    fclose($fp);
?>

@Nj0376
Copy link

Nj0376 commented Feb 21, 2018

No I was using Microsoft Web Api and C# to process the server request. Can you install Fiddler and see what's getting sent to your server and more importantly what's coming back from the server. It should give you a detailed response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants