PHP Annotations und Reflections

Mit Hilfe der Reflections-Klassen in PHP sit es auch z.B. möglich sich einen JSON-Encoder zubauen, der nicht verlangt, dass alle Attribute der Klasse public sein müssen. Ähnlich wie in Java kann man hier auch auf private Attribute ohne Probleme zugreifen wenn man dieses setzt:


$prop->setAccessible(true);


Wenn man dann noch neben den skalaren Typen eine extra Behandlung für Array-Inhalte und Objekte einbaut, kann man sich ganz einfach einen rekursiven JSON-Encoder bauen, der auch mit normalen Beans mit Gettern und Settern zurecht kommt und man keine zusätzlichen DTOs mehr extra anlegen muss.


class XWJSONConverter{
public function __construct(){

}

public function convert($value,$level=0,$name=null,$firstInLine=true,$result=""){
$opening=false;
if($level==0 && $name!=null){
$result.="{";
$opening=true;
}
if(is_scalar($value)){
if(!$firstInLine){
$result.= ",";
}
if($name!=null){
$result.= '"'.$name.'":';
}
$result.= json_encode($value);
}
else if(is_array($value)){
if($name!=null){
$result.= '"'.$name.'":';
}
$result.= "[";
$i=0;
foreach($value as $val){
$result=$this->convert($val,$level+1,null,$i==0,$result);
$i++;
}
$result.= "]";
}
else if(is_object($value)){
if(!$firstInLine){
$result.= ",";
}
if($name!=null){
$result.= '"'.$name.'":';
}
$result.= "{";
$ref=new ReflectionClass(get_class($value));
$props=$ref->getProperties();
$cnt=count($props);
for($i=0;$i<$cnt;$i++){
$prop=$props[$i];

$doc=trim($prop->getDocComment());
if(!preg_match("/@json_transient/i",$doc)){
$prop->setAccessible(true);
$name=$prop->getName();
if($prop->isPrivate() || $prop->isProtected()){
$name=preg_replace("/^_/","",$name);
}
$result=$this->convert($prop->getValue($value),$level+1,$name,$i==0,$result);
}
}
$result.= "}";
}
else if(is_null($value)){
if (!$firstInLine) {
$result .= ',';
}
if ($name != null) {
$result .= '"' . $name . '":';
}
$result .= 'null';
}

if($opening){
$result.="}";
}
return $result;
}
}


Ein Decoder war mir jetzt nciht wirklich wichtig, da in meinen Anwendungsfällen PHP eigetnlich immer nur JSON für REST-APIs generiert und auf JavaScript-Seite, das decodieren in eine Objekt-Struktur ohne Probleme dann wieder möglich ist. Da sind private und public nicht mehr wichtig.

Was hier noch interessant sein könnte ist mein Versuch mit Annotations in PHP zu arbeiten. Wenn man verhindern will, dass ein Attribute mit nach JSON encodiert wird, kann man das damit verhindern:


class Test{
private $toJSON="ok";
/**
* @json_transient
*/
private $notToJSON="ne";
}


Damit wird im JSON-String nur das erste Attribute auftauchen.
User annonyme 2015-09-16 19:22

write comment:
Five + = 10

Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?