4

The goal is to successfully POST a new job to the marathon REST API. I'm using jQuery v1.12.4

The following code is getting values from a form and printing valid json to the console.log. I've verified it using JSONLint. But it doesn't seem to be getting to the server. here's the JSON that's being printed to the log, and that I see in firebug:

{"id":"basic-0","cpus":"0.1","mem":"32","instances":"1","cmd":"while [ true ] ; do echo 'Hello Marathon' ; sleep 5 ; done"}

I'm getting 400 Bad Request, and then I see this crazy response (in firebug):

{"message":"Invalid JSON","details":[{"path":"/instances","errors":["error.expected.jsnumber"]},{"path"
:"/cpus","errors":["error.expected.jsnumber"]},{"path":"/mem","errors":["error.expected.jsnumber"]}]
}

I have no idea what that response means. Is it coming from jQuery or the server? Does anyone know of a working example of calling the marathon REST API from javascript?

Here's the code. Yes, I know it's really bad practice to pass the username and password in the request, but I haven't figured out how to use the basic authentication yet, not have I yet figured out how to enable SSL on the marathon webserver. Baby steps...

var $form = $('#appsubmit1');

$form.submit(function() {
    var form2json = JSON.stringify($('form').serializeObject());
    console.log(form2json);
    $.ajax({
      type: 'POST',
      url: 'https://user:pass@mesos-head.achillesv.net/marathon/v2/apps',
      data: form2json,
      dataType: 'json',
      contentType: "application/json; charset=utf-8",
      timeout: 10000 
    }).done(function(resp, status, xhr) { 
      console.log("ajax function done: ", status);
    }).fail(function(xhr, status, errmsg) { 
      console.log("error: ", status); 
      console.log("error: ", errmsg); 
    });      
    return false;
  });

Here's the code for the serializeObject function, which I did not write, but found found online. It works great, except that it double quotes all the values. I need the numeric values to be un-quoted. Unfortunately I don't see where the code puts the double quotes in, therefore I don't how to take them out. I'm still working on it.

$.fn.serializeObject = function() {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
      if (o[this.name] !== undefined) {
        if (!o[this.name].push) {
            o[this.name] = [o[this.name]];
        }
        o[this.name].push(this.value || '');
      } else {
        o[this.name] = this.value || '';
      }
    });
    return o;
  };

I'm thinking of checking each this.value against a regexp that removes the quotes if the value is completely numeric, i.e., 0.1, 3, 200.5, etc. I'll post that when I figure it out because I figure somebody else must have this same problem.

Robert Stober
  • 53
  • 1
  • 7

2 Answers2

2

The error clearly states that the service requires a number instead of a string for cpus, mem and instances fields. Try to post with this json:

{
    "id": "basic-0",
    "cpus": 0.1,
    "mem": 32,
    "instances": 1,
    "cmd": "while [ true ] ; do echo 'Hello Marathon' ; sleep 5 ; done"
}
Sarantis Tofas
  • 5,097
  • 1
  • 23
  • 36
2

Why are you going to all the effort of var form2json = JSON.stringify($('form').serializeObject()); ... data: form2json when you can just do data: $("form").serialize()? This is likely to resolve your expected integer issue as it's not stringifying all your form data in the pre-processing.

Jonathan
  • 10,936
  • 8
  • 64
  • 79
  • 2
    I discovered the problem myself and was coming back to answer my own question. But **Thank you** to both Akis and Jonathan. Jonathan, I'll try the serializeObject, but I read that it (or serializeArray) didn't handle all the various form possibilities such as checkboxes, etc. I hope you're right. – Robert Stober Jul 31 '16 at 23:36
  • Akis's answer is essentially right but is not giving you a particular solution. jQuery's `serialize()` is most often used to get your form data for AJAX. You would only want to use the alternatives for specific reasons that you know of at the time. Thanks for your up-vote anyway – Jonathan Aug 01 '16 at 00:00
  • See [this fiddle](https://jsfiddle.net/ge2j4hk2/). There is no `serializeObject()` in jQuery so I assume you are using some plugin for that – Jonathan Aug 01 '16 at 00:06
  • I'm not sure where you heard that it doesn't handle all the various possibilities as in my experience [it does](https://api.jquery.com/serialize/). The only gotchas are the edge-cases where you might expect a checkbox to send their unchecked value. But that is because they only submit a value when checked. – Jonathan Aug 01 '16 at 00:09
  • It doesn't handle the numeric values in the 'mem', 'cpus' and 'instances' field in this case - it just puts them in double quotes. But that's the problem. I need the JSON to leave the numeric values un-quoted. When I did per Akis' answer, it worked. But even the serializeObject function (I found somewhere on SO) doesn't solve this problem for me. I've added the serializeObject function code to my original post, because it won't let me add it here. To be clear, this code does not solve my problem because it quotes all the values, whereas I need the numeric fields un-quoted. – Robert Stober Aug 01 '16 at 05:05
  • I'm asking you to use serialize not this serializeObject function you're talking about. – Jonathan Aug 01 '16 at 07:33