3

I need some clarification on JSON objects. Inside my node backend, I receive a JSON object and after I'm done going through which key/value pairs I need, I send it off to the frontend. This is where I'm getting confused- I still need to turn that response object into json via response.json(). Why? If the backend is passing JSON, then why would I need to turn the response obj into JSON?

// test.js (node)

const testObj = {
    "test1": {
        "1": "Hello there"
   }
}


app.get('some-route', async(req,res) =>{
       res.send(testObj)
}


// front.js (React)

async someFunc(){
      const response = await fetch('/some-route');
      const data = await response.json(); //why?
}
hello_there
  • 209
  • 1
  • 5
  • 10
  • 2
    It doesn't matter if the backend is also JavaScript, the data is transmitted as bytes through the network, and are received as string, you will always need to parse it into something your language can understand (as JSON). – Washington Guedes Jun 24 '19 at 21:16

4 Answers4

5

Because on your front-end, the fetch API receives a buffer -- an array of bytes, which could contain any payload. It could be an image, plain text, a file, or a JSON payload.

Knowing what your back-end is going to send down, you need to receive the buffer of the data and then perform the .json() API on it, essentially asking that the buffer be interpreted as a serialized string representing a JSON object, and then having the Javascript engine evaluate (deserialize) that string into an object.

Fetch is a multi-purpose API that doesn't have any prior knowledge about the payload that the server is going to send. You are instructing it to treat the payload as JSON by using the .json() function.

Besides .json(), there are other helper methods to read and parse a variety of other possible response types; for example, .text() for plain text, .formData() for form encoded data (similar to querystring values), .blob(), and .arrayBuffer() for byte-level access to the returned data. You will use the appropriate method based on the response type that you're expecting from the API.

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

Arash Motamedi
  • 9,284
  • 5
  • 34
  • 43
3

The response object isn't whatever you sent from the backend, it will be a Response object. That's how the Fetch API works. That Response object will have lots of metadata on it, and some methods, including .json which Takes a Response stream and reads it to completion. It returns a promise that resolves with the result of parsing the body text as JSON.

If you don't want to have to go through these two steps, just write this function.

const fetchJson = async url => {
    const response = await fetch(url)
    return response.json()
}

and use it like this:

async someFunc(){
      const data = await fetchJson('/some-route')
}
pteranobyte
  • 564
  • 3
  • 9
2

A response object is more than just its JSON part. It contains all HTTP protocol elements, like headers, the state of the response and so on.

When you use res.json() you are telling your code to separate only the JSON part from all these other things.

To understand a bit more about an HTTP response, I suggest you to read this.

Ed de Almeida
  • 3,675
  • 4
  • 25
  • 57
0

Good question!

When you send data to the front-end from the back-end, you're not just sending the data payload you created in your testObj. What's actually being returned is a response object, which will look something like:

{
  type: "cors",
  url: "http://some-url.com/some-api",
  redirected: false,
  status: 200,
  ok: true,
  body: ReadableStream,
  ...
  headers: Headers,
  json: json(),
  ...
}

where the value of response.json is the body deserializer method in the response object. You can see for yourself; try to console.log(data) from your example after removing the .json() bit, and you'll get a look at the response object in its entirety.

As you can see, the response's body - or the payload you sent from the server - is received by the client as a ReadableStream object, which then needs to be deserialized once the entire object has reached the client. The response.json() method simply deserializes the response.body ReadableStream object from serialized byte data into JSON, which you can then parse in your application.

cloake
  • 56
  • 2
  • 5