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

response.json() gives an error "unexpected end of input" if the data sent back from request is null. #268

Closed
andreacab opened this issue Jan 29, 2016 · 11 comments

Comments

@andreacab
Copy link

This is what I have:

this.authTokenStore.get()
    .then(authToken => {
        return fetch(this.serverUrl + '/REST/search?searchTerms=' + text, {
            method: 'get',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'X-Client-Auth-Token': authToken
            }
        })
    })
    .then(this._checkStatus)
    .then(this._parseJSON)
    .then(serverGetSearchSuccess)
    .catch(serverGetSearchError);

What I don't understand and would need some help, it is with the fact that the response has a status 200, then goes to parseJSON but then goes back to checkStatus and throws that error "unexpected end of input" (debugging step by step using the chrome debugger).

My question I guess is how could I check for the body of the request in the this._parseJSON function and detect there if it is null and do a return Promise.resolve(response) instead of response.json()

I am not sure if that should be posted on some site like SO, if yes I'm sorry for the inconvenience.

Thx for your help

@mislav
Copy link
Contributor

mislav commented Jan 29, 2016

This is a usage question and as such should be asked on sites like SO instead of here.

Ideally, the server shouldn't return an invalid (empty) response body to an application/json request, especially because it responded with HTTP 200. But since it misbehaves, you can catch those occurrences inside .catch(serverGetSearchError). I'm not sure why would you want to resolve a promise in that case, like nothing bad happened.

But if you want to avoid a parse error at all costs, why can't you change your _parseJSON function?

_parseJSON: function(response) {
  return response.text().then(function(text) {
    return text ? JSON.parse(text) : {}
  })
}

In any case, the power is in your hands. We can't decide your app's logic for you.

@mislav mislav closed this as completed Jan 29, 2016
@andreacab
Copy link
Author

Hey Mislav, thanks for your response and thanks for the work on the fetch polyfill, it's been a real help.
Sorry again for posting that here.

@abologna-r7
Copy link

This is a super late response, but anyways my 2 cents on this issue is that if you're expecting a null response body, with a status code of > 200, you can always send a 204 (no content) response back from the server and handle it without the use of response.json() call.

@tonyc726
Copy link

@mislav it's nice , and i think maybe add one step to verify that text will be better.

// https://github.com/douglascrockford/JSON-js/blob/master/json2.js#478
const rxOne = /^[\],:{}\s]*$/;
const rxTwo = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
const rxThree = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
const rxFour = /(?:^|:|,)(?:\s*\[)+/g;
const isJSON = (input) => (
  input.length && rxOne.test(
    input.replace(rxTwo, '@')
      .replace(rxThree, ']')
      .replace(rxFour, '')
  )
);

_parseJSON: function(response) {
  return response.text().then(function(text) {
    return isJSON(text) ? JSON.parse(text) : {}
  })
}

@Zoly90
Copy link

Zoly90 commented May 18, 2017

@mislav the solution almost works, it is enough to do it like this:

_parseJSON(response) {
return response.text() ? JSON.parse(response) : null
}

Your version was crashing on my side.

@HelloAndyZhang
Copy link

HelloAndyZhang commented Nov 13, 2017

I also encountered a similar problem,
read the above method,
still can not be solved,
this is my code
http://ww1.sinaimg.cn/large/005SjUnYly1flgt8vhksfj30sy0cpabd.jpg
@andreacab

@ysfdev
Copy link

ysfdev commented Feb 27, 2018

@Zoly90 and @AndyZhang7

The solution from @mislav works as expected. It's important to note that if you are using the _parseJSON function/JSON.parse will trow an exemption whenever it tries to parse an invalid JSON text. For instance, if you are using the _parseJSON within a Promise chain with a .catch handler, that handler will catch the Parsing exemption.

@ruoru
Copy link

ruoru commented May 24, 2018

this error maybe server not allowed, if CORS set moda:cors in request, and check error message if let u set no-cors, then u need teel backend let u address request, worth checking if anyone else.

@antoxi4
Copy link

antoxi4 commented Jun 22, 2018

I use this code

tryGetJson = async (resp) => {
    return new Promise((resolve) => {
      if (resp) {
        resp.json().then(json => resolve(json)).catch(() => resolve(null))
      } else {
        resolve(null)
      }
    })
  }

@ruoru
Copy link

ruoru commented Jun 25, 2018

@antoxi4 sometime is not ur code problem. and whatever use ES5 or ES6.

@kvr2277
Copy link

kvr2277 commented Jul 6, 2018

@antoxi4 By using catch on resp.json() - you might be silently suppressing genuine parsing errors too. So when there is no data or when data has parsing errors - your code always assumes only no data case

Repository owner locked as resolved and limited conversation to collaborators Jul 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants