Skip to content

Instantly share code, notes, and snippets.

@paulferrett
Last active March 10, 2017 15:53
Show Gist options
  • Save paulferrett/9751776 to your computer and use it in GitHub Desktop.
Save paulferrett/9751776 to your computer and use it in GitHub Desktop.
<?php
namespace Acme\YourBundle\Serializer;
use JMS\Serializer\Context;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Metadata\ClassMetadata;
/*
* Copyright 2014 Paul Ferrett <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class SideLoadJsonSerializationVisitor extends JsonSerializationVisitor {
private $sideData = array();
private $sideDataIds = array();
public function getRoot() {
$root = parent::getRoot();
if (!is_array($root) || !$root) {
return $root;
}
return $root + $this->sideData;
}
public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) {
$rs = parent::endVisitingObject($metadata, $data, $type, $context);
if ($context->getDepth() === 0) {
return $rs;
}
return $this->addSideData($rs, $metadata, $data, $type, $context);
}
protected function addSideData($rs, ClassMetadata $metadata, $data, array $type, Context $context) {
$class = $this->getSideDataClass($metadata, $data, $type);
$id = $this->getSideDataId($metadata, $data);
if (!$class || !$id) {
return $rs;
}
if (!isset($this->sideDataIds[$class])) {
$this->sideDataIds[$class] = array();
$this->sideData[$class] = array();
} else if (in_array($id, $this->sideDataIds[$class])) {
return $id;
}
$this->sideDataIds[$class][] = $id;
$this->sideData[$class][] = $rs;
return $id;
}
protected function getSideDataClass(ClassMetadata $metadata, $data, array $type) {
$className = get_class($data);
if (strpos($className, '\\') !== false) {
$className = substr($className, strrpos($className, '\\') + 1);
}
return strtolower(preg_replace(array('/(s|x)$/', '/y$/'), array('$1e', 'ie'), lcfirst($className))) . 's';
}
protected function getSideDataId(ClassMetadata $metadata, $data) {
if (!method_exists($data, 'getId')) {
return null;
}
return $data->getId();
}
}
@gbirke
Copy link

gbirke commented Mar 29, 2014

You should add the following to the header:

use JMS\Serializer\Context;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Metadata\ClassMetadata;

If those lines are missing, you'll get errors because the classes are not found by the autoloader in the global/current namespace.

@paulferrett
Copy link
Author

@gbirke Thanks for the pickup! I've added them in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment