0

I'm trying to get JSON value from PHP but if one of the property values contains a forward slash "/" it fails (I'm using GET to send data for this particular scenario).

Here's how I'm sending the data (This works just fine when I don't send "/").

UI side

const dataObj = {
      description: 'my / description',
      buyer: 'Mike Brown'
    };

const dataString = JSON.stringify(dataObj);

fetch(`http://localhost:8000/clients/${dataString}`)
    .then((response) => response.text())
      .then((responseData) => {
         ......
      });

PHP side:

Route::get('/clients/{data}', function($data) {
   // This line below fails ONLY if value of description property contains "/"
   // otherwise it works just fine
   $dataToBeSaved = json_decode($data, true); 

});

Yes, I did some research on json_decode, but nothing very clear. Can anyone point me on the right direction? Thanks a lot in advance!

3
  • Try like this way, works for me: $personJSON = '{"name":"Johny / Carson","title":"CTO"}'; $person = json_decode($personJSON); echo "Name: ". $person->name . '<br/>'; echo "Title: ". $person->title; Commented Mar 20, 2021 at 5:24
  • do you need send it as get request? if you can send it as post request this will be easier Commented Mar 20, 2021 at 7:02
  • Did you resolve this issue? Commented Mar 24, 2021 at 21:11

1 Answer 1

1

It's not really a good idea to pass JSON data in a URL, and you can't do it directly because it will contain characters that have meaning in URLs (e.g. /, ?, =, etc.). But if you must you have a couple options:

  1. You can URL encode the string and pass it as a parameter. This wouldn't work with the route you have, but it has the benefit of not needing to do anything else. You can just get the value from the parameter.

const dataObj = {
  description: 'my / description',
  buyer: 'Mike Brown'
};

const dataString = encodeURIComponent(JSON.stringify(dataObj));

console.log(`https://example.com/clients?data=${dataString}`);

  1. Or you can base64 encode it. This doesn't by default create URL safe strings, so you'll have to replace a few characters to make it URL safe. That also means you'll have to do the reverse on the server. This solution will work with your route.

const base64UrlEncode = function(str) {
  return btoa(str)
    // this character have meaning in URLs so we need to replace them
    // with something else. we'll have to reverse this on the server.
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
};

const dataObj = {
  description: 'my / description',
  buyer: 'Mike Brown'
};

const dataString = base64UrlEncode(JSON.stringify(dataObj));

console.log(`https://example.com/clients/${dataString}`);

And to decode on the server:

function base64UrlDecode($encodedStr) {
  // undo the character replacements we did when encoding the string
  $unreplace1 = str_replace('-', '+', $encodedStr);
  $unreplace2 = str_replace('_', '/', $unreplace1);

  return base64_decode($unreplace2);
}

Route::get('/clients/{data}', function($data) {
   $dataToBeSaved = json_decode(base64UrlDecode($data), true); 
});

One thing to note with this solution is that web servers usually have a limit for the length of URLs (e.g. Apache's default is 8,177 characters). Also, there is usually a limit to the size of the "filename" in the URL (the last component in the path). Apache's default is 255 bytes/characters. So if your base64 encoded JSON is longer than 255 characters, it won't work. A better solution is to pass the data as part of the request body (i.e. as a POST request). That way you won't have a limit and you won't need to encode it beyond converting it to JSON.

Sign up to request clarification or add additional context in comments.

5 Comments

I tried your first solution and it didn't work, also what is btoa? doesn't seem to work either
@progx When you say "it didn't work", how so? Did you get the $data value on the serverside? What did it look like? btoa base64 encodes a string.
@progx I realized you can't URI encode a string to make it part of a URL path. You would have to pass it as a URL parameter. I updated my answer accordingly. Though the base64 solution should work with the route you have. I just tested on a server of mine and it worked.
@progx I also added a note about URL limits at the end of the answer. You'll likely run into that when passing JSON data as part of the URL path.
Btw, sorry, I accidentally tagged progx for some reason.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.