Well after 2 hours of digging (cf Edits)
I found out following :
- In my case it's a encoding problem
mb_detect_encodingreturns probably a faulty response, some strings were probably not UTF-8- using
utf8_encode()on those string solved my problem, but see note below
Here is a recursive function that can force convert to UTF-8 all the strings contained in an array:
function utf8ize($d) {
if (is_array($d)) {
foreach ($d as $k => $v) {
$d[$k] = utf8ize($v);
}
} else if (is_string ($d)) {
return utf8_encode($d);
}
return $d;
}
Use it simply like this:
echo json_encode(utf8ize($data));
Note: utf8_encode() encodes ISO-8859-1 string to UTF-8 as per the docs so if you are unsure of the input encoding iconv() or mb_convert_encoding() may be better options as noted in comments and other solutions.
Answer from Matthieu Riegler on Stack OverflowWell after 2 hours of digging (cf Edits)
I found out following :
- In my case it's a encoding problem
mb_detect_encodingreturns probably a faulty response, some strings were probably not UTF-8- using
utf8_encode()on those string solved my problem, but see note below
Here is a recursive function that can force convert to UTF-8 all the strings contained in an array:
function utf8ize($d) {
if (is_array($d)) {
foreach ($d as $k => $v) {
$d[$k] = utf8ize($v);
}
} else if (is_string ($d)) {
return utf8_encode($d);
}
return $d;
}
Use it simply like this:
echo json_encode(utf8ize($data));
Note: utf8_encode() encodes ISO-8859-1 string to UTF-8 as per the docs so if you are unsure of the input encoding iconv() or mb_convert_encoding() may be better options as noted in comments and other solutions.
For me, the answer to this problem was setting charset=utf8 in my PDO connection.
$dbo = new PDO('mysql:host=localhost;dbname=yourdb;charset=utf8', $username, $password);
Any ideas about why json_encode would return empty for a request on local dev, but not empty on server?
json_encode shows empty objects
Best way to create an empty object in JSON with PHP? - Stack Overflow
php - Why json_encode returns empty brackets? - Stack Overflow
I have a function written like this in my Laravel controller:
/**
* @param Request $request
*
* @throws \Illuminate\Auth\Access\AuthorizationException
* @throws \Throwable
*/
public function saveFreshBatch(Request $request)
{
Log::info("Received a new fresh batch... " . json_encode($request));
...
On my local, I get the following in my logs: "Received a new fresh batch... ", so a string followed by an empty array, with no text afterward, which means the result of json_encode($request) was blank. However, the object is full of data. I ran the debugger and it returned this:
> json_encode($request)
< {"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}
However, json_encode($request->all()) returns the correct string as if doing the whole thing, even on local.
On the production (Dev) server, I get a full JSON output, so a gigantic PHP array. In both cases I notice $request->all() gives full code.
Any ideas why the same code would result in different output, for the same object? The only thing I can think of is the headers are different, or the subclassed request is different.
Why does json_encode($request) return different outputs for the same HTTP request?
Recommended method
json_decode ("{}") will return a stdClass per default, using the below should therefor be considered safe/portable and correct.
json_encode (new stdClass);
Your solution could work..
The documentation specifies that (object) null will result in an empty object, some might therefor say that your code is valid and that it's the method to use.
PHP: Objects - Manual
If a value of any other type is converted to an object, a new instance of the stdClass built-in class is created. If the value was NULL, the new instance will be empty.
.. but, try to keep it safe!
Though you never know when/if the above will change, so if you'd like to be 100% certain that you will always will end up with a {} in your encoded data you could use a hack such as:
$empty = json_decode ("{}");
$result = json_encode($empty); // "{}"
Even though it's tedious and ugly I do assume/hope that json_encode/json_decode is compatible with one another and always will evaluate the following to true:
$a = <something>;
$a === json_decode (json_encode ($a));
If you use objects as dynamic dictionaries (and I guess you do), then I think you want to use an ArrayObject.
It maps into JSON dictionary even when it's empty. It is great if you need to distinguish between lists (arrays) and dictionaries (associative arrays):
$complex = array('list' => array(), 'dict' => new ArrayObject());
print json_encode($complex); // -> {"list":[],"dict":{}}
You can also manipulate it seamlessly (as you would do with an associative array), and it will keep rendering properly into a dictionary:
$complex['dict']['a'] = 123;
print json_encode($complex); // -> {"list":[],"dict":{"a":123}}
unset($complex['dict']['a']);
print json_encode($complex); // -> {"list":[],"dict":{}}
If you need this to be 100% compatible both ways, you can also wrap json_decode so that it returns ArrayObjects instead of stdClass objects (you'll need to walk the result tree and recursively replace all the objects, which is a fairly easy task).
Gotchas. Only one I've found so far: is_array(new ArrayObject()) evaluates to false. You need to find and replace is_array occurrences with is_iterable.
use the JSON_FORCE_OBJECT option of json_encode:
json_encode($status, JSON_FORCE_OBJECT);
Documentation
JSON_FORCE_OBJECT (integer) Outputs an object rather than an array when a non-associative array is used. Especially useful when the recipient of the output is expecting an object and the array is empty. Available since PHP 5.3.0.
Or, if you want to preserve your "other" arrays inside your object, don't use the previous answer, just use this:
$status = array(
"message"=>"error",
"club_id"=>$_club_id,
"status"=>"1",
"membership_info"=> new stdClass()
);
$status = array(
"message"=>"error",
"club_id"=>$_club_id,
"status"=>"1",
"membership_info"=>(object) array(),
);
By casting the array into an object, json_encode will always use braces instead of brackets for the value (even when empty).
This is useful when can't use JSON_FORCE_OBJECT and when you can't (or don't want) to use an actual object for the value.
It is because your class's properties are private.
An example class with only private properties ...
php > class Foo { private $bar = 42; }
php > $obj = new Foo();
do not expose values:
php > echo json_encode($obj);
{}
But an example class with public properties ...
php > class Bar { public $foo = 42; }
php > $objBar = new Bar();
do it!
php > echo json_encode($objBar);
{"foo":42}
\JsonSerializable
PHP provide an'interafce \JsonSerializable that require a method jsonSerialize. This method is automatically called by json_encode().
class JsonClass implements JsonSerialize {
private $bar;
public function __construct($bar) {
$this->bar = $bar;
}
public function jsonSerialize() {
return [
'foo' => $this->bar,
];
}
}
I prefer this solution because is not good to expose publicly properties
serialization and unserialization ...
If you need to serialize and unserialize php object you can ...
php > class Classe { public $pub = "bar"; }
php > $obj = new Classe();
php > $serialized = serialize($obj);
php > $original = unserialize($serialized);
php > var_dump($original);
php shell code:1:
class Classe#2 (1) {
public $pub =>
string(3) "bar"
}
$serialized variable contains O:6:"Classe":1:{s:3:"pub";s:3:"bar";}. As you can see is not a json, but is a format that allow you to recreate original object using unserialize function.
You have a couple of options here.
Option 1: Make your class properties public
Like what sensorario mentioned, change the visibility of your properties so that it is accessible from outside the class, which is where you are calling json_encode.
Option 2: Introduce a method/function within the class to return the encoded JSON object
Have a toJson() function inside your User class.
Of course, there are way more options - such as extending User so that User is not "contaminated", etc.
But yup, the general problem is your private properties.
I bet you are retrieving data in non-utf8 encoding: try to put mysql_query('SET CHARACTER SET utf8') before your SELECT query.
If you have at least PHP 5.5, you can use json_last_error_msg(), which will return a string describing the problem.
If you don't have 5.5, but are on/above 5.3, you can use json_last_error() to see what the problem is.
It will return an integer, that you can use to identify the problem in the function's documentation. Currently (2012.01.19), the identifiers are:
0 = JSON_ERROR_NONE
1 = JSON_ERROR_DEPTH
2 = JSON_ERROR_STATE_MISMATCH
3 = JSON_ERROR_CTRL_CHAR
4 = JSON_ERROR_SYNTAX
5 = JSON_ERROR_UTF8
These can change in future versions, so it's better to consult the manual.
If you are below 5.3, you are out of luck, there is no way to ask what the error was.