# json_encode ignores protected/private class members

- Thread: https://externals.io/message/40885
- Original archive: https://news-web.php.net/php.internals/40885
- Started by Jarismar Chaves da Silva on 2008-10-09T12:54:05+00:00
- Messages: 20
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #40885 — Jarismar Chaves da Silva — 2008-10-09T12:54:05+00:00

URL: https://externals.io/message/40885#40885

Hi internals,

  Does anyone knows why json_encode ignores protected/public class members ?
  I've searching about it on documentation an mailing lists but found 
nothing but workarounds.
  Until now I'm forced to change my classes to use public members when I 
need to send a PHP object on e.g. AJAX responses. It would be nice if 
json_encode also send those attributes or at least have a parameter to 
whether send non-public attributes or not.

Thanks in advance.
 Jaris.

-- 

*Jarismar Chaves da Silva, M.Sc.*

*ADP**Labs** Brazil**
*jarismar_silva@adplabs.com.br <mailto:jarismar_silva@adplabs.com.br>
http://www.adp.com

---

## #40886 — Vesselin Kenashkov — 2008-10-09T13:07:59+00:00

URL: https://externals.io/message/40885#40886 · In reply to: #40885

Until this gets fixed instead of declaring the properties public you can use
a encode method like this:
<?
class c1
{
protected $p1 = 'aa';
public $p2 = 'bb';
public function enc()
    {
    //print $this->p1;
    return json_encode(get_object_vars($this));//this will encode the
protected var
    }
}
$o = new c1;
print $o->enc();
?>

On Thu, Oct 9, 2008 at 3:54 PM, Jarismar Chaves da Silva <
jarismar_silva@adplabs.com.br> wrote:

> Hi internals,
>
>  Does anyone knows why json_encode ignores protected/public class members ?
>  I've searching about it on documentation an mailing lists but found
> nothing but workarounds.
>  Until now I'm forced to change my classes to use public members when I
> need to send a PHP object on e.g. AJAX responses. It would be nice if
> json_encode also send those attributes or at least have a parameter to
> whether send non-public attributes or not.
>
> Thanks in advance.
> Jaris.
>
> --
>
> *Jarismar Chaves da Silva, M.Sc.*
>
> *ADP**Labs** Brazil**
> *jarismar_silva@adplabs.com.br <mailto:jarismar_silva@adplabs.com.br>
> http://www.adp.com

---

## #40887 — Jarismar Chaves da Silva — 2008-10-09T13:13:43+00:00

URL: https://externals.io/message/40885#40887 · In reply to: #40886

Ok, nice solution, but I still don't see why json_encode ignores 
protected/private class members. I mean,  why we need this feature.

Vesselin Kenashkov wrote:
> Until this gets fixed instead of declaring the properties public you 
> can use a encode method like this:
> <?
> class c1
> {
> protected $p1 = 'aa';
> public $p2 = 'bb';
> public function enc()
>     {
>     //print $this->p1;
>     return json_encode(get_object_vars($this));//this will encode the 
> protected var
>     }
> }
> $o = new c1;
> print $o->enc();
> ?>
>
> On Thu, Oct 9, 2008 at 3:54 PM, Jarismar Chaves da Silva 
> <jarismar_silva@adplabs.com.br <mailto:jarismar_silva@adplabs.com.br>> 
> wrote:
>
>     Hi internals,
>
>      Does anyone knows why json_encode ignores protected/public class
>     members ?
>      I've searching about it on documentation an mailing lists but
>     found nothing but workarounds.
>      Until now I'm forced to change my classes to use public members
>     when I need to send a PHP object on e.g. AJAX responses. It would
>     be nice if json_encode also send those attributes or at least have
>     a parameter to whether send non-public attributes or not.
>
>     Thanks in advance.
>     Jaris.
>
>     -- 
>
>     *Jarismar Chaves da Silva, M.Sc.*
>
>     *ADP**Labs** Brazil**
>     *jarismar_silva@adplabs.com.br
>     <mailto:jarismar_silva@adplabs.com.br>
>     <mailto:jarismar_silva@adplabs.com.br
>     <mailto:jarismar_silva@adplabs.com.br>>
>     http://www.adp.com
>
>

-- 

*Jarismar Chaves da Silva, M.Sc.*

*ADP**Labs** Brazil**
*+55 51 3327 1491 – Direct

+55 51 9947 3613 – Mobile

jarismar_silva@adplabs.com.br <mailto:jarismar_silva@adplabs.com.br>
http://www.adp.com 
This message and any attachments are intended only for the use of the 
addressee and may contain information that is privileged and 
confidential. If the reader of the message is not the intended recipient 
or an authorized representative of the intended recipient, you are 
hereby notified that any dissemination of this communication is strictly 
prohibited. If you have received this communication in error, please 
notify us immediately by e-mail and delete the message and any 
attachments from your system.

---

## #40888 — Stefan Walk — 2008-10-09T13:17:36+00:00

URL: https://externals.io/message/40885#40888 · In reply to: #40887

On Thursday 09 October 2008 15:13:43 Jarismar Chaves da Silva wrote:
> Ok, nice solution, but I still don't see why json_encode ignores
> protected/private class members. I mean,  why we need this feature.

Because, in theory, it shouldn't even be able to see those members?

Regards,
Stefan

---

## #40889 — David Coallier — 2008-10-09T13:26:02+00:00

URL: https://externals.io/message/40885#40889 · In reply to: #40888

> > […]
>
> Because, in theory, it shouldn't even be able to see those members?
>

Stefan's right. Unless you are in the local scope or inheriting the
object you shouldn't be able to see those variables. And I have yet to
see

classs Name extends json_decode($jsonValues) { }

That's the point in having access modifiers. Unless I'm mistaking
there's no bug there.



-- 
Slan,
David

---

## #40890 — Lukas Kahwe Smith — 2008-10-09T13:31:54+00:00

URL: https://externals.io/message/40885#40890 · In reply to: #40889

> > […]
>
> Stefan's right. Unless you are in the local scope or inheriting the
> object you shouldn't be able to see those variables. And I have yet to
> see
>
> classs Name extends json_decode($jsonValues) { }
>
> That's the point in having access modifiers. Unless I'm mistaking
> there's no bug there.


well .. i think this is at least the common use case. then again, json  
is an encoding format, and i expect that i can get the same object  
state by decoding. so the expectation to also get non public  
properties in the json encoded string is not totally crazy.

however changing this at this point would be a huge security issue, so  
if at all, it would need to be handled by an optional parameter that  
defaults to false.

regards,
Lukas Kahwe Smith
mls@pooteeweet.org

---

## #40891 — Jarismar Chaves da Silva — 2008-10-09T13:42:12+00:00

URL: https://externals.io/message/40885#40891 · In reply to: #40888

I agree with you.
But when using json_encode I believe the developer wants to transfer the 
complete object state, just like when using serialize.
Serialize does see private/protected class members, while json_encode not.
Javascript does not have class-accessors so why not convert 
protected/private to public javascript attributes.

Stefan Walk wrote:
> On Thursday 09 October 2008 15:13:43 Jarismar Chaves da Silva wrote:
>   
> > […]
>
> Because, in theory, it shouldn't even be able to see those members?
>
> Regards,
> Stefan
>
>   
-- 

*Jarismar Chaves da Silva, M.Sc.*

*ADP**Labs** Brazil**
*jarismar_silva@adplabs.com.br <mailto:jarismar_silva@adplabs.com.br>
http://www.adp.com

---

## #40892 — Dave Ingram — 2008-10-09T13:45:29+00:00

URL: https://externals.io/message/40885#40892 · In reply to: #40890

> > […]
> well .. i think this is at least the common use case. then again, json
> is an encoding format, and i expect that i can get the same object
> state by decoding. so the expectation to also get non public
> properties in the json encoded string is not totally crazy.

I'd have thought the common use case is that you only want the public
class members, unless you're inside the class. It could make sense to
have an additional "member visibility filter" flag of some kind,
defaulting to public visibility, but can be set to encode protected or
private members as well (for backwards compatibility). It would be nice
(I suppose) if it automatically encoded private/protected members as
well depending on context, but I'm not sure how complex it would be to
add, and how intuitive it would be.

I think that the solution given earlier is best though - explicitly
encoding the array returned by `get_object_vars()`.

> But when using json_encode I believe the developer wants to transfer
> the complete object state, just like when using serialize.
> Serialize does see private/protected class members, while json_encode not.
If you want to serialize an object, then use the appropriate function. I
think that `json_encode()` has the correct behaviour - encoding only the
publicly-visible structure of an object. They have fundamentally
different aims. If you want to expose data to an external source (e.g.
JavaScript) then surely it would make sense for it to be a public class
member? Why would you not want your PHP code to be able to access it?

> Javascript does not have class-accessors so why not convert
> protected/private to public javascript attributes. 
That's true, although it does have convention that members beginning
with an underscore are generally understood to be treated as
private/protected.


Dave

---

## #40893 — Lukas Kahwe Smith — 2008-10-09T13:49:59+00:00

URL: https://externals.io/message/40885#40893 · In reply to: #40892

> > […]
> If you want to serialize an object, then use the appropriate  
> function. I
> think that `json_encode()` has the correct behaviour - encoding only the
> publicly-visible structure of an object. They have fundamentally
> different aims. If you want to expose data to an external source (e.g.
> JavaScript) then surely it would make sense for it to be a public  
> class
> member? Why would you not want your PHP code to be able to access it?


Because JSON is a language agnostic serialization format. Again I  
agree that in the usual situation you only want public, but the other  
use case is also quite legit. Having to add such a "hack" into every  
class is not very useable, especially until we have traits.

regards,
Lukas Kahwe Smith
mls@pooteeweet.org

---

## #40894 — Stefan Walk — 2008-10-09T13:51:22+00:00

URL: https://externals.io/message/40885#40894 · In reply to: #40890

On Thursday 09 October 2008 15:31:54 Lukas Kahwe Smith wrote:
> well .. i think this is at least the common use case. then again, json
> is an encoding format, and i expect that i can get the same object
> state by decoding. so the expectation to also get non public
> properties in the json encoded string is not totally crazy.

Well, you lose the information about the class anyway, so there is no way to 
decode it to the previous state without implementing it yourself, and in 
order to set private/protected attributes, you have to implement it as a 
method ... and if you do that, it's natural that you also do a member 
function that does the encoding, so the round-trip argument doesn't really 
work.

> however changing this at this point would be a huge security issue, so
> if at all, it would need to be handled by an optional parameter that
> defaults to false.

That would be unclean. If it's implemented in some way, json_encode should 
look for the implementation of some interface (JSONEncodable or something) 
providing encoding/decoding methods (similar to __sleep/__wakeup).

Regards,
Stefan

---

## #40896 — Dave Ingram — 2008-10-09T13:57:53+00:00

URL: https://externals.io/message/40885#40896 · In reply to: #40894

> > […]
>
> That would be unclean. If it's implemented in some way, json_encode should 
> look for the implementation of some interface (JSONEncodable or something) 
> providing encoding/decoding methods (similar to __sleep/__wakeup).
>   
I must say that does sound like a very elegant way of doing things. Then
the default for __json_encode() would encode the public members, and
there would be no default __json_decode(), I suppose.


Dave

---

## #40895 — Ron Rademaker — 2008-10-09T13:58:02+00:00

URL: https://externals.io/message/40885#40895 · In reply to: #40894

Stefan Walk wrote:
> That would be unclean. If it's implemented in some way, json_encode should 
> look for the implementation of some interface (JSONEncodable or something) 
> providing encoding/decoding methods (similar to __sleep/__wakeup).
Looking at our current JSON implementations, such an interface would be 
very very welcome. If at all possible something like JSONDecodable would 
be great as well, for restoring class members from json.

Ron

---

## #40897 — Dave Ingram — 2008-10-09T14:00:29+00:00

URL: https://externals.io/message/40885#40897 · In reply to: #40895

Ron Rademaker wrote:
> Stefan Walk wrote:
> > […]
> Looking at our current JSON implementations, such an interface would
> be very very welcome. If at all possible something like JSONDecodable
> would be great as well, for restoring class members from json.
I'm thinking about getting involved with some PHP internals, so this
might be as good a place to start as any, unless someone else is
particularly interested or motivated. Having said that, I had first
planned to make some minor changes to the apache2 SAPI to solve a
long-requested feature. I haven't yet looked into why the Apache hasn't
been implemented yet though, so I didn't want to propose it yet.


Dave

---

## #40898 — Jarismar Chaves da Silva — 2008-10-09T14:44:55+00:00

URL: https://externals.io/message/40885#40898 · In reply to: #40896

Yes, it like it too. Just like an OOP should be.

Dave Ingram wrote:
> > […]
> I must say that does sound like a very elegant way of doing things. Then
> the default for __json_encode() would encode the public members, and
> there would be no default __json_decode(), I suppose.
>
>
> Dave
>
>   

-- 

*Jarismar Chaves da Silva, M.Sc.*

*ADP**Labs** Brazil**
*+55 51 3327 1491 -- Direct

+55 51 9947 3613 -- Mobile

jarismar_silva@adplabs.com.br <mailto:jarismar_silva@adplabs.com.br>
http://www.adp.com 
This message and any attachments are intended only for the use of the 
addressee and may contain information that is privileged and 
confidential. If the reader of the message is not the intended recipient 
or an authorized representative of the intended recipient, you are 
hereby notified that any dissemination of this communication is strictly 
prohibited. If you have received this communication in error, please 
notify us immediately by e-mail and delete the message and any 
attachments from your system.

---

## #40899 — Rodrigo Saboya — 2008-10-09T21:43:00+00:00

URL: https://externals.io/message/40885#40899 · In reply to: #40891

Jarismar Chaves da Silva wrote:
> I agree with you.
> But when using json_encode I believe the developer wants to transfer the 
> complete object state, just like when using serialize.
> Serialize does see private/protected class members, while json_encode not.
> Javascript does not have class-accessors so why not convert 
> protected/private to public javascript attributes.

In theory only the public members are relevant to anyone except the 
object itself. If you need information about private/protected members 
you are either using the wrong visibility for your variables or using 
json for something it's not supposed to do.

-- Rodrigo Saboya

---

## #40914 — Richard Quadling — 2008-10-10T09:30:08+00:00

URL: https://externals.io/message/40885#40914 · In reply to: #40899

2008/10/9 Rodrigo Saboya <rodrigo.saboya@bolsademulher.com>:
> Jarismar Chaves da Silva wrote:
> > […]
>
> In theory only the public members are relevant to anyone except the object
> itself. If you need information about private/protected members you are
> either using the wrong visibility for your variables or using json for
> something it's not supposed to do.
>
> -- Rodrigo Saboya
>
> --
> 
> 
>
>

A simply userland solution would be to use an abstract base class with
 `json_encode()`/json_decode() as public final methods. All classes
needing to support json_encode/json_decode would simply need to extend
from this base class.

No need to add even more "magic" to the base stdClass.

Richard.

-- 
-----
Richard Quadling
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
"Standing on the shoulders of some very clever giants!"

---

## #40909 — Jarismar Chaves da Silva — 2008-10-10T11:52:23+00:00

URL: https://externals.io/message/40885#40909 · In reply to: #40899

Rodrigo Saboya wrote:
> Jarismar Chaves da Silva wrote:
> > […]
>
> In theory only the public members are relevant to anyone except the 
> object itself. If you need information about private/protected members 
> you are either using the wrong visibility for your variables or using 
> json for something it's not supposed to do.

Yes, of course. But currently json_encode ignores the attributes even if 
the call is from inside the class.
<?php
class Person {
    protected $name;

    public function __construct($sName) {
        $this->name = $sName;
    }

    public function toJSON() {
        return json_encode($this);
    }
}

$person = new Person('jaris');
print $person->toJSON(); // ==> will print an empty object e.g. {}
?>

I don't know if I'm using json_encode for something it's not supposed to 
do. I'm using it to serialize an object to send it to another 
runtime-environment in response to an remote call, just like what I can 
do with SOAP, REST or RMI. In this context I don't see much sense in 
preventing protected/private data from being transfered.

Regards,
Jaris.

> -- Rodrigo Saboya
>

-- 

*Jarismar Chaves da Silva, M.Sc.*

*ADP**Labs** Brazil**
*jarismar_silva@adplabs.com.br <mailto:jarismar_silva@adplabs.com.br>
http://www.adp.com

---

## #40910 — Richard Quadling — 2008-10-10T12:25:53+00:00

URL: https://externals.io/message/40885#40910 · In reply to: #40909

2008/10/10 Jarismar Chaves da Silva <jarismar_silva@adplabs.com.br>:
>
>
> Rodrigo Saboya wrote:
> > […]
>
> Yes, of course. But currently json_encode ignores the attributes even if the
> call is from inside the class.
> <?php
> class Person {
>   protected $name;
>
>   public function __construct($sName) {
>       $this->name = $sName;
>   }
>
>   public function toJSON() {
>       return json_encode($this);
>   }
> }
>
> $person = new Person('jaris');
> print $person->toJSON(); // ==> will print an empty object e.g. {}
> ?>
>
> I don't know if I'm using json_encode for something it's not supposed to do.
> I'm using it to serialize an object to send it to another
> runtime-environment in response to an remote call, just like what I can do
> with SOAP, REST or RMI. In this context I don't see much sense in preventing
> protected/private data from being transfered.
>
> Regards,
> Jaris.
>
> > […]
>
> --
>
> *Jarismar Chaves da Silva, M.Sc.*
>
> *ADP**Labs** Brazil**
> *jarismar_silva@adplabs.com.br <mailto:jarismar_silva@adplabs.com.br>
> http://www.adp.com
>
>

Let's just for example say that class X has the username and password
values for the login system.

You've made them private as only this class should access them.

How are you going to stop the `json_encode()` from seeing them and
passing them on.




-- 
-----
Richard Quadling
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
"Standing on the shoulders of some very clever giants!"

---

## #40943 — Daniel Convissor — 2008-10-12T14:08:39+00:00

URL: https://externals.io/message/40885#40943 · In reply to: #40909

Hi Jaris:

> I don't know if I'm using json_encode for something it's not supposed to  
> do. I'm using it to serialize an object to send it to another  
> runtime-environment in response to an remote call, just like what I can  
> do with SOAP, REST or RMI. In this context I don't see much sense in  
> preventing protected/private data from being transfered.

So you are accessing the class from outside.  This is exactly the 
situation where private and protected should not be visible.  It's just 
like you're trying to access private properties from the wrong scope in 
PHP itself:

<?php
class c {
    private $p = 'hidden';
}

$o = new c;
echo $o->p;  // This will fail, as it should.

You need to change your architecture to do what you want.

--Dan

-- 
 T H E   A N A L Y S I S   A N D   S O L U T I O N S   C O M P A N Y
            data intensive web and database programming
                http://www.AnalysisAndSolutions.com/
 4015 7th Ave #4, Brooklyn NY 11232  v: 718-854-0335 f: 718-854-0409

---

## #41160 — Lukas Kahwe Smith — 2008-10-16T18:08:28+00:00

URL: https://externals.io/message/40885#41160 · In reply to: #40943

Hi,

So I guess the conclusion is:
Create a feature request ticket, take the information from this thread  
and put it into the ticket .. and ideally write a patch yourself or  
motivate someone else ..

regards,
Lukas
