60

I want to convert an HTML input file to a JSON string like this:

var jsonString = JSON.stringify(file);
console.log( file );
console.log( jsonString );

Now, in my Firebug it logs as:

File { size=360195, type="image/jpeg", name="xyz.jpg", mehr...} 
Object {}

Why is the jsonString empty?

Background info: I want to send the file-reference with JSONP to another PHP server.

Additional Information: I want to convert only the file-pointer (reference) to a string, to send it via GET.

Ivar
  • 6,138
  • 12
  • 49
  • 61
peacemaker
  • 601
  • 1
  • 5
  • 5

7 Answers7

31

It is not possible to directly convert a File object into JSON using JSON.stringify in Chrome, Firefox and Safari.

You can make a work around to convert File object to string using JSON.stringify

Ex:

// get File Object  
var fileObject = getFile();

// reCreate new Object and set File Data into it
var newObject  = {
   'lastModified'     : fileObject.lastModified,
   'lastModifiedDate' : fileObject.lastModifiedDate,
   'name'             : fileObject.name,
   'size'             : fileObject.size,
   'type'             : fileObject.type
};  
 
// then use JSON.stringify on new object
JSON.stringify(newObject);

You can also add the toJSON() behavior to your File object

EX:

// get File Object  
var fileObject = getFile();

// implement toJSON() behavior  
fileObject.toJSON = function() { return {
   'lastModified'     : myFile.lastModified,
   'lastModifiedDate' : myFile.lastModifiedDate,
   'name'             : myFile.name,
   'size'             : myFile.size,
   'type'             : myFile.type 
};}  
 
// then use JSON.stringify on File object
JSON.stringify(fileObject);

Note: send a File Object to server using the POST HTTP method.

Ivar
  • 6,138
  • 12
  • 49
  • 61
ahmed hamdy
  • 5,096
  • 1
  • 47
  • 58
  • Actually, in Chrome you cannot stringify a `File` object either. – ffxsam Sep 27 '15 at 20:43
  • yes, Now I had test `JSON.stringify` with `File` Object in chrome and does not work. But I had test it when I answer this question was work – ahmed hamdy Sep 28 '15 at 13:18
  • Uh... what? The File API was not meant to be convertible to a String. See: http://stackoverflow.com/questions/19119040/how-do-i-save-and-restore-a-file-object-in-local-storage – wle8300.com Sep 30 '15 at 15:09
  • @williamle8300 your miss the part of Question that say he want to send `File` Object as JSON request to `PHP` server So that he want to Stringify `File` Object. the Question link which you put it, ask for another case also the accept answer say: (you can't serialize `File` Object) -> (same problem of this Question). my answer is Just workaround to Stringify `File` Object – ahmed hamdy Oct 01 '15 at 10:04
  • Stringfying and Serializing are synonyms – wle8300.com Oct 01 '15 at 15:57
  • @williamle8300 yes i known, my answer to solve the case of this question. – ahmed hamdy Oct 01 '15 at 16:40
  • @InsanelyADHD as I had comment on previous comment about serializing topic before [Here => https://stackoverflow.com/questions/24139216/js-input-file-to-json-with-for-example-json-stringify/29281243#comment53599554_29281243], on comment I mention about my solution was not for serializing `File` Object But convert `File` Object to String Only like the question needs(The Same Problem I had face too) !!! Thanks for down vote. – ahmed hamdy Sep 29 '19 at 18:10
11

You have to read the file content using the FileReader API. The File object does not contain the file content (it is just a pointer toward the file, which allows you to read it later).

You can check out this HTML5Rocks article to find out more about the usage of this API.

var file = getAFile( );

var success = function ( content ) {
  console.log( JSON.stringify( content ) ); }

var fileReader = new FileReader( );
fileReader.onload = function ( evt ) { success( evt.target.result ) };
fileReader.readAsText( file );
Maël Nison
  • 7,055
  • 7
  • 46
  • 77
  • Thank you for your answer. I want to send the pointer to another server. So I have to convert the file-pointer to a string. Do you have an idea? – peacemaker Jun 10 '14 at 13:44
  • Did you read the article ? `evt.target.result` is a string containing the file content. Using the FileReader API is the only way to fetch it, for security reasons. – Maël Nison Jun 11 '14 at 14:08
  • I think this is not the solution in my project. There is a problem because I will send the string with GET. The size of the string is too long if the file is for example 500 MB. – peacemaker Jun 12 '14 at 07:44
  • Well, then don't send it using GET? I'm not sure to understand what you want. If you just need to post a file, do it with [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) rather than JSON, since the former can streamline a file upload without requiring to buffer its content in the RAM. – Maël Nison Jun 13 '14 at 09:12
  • 1
    You cannot send files via GET. POST is the way here, I don't understand why you would prefer using GET. A web server will never be willing to parse a 500Mo URL. – Maël Nison Jun 13 '14 at 15:45
4

In case anyone is still looking for a solution to this please see my answer on a different post and working example on JSFiddle.

JS:

function getFiles(){
    var files = document.getElementById("myFiles").files;
    var myArray = [];
    var file = {};

    console.log(files); // see the FileList

    // manually create a new file obj for each File in the FileList
    for(var i = 0; i < files.length; i++){

      file = {
          'lastMod'    : files[i].lastModified,
          'lastModDate': files[i].lastModifiedDate,
          'name'       : files[i].name,
          'size'       : files[i].size,
          'type'       : files[i].type,
      } 

      //add the file obj to your array
      myArray.push(file)
    }

    //stringify array
    console.log(JSON.stringify(myArray));
}

HTML:

<input id="myFiles" type="file" multiple onchange="getFiles()" />
Community
  • 1
  • 1
Tammy Tee
  • 105
  • 1
  • 10
4

You just need a custom replacer:

function stringify(obj) {
    const replacer = [];
    for (const key in obj) {
        replacer.push(key);
    }
    return JSON.stringify(obj, replacer);
}

const json = stringify(file);
console.log(file);
console.log(json);

Now you should see:

File {name: "xyz.jpg", type: "image/jpeg", size...}
'{"name":"xyz.jpg","type":"image/jpeg","size"...}'
kevlened
  • 10,846
  • 4
  • 23
  • 17
1

Instead of looping through, or rather extracting each key one after the other, i came up with this function and i've used it image input.

const fileObject = e.target.files[0];

important notice

//dont use shorthand for of loop
for (const [key, value] in Object.entries(x)) 
it can't loop through a file object in JS 

Use this code instead

const imageObject = {};

for (const key in fileObject) {
    const value = fileObject[key];
    const notFunction = typeof value !== "function";
    notFunction && (imageObject[key] = value);
}

console.log(imageObject) // => should give you a normal JS object now
Chukwuemeka Maduekwe
  • 6,687
  • 5
  • 44
  • 67
-1

When you pass a json string Javascript internally trnsform it to Json object and hence no need to parse it.

follow steps in case of of json file ->

$('#inp_import_template')[0].files[0]

Now your json file is transformed to json object (Javascript).

New Bee
  • 390
  • 3
  • 10
-3
var obj = {
  name: 'dashu3f'
};

var stringObj = JSON.stringify(obj);
console.log(typeof stringObj);
console.log(stringObj);

open terminal this Folder file and run node json.js

yousef
  • 1
  • 1