71

I'm getting a "not well-formed" error in the error console of Firefox 3.0.7 when the JavaScript on my page loads a text file containing an object in JavaScript Object Notation format. If the file contains nothing but the JSON object, it produces the error. If I wrap the object in <document></document> tags it does not produce the error. The request succeeds either way, so I could just ignore it, but I don't want my error log filling up with these messages.

Here is some example code to illustrate the problem. First, the "not well-formed" file called "data.json":

{ a: 3 }

Now some code to load the file:

var req = new XMLHttpRequest();
req.open("GET", "data.json");
req.send(null);

Which produces the following error in the Firefox error console:

not well-formed
file://path/to/data.json Line: 1
{ a: 3 }
- ^

If data.json is modified to this:

<document>{ a: 3 }</document>

There is no error. I assumed that it is complaining because the plain JSON file is not a well formed XML document, so I tried overriding the MIME type before the "send" call to force it to load as plain text, but that didn't work.

var req = new XMLHttpRequest();
req.open("GET", "data.json");
req.overrideMimeType("text/plain");
req.send(null);
// Still produces an error!

I am going to continue with wrapping my JSON data in an XML document to get around whatever validation the XMLHttpRequest is performing, but I'd like to know if there is any way I can force it to just load plain text uncritically and not try to validate it. Alternatively, is there another method of loading data besides XMLHttpRequest that can be used with plain text?

A. Levy
  • 29,056
  • 6
  • 39
  • 56

9 Answers9

77

Have you tried using the MIME type for JSON?

application/json

You could also configure your server to send this MIME type automatically for .json files.

jthompson
  • 7,178
  • 2
  • 34
  • 33
21

Firstly, true JSON is much stricter than JavaScript, and to be valid JSON, you have to have your keys quoted.

 { "a": 3 } 

Also, as you are using a bare XMLHttpRequest, which generally expects to receive an XML result unless MIME headers specify strictly otherwise.

You may however wish to make your own life easier by simply using a JavaScript framework such as jQuery which will abstract away all this problem for you and deal with all the nasty edge cases.

$.getJSON("data.json",{}, function( data ){ 
  /*  # do stuff here  */ 
});

Additionally, if you use both strict JSON and use a library to abstract it for you, when browsers start having native JSON parsers the library will be able to transparently make use of these and get a significant speed improvement.

( This is slated to happen sooner than later, and when it happens, your users will get a silent upgrade with no effort required! ).

Kent Fredric
  • 56,416
  • 14
  • 107
  • 150
  • Thanks for the pointers on JSON. I will change my data to use quoted string attribute names. Unfortunately, jQuery, or some other framework, is not an option for me. – A. Levy Mar 24 '09 at 15:43
  • I'd be most interested why, generally that's the sign of code-stink to vehemently avoid code reuse and to avoid using solved problems. – Kent Fredric Mar 24 '09 at 15:47
  • 2
    @Kent, I'd be happy to use jQuery. However, the approval process for using jQuery is prohibitively difficult. The amount of time it would take to argue with the customer and demonstrate that we need to use jQuery is not worth the benefit. Sad, but true. – A. Levy May 13 '09 at 15:06
  • @A. Levy: you'll learn, and next time you'll be less likely to hand-code-everything :) – Kent Fredric May 14 '09 at 16:10
  • 15
    using `$.getJSON()` still generates that error message for me. – shoosh Jan 26 '11 at 08:41
  • @Shoosh , are you encoding your data properly? As stated, you *MUST* encode keys and values appropriately, see http://jsfiddle.net/kentnl/uGDQP/1/ for examples. – Kent Fredric Feb 06 '11 at 13:11
7

This also occurs when Content-Type is completely empty (thereby circumventing the natural type-detection).

Dustin Oprea
  • 9,673
  • 13
  • 65
  • 105
4

I found the same error message but from a very different cause. After a little time fruitlessly changing the JSON content, realized that I had accidentally restarted the page running off the local file system (file://Users/me/Sites/mypage.html) rather than the server (http://localhost/~me/Sites/mypage.html).

prototype
  • 7,249
  • 15
  • 60
  • 94
4

It should be {"a": 3} actually.

Julian Aubourg
  • 11,346
  • 1
  • 29
  • 29
0

I was also getting the same warning message with XMLHttpRequest() (in FireFox), when requesting resources marked as Content-Type: application/json by the server.

What did the trick for me was to explicitly set the XMLHttpRequest.responseType property to json on the request object. E.g,

var request = new XMLHttpRequest();
request.onreadystatechange = function() { ... }
...
request.open('GET','https://random-domain.com/random-path',true);
request.responseType = 'json';
...
request.send();
focorner
  • 1,927
  • 1
  • 20
  • 24
0
Browser --- request expects a given content-type ---> Server
        <-- response contains content-type ----------

Firefox looks at the HTTP Content-Type header. If the server HTTP response header does not match the expectations of your browser code it will complain with this message.

IMHO this error message could have been a lot better, like "Expecting response Content-Type header ... but found ...".

Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
0

Unless there is a specific reason for opening your HTML directly from the disk (file://), you should do yourself a favor and open it served by a local HTTP server (http://), like the prototype user has written. This will fix this issue because the MIME type will be set correctly, as jthompson suggested.

Thanks to that you will also not run into another issue, like "Reason: CORS request not HTTP", and possibly others as browsers are getting more and more suspicious when they are asked to open files on the local disk - and for good reasons (security!).


If you have Python on your system then the (arguably) easiest way to run a local HTTP server is:

Mac/Linux: python3 -m http.server

Windows: python -m http.server or py -3 -m http.server

The files from the current working directory will then be served under http://localhost:8000/

halfer
  • 19,824
  • 17
  • 99
  • 186
Greg Dubicki
  • 5,983
  • 3
  • 55
  • 68
-6

Kent, I disagree.

The following IS "valid" JSON:

{ a: 3 }

JavaScript object property names do NOT have to be strings.

The problem is one of MIME type, not JSON/JavaScript syntax.

I just solved this very issue by adding json as "text/javascript" to my webserver mime types file:

text/javascript                 js, json

The "not well-formed" error disappeared. The browser (FireFox) assumed, incorrectly, that the .json file was XML.

Brian Mains
  • 50,520
  • 35
  • 148
  • 257
Rhino
  • 5
  • 1
  • 8
    Wrong. It is valid *javascript*, and if you interpret it as javascript, then it will be fine. Howver, JSON is *stricter* than javascript, and the JSON format is parsed seperatly by a conformant client thant wants "JSON" not "Javascript". Any Specificiation compatible JSON parser treats unquoted keys as an error. – Kent Fredric Feb 04 '11 at 03:29
  • 1
    To reiterate, JSON is a *sublanguage* of javascript, and while *ALL* JSON is valid javascript, **NOT** all Javascript is valid JSON. – Kent Fredric Feb 04 '11 at 03:30
  • 1
    If you disagree with me, take your complaint to Mozilla, as you're arguing their JSON parser is wrong =). http://jsfiddle.net/kentnl/uGDQP/ – Kent Fredric Feb 06 '11 at 13:04
  • 1
    I have to say that requiring keys to have "" is a mayor flaw in JSON. It's extra slump, JS proves it isn't required. It's probably there to accomodate parser writers, and there's far less parser writers than there's users. I also take grief of not being able to pass functions, but that at least makes sense. – Lodewijk Nov 01 '13 at 13:59
  • Also the name "JavaScript Object Notation" is misguiding. It isn't the same notation as used in Javascript. – Lodewijk Nov 01 '13 at 14:00