<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>shoreflyer.net &#187; admin</title>
	<atom:link href="http://www.shoreflyer.net/author/admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.shoreflyer.net</link>
	<description>blog this!</description>
	<lastBuildDate>Sat, 18 Dec 2010 16:24:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Custom JSON De-serializer for PHP</title>
		<link>http://www.shoreflyer.net/2010/12/18/custom-json-de-serializer-for-php/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=custom-json-de-serializer-for-php</link>
		<comments>http://www.shoreflyer.net/2010/12/18/custom-json-de-serializer-for-php/#comments</comments>
		<pubDate>Sat, 18 Dec 2010 16:24:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[de-serialization]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[reflection]]></category>

		<guid isPermaLink="false">http://www.shoreflyer.net/?p=46</guid>
		<description><![CDATA[My previous post dealt with taking an object graph and turning it into JSON. If you are building a RESTful web service using PHP and you don&#8217;t have the option of using frameworks like Jersey for Java or just prefer &#8230; <a href="http://www.shoreflyer.net/2010/12/18/custom-json-de-serializer-for-php/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My previous <a href="http://www.shoreflyer.net/2010/12/06/custom-json-serializer-for-php/">post</a> dealt with taking an object graph and turning it into JSON. If you are building a RESTful web service using PHP and you don&#8217;t have the option of using frameworks like Jersey for Java or just prefer doing things in PHP then you also might find the following de-serializer useful. It is not complete in its current form but I chose to share it as is in case someone needed an idea of how to accomplish this.<br />
<span id="more-46"></span></p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
namespace YourCompanyUtil;

/**
 *
 * Custom JSON de-serializer using reflection.
 * WARNING: NOT TO BE USED FOR HI LOAD APPLICATIONS!!!
 *
 * @author christian.kassab@binaryworx.net
 *
 */
class JsonDeserializer{

	private $aSimpleTypes = array( 'bool', 'boolean', 'int', 'integer', 'float', 'double', 'string', 'array');

	/**
	 *
	 * depth
	 * @var integer
	 */
	private $iDepth = 6;

	/**
	 *
	 * keep track of the current depth
	 * @var integer
	 */
	private $iCurrentDepth = 0;

	/**
	 *
	 * are we using type prefixes
	 * @var boolean
	 */
	private $bUsesTypePrefixes = true;

	/**
	 *
	 * default constructor with options
	 * @param array $aOpts
	 */
	public function __construct(array $aOpts = array()){

	}

	/**
	 *
	 * unmarshall json string to given object type
	 * @param string $sType
	 * @param string $sJson
	 * @return
	 */
	public function unMarshall($sType, $sJson){
		$aObjectGraph = json_decode($sJson, true);
		return $this-&gt;_unMarshall($aObjectGraph, $sType);
	}

	/**
	 *
	 * do the actual unmarshalling...
	 * @param array $aObjectGraph
	 * @param string $sType
	 */
	protected function _unMarshall(array $aObjectGraph, $sType){
		$oRC = new ReflectionClass($sType);
		$aProperties = $oRC-&gt;getProperties();
		$o = $oRC-&gt;newInstance();

		foreach($aProperties as $oRPC){
			$sName = ($this-&gt;bUsesTypePrefixes) ? lcfirst(substr($oRPC-&gt;getName(), 1)) : $oRPC-&gt;getName();
			if(isset($aObjectGraph[$sName])){
				if(!$oRPC-&gt;isPublic()){
					$oRPC-&gt;setAccessible(true);
				}

				if($sType = $this-&gt;_getTypeFromDocBlock($oRPC)){
					$bScalar = is_scalar($aObjectGraph[$sName]);
					if($bScalar &amp;&amp; $this-&gt;_isSimpleType($sType)){
						$oRPC-&gt;setValue($o, $aObjectGraph[$sName]);
					}elseif($bScalar){
						$oRPC-&gt;setValue($o, $this-&gt;_objectForType($sType, $aObjectGraph[$sName]));
					}else{
						if($this-&gt;_hasGenerics($sType)){
                            // handle generics here if necessary...

						}else{
							$oRPC-&gt;setValue($o, $this-&gt;_unMarshall($aObjectGraph[$sName], $sType));
						}
					}

				}else{
					throw new Exception('Missing type annotation for property: ' . $sName);
				}

				if(!$oRPC-&gt;isPublic()){
					$oRPC-&gt;setAccessible(false);
				}
			}
		}

		return $o;
	}

	/**
	 *
	 * fetch the varialble type from the docblock
	 * @param ReflectionProperty $oRPC
	 */
	protected function _getTypeFromDocBlock(ReflectionProperty $oRPC){

		$sComment = $oRPC-&gt;getDocComment();
		$aTmp = array();
		if(preg_match_all('|@vars([\\a-z_]{1}[\\a-z0-9_&lt;&gt;]+)s|i', $sComment, $aTmp, PREG_SET_ORDER)){
			return $aTmp[0][1];
		}
		return null;
	}

	/**
	 *
	 * determine if type has generics
     *   e.g. type could be array&lt;YourCompanySubPackageMyClass&gt; or YourCompanyUtilMyCollectionClass&lt;YourCompanySubPackageMyClass&gt;
     *
	 * @param string $sType
	 * @return boolean
	 */
	protected function _hasGenerics($sType){
		return preg_match('|(&lt;([\\a-z0-9_]+)&gt;)|i', $sType);
	}

	/**
	 *
	 * check to see if the type is actually a simple type...
	 * @param string $sType
	 * @return boolean
	 */
	protected function _isSimpleType($sType){
		return in_array($sType, $this-&gt;aSimpleTypes);
	}

	/**
	 *
	 * factory for special object types
	 *   this method can loop through registered type handlers... yet to be implemented
	 * @param string $sType
	 * @param mixed $mValue
	 * @return object
	 */
	protected function _objectForType($sType, $mValue){

		return null;
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.shoreflyer.net/2010/12/18/custom-json-de-serializer-for-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom JSON Serializer for PHP</title>
		<link>http://www.shoreflyer.net/2010/12/06/custom-json-serializer-for-php/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=custom-json-serializer-for-php</link>
		<comments>http://www.shoreflyer.net/2010/12/06/custom-json-serializer-for-php/#comments</comments>
		<pubDate>Mon, 06 Dec 2010 22:42:52 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[serialisation]]></category>

		<guid isPermaLink="false">http://www.shoreflyer.net/2010/12/06/json-serializer-for-php/</guid>
		<description><![CDATA[The project I am working on currently requires serializing PHP objects into natural JSON. After a while it gets a bit old having to transform those objects into key-value pair arrays to then transform them into JSON using json_encode. An &#8230; <a href="http://www.shoreflyer.net/2010/12/06/custom-json-serializer-for-php/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The project I am working on currently requires serializing PHP objects into natural JSON.</p>
<p>After a while it gets a bit old having to transform those objects into key-value pair arrays to then transform them into JSON using <a href="http://uk.php.net/json_encode">json_encode</a>. An alternative would be to make all properties public and then just serialize the objects using <a href="http://uk.php.net/json_encode">json_encode</a>&#8230; so much for encapsulation though.</p>
<p>Having worked with Java REST frameworks like <a href="http://jersey.java.net/">Jersey</a> I am used to having plug-able and configurable serializers like JAXB and Jackson. These libraries use intelligent defaults so the amount of configuration and/or annotation is nil or an absolute minimum.</p>
<p>However, as the choice of technology fell on PHP for almost all tiers in the current project I had to come up with an alternative solution producing JSON.</p>
<p>Using <a href="http://fatfree.sourceforge.net/">F3</a>, a light weight PHP framework for serving up the RESTful JSON endpoints all that was missing was the (fairly) intelligent serializer.<br />
<span id="more-30"></span><br />
The light weight implementation below is roughly what I used on the project. You might have to tweak things here and there to suit your projects serialization (marshaling) needs.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
namespace YourCompanyUtil;

/**
 *
 * Custom JSON serializer using reflection.
 * WARNING: NOT TO BE USED FOR HIGH LOAD APPLICATIONS!!!
 *
 * @author christian.kassab@binaryworx.net
 *
 */
class JsonSerializer{

	/**
	 *
	 * maximum depth of serialization
	 * @var integer
	 */
	private $iDepth = 6;

	/**
	 *
	 * keep track of the current depth
	 * @var integer
	 */
	private $iCurrentDepth = 0;

	/**
	 *
	 * are we using type prefixes (e.g. bBoolean, sString, fFloat or just _underScore for private members)
	 * @var boolean
	 */
	private $bUsesTypePrefixes = true;

	/**
	 *
	 * default constructor with options
	 * @param array $aOpts
	 */
	public function __construct(array $aOpts = array()){

	}

	/**
	 *
	 * serialize object/graph to json string
	 * @param object $object
	 * @return string
	 */
	public function marshall($object){
		$aObjectGraph = $this-&gt;_marshall($object);
		return json_encode($aObjectGraph);
	}

	/**
	 *
	 * do the actual serialization and return array of object graph
	 * @param object $object
	 * @return array
	 */
	private function _marshall($object){
		if($this-&gt;iCurrentDepth &gt;= $this-&gt;iDepth){
			return array();
		}
		$this-&gt;iCurrentDepth++;
		$aPartialGraph = array();
		if($object instanceof ArrayAccess){
			$aPartialGraph = $this-&gt;_marshallCollection($object);
		}else{
			$oR = new ReflectionClass($object);
			foreach($oR-&gt;getProperties() as $oProperty){
				if(!strstr($oProperty-&gt;getDocComment(), '@Transient')){
					$aPartialGraph = array_merge($aPartialGraph, $this-&gt;_marshalProperty($oProperty, $object));
				}
			}
		}

		$this-&gt;iCurrentDepth--;
		return $aPartialGraph;
	}

	/**
	 *
	 * manage individual properties
	 *
	 * @param ReflectionProperty $oProperty
	 * @param object $object
	 * @return array
	 */
	private function _marshalProperty(ReflectionProperty $oProperty, $object){
		$sPropName = $oProperty-&gt;getName();
		if($this-&gt;bUsesTypePrefixes){
			$sPropName = lcfirst(substr($sPropName, 1));
		}

		$aProperty = array();
		$mValue = null;
		if($oProperty-&gt;isPrivate() || $oProperty-&gt;isProtected()){
			$oProperty-&gt;setAccessible(true);
			$mValue = $oProperty-&gt;getValue($object);
			$oProperty-&gt;setAccessible(false);
		}else{
			$mValue = $oProperty-&gt;getValue($object);
		}

		switch (gettype($mValue)){
			case 'array':
				$aProperty[$sPropName] = $this-&gt;_marshallArray($mValue);
				break;
			case 'object':
				$aProperty[$sPropName] = $this-&gt;_marshall($mValue);
				break;
			default:
				$aProperty[$sPropName] = $mValue;
		}

		return $aProperty;
	}

	/**
	 *
	 * marshall array
	 * @param array $aValues
	 * @return array
	 */
	private function _marshallArray(array $aValues){
		$aReturn = array();
		foreach($aValues as $mKey=&gt;$mValue){
			if(is_object($mValue)){
				$aReturn[$mKey] = $this-&gt;_marshall($mValue);
			}elseif(is_array($mValue)){
				$aReturn[$mKey] = $this-&gt;_marshallArray($mValue);
			}else{
				$aReturn[$mKey] = $mValue;
			}
		}

		return $aReturn;
	}

	/**
	 *
	 * marshall collection
	 * @param ArrayAccess $collection
	 */
	private function _marshallCollection(ArrayAccess $collection){
		$aReturn = array();
		foreach($collection as $mValue){
			$aReturn[] = $this-&gt;_marshall($mValue);
		}
		return $aReturn;
	}
}
</pre>
<p>Feel free to use this code &#8220;as is&#8221; and share any improvements with the rest of us. I hope this helps some of you having similar problems to solve.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shoreflyer.net/2010/12/06/custom-json-serializer-for-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello world!</title>
		<link>http://www.shoreflyer.net/2010/12/01/hello-world-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=hello-world-2</link>
		<comments>http://www.shoreflyer.net/2010/12/01/hello-world-2/#comments</comments>
		<pubDate>Wed, 01 Dec 2010 22:21:10 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.shoreflyer.net/2006/05/06/hello-world/</guid>
		<description><![CDATA[Hey, so you have stumbled upon my blog&#8230; Visit again some time, who knows, maybe I will have shared something worth while by then.]]></description>
			<content:encoded><![CDATA[<p>Hey, so you have stumbled upon my blog&#8230;</p>
<p>Visit again some time, who knows, maybe I will have shared something worth while by then.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shoreflyer.net/2010/12/01/hello-world-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

