Serializer.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. namespace Swagger;
  3. /**
  4. * Class AnnotationDeserializer is used to deserialize a json string
  5. * to a specific Swagger PHP Annotation class and vice versa.
  6. *
  7. * @link https://github.com/zircote/swagger-php
  8. */
  9. class Serializer
  10. {
  11. const CONTACT = 'Swagger\Annotations\Contact';
  12. const DEFINITION = 'Swagger\Annotations\Definition';
  13. const DELETE = 'Swagger\Annotations\Delete';
  14. const EXTERNALDOCUMENTATION = 'Swagger\Annotations\ExternalDocumentation';
  15. const GET = 'Swagger\Annotations\Get';
  16. const HEAD = 'Swagger\Annotations\Head';
  17. const HEADER = 'Swagger\Annotations\Header';
  18. const INFO = 'Swagger\Annotations\Info';
  19. const ITEMS = 'Swagger\Annotations\Items';
  20. const LICENSE = 'Swagger\Annotations\License';
  21. const OPERATION = 'Swagger\Annotations\Operation';
  22. const OPTIONS = 'Swagger\Annotations\Options';
  23. const PARAMETER = 'Swagger\Annotations\Parameter';
  24. const PATCH = 'Swagger\Annotations\Patch';
  25. const PATH = 'Swagger\Annotations\Path';
  26. const POST = 'Swagger\Annotations\Post';
  27. const PROPERTY = 'Swagger\Annotations\Property';
  28. const PUT = 'Swagger\Annotations\Put';
  29. const RESPONSE = 'Swagger\Annotations\Response';
  30. const SCHEMA = 'Swagger\Annotations\Schema';
  31. const SECURITYSCHEME = 'Swagger\Annotations\SecurityScheme';
  32. const SWAGGER = 'Swagger\Annotations\Swagger';
  33. const TAG = 'Swagger\Annotations\Tag';
  34. const XML = 'Swagger\Annotations\Xml';
  35. private static $cachedNames;
  36. private static function getDefinedNames()
  37. {
  38. if (static::$cachedNames === null) {
  39. static::$cachedNames = [];
  40. $reflection = new \ReflectionClass(__CLASS__);
  41. static::$cachedNames = $reflection->getConstants();
  42. }
  43. return static::$cachedNames;
  44. }
  45. public static function isValidClassName($className)
  46. {
  47. return in_array($className, static::getDefinedNames());
  48. }
  49. /**
  50. * Serialize.
  51. *
  52. * @param Annotations\AbstractAnnotation $annotation
  53. * @return string
  54. */
  55. public function serialize(Annotations\AbstractAnnotation $annotation)
  56. {
  57. return json_encode($annotation);
  58. }
  59. /**
  60. * Deserialize a string
  61. *
  62. * @param $jsonString
  63. * @param $className
  64. *
  65. * @return Annotations\AbstractAnnotation
  66. *
  67. * @throws \Exception
  68. */
  69. public function deserialize($jsonString, $className)
  70. {
  71. if (!$this->isValidClassName($className)) {
  72. throw new \Exception($className.' is not defined in Swagger PHP Annotations');
  73. }
  74. return $this->doDeserialize(json_decode($jsonString), $className);
  75. }
  76. /**
  77. * Deserialize a file
  78. *
  79. * @param $filename
  80. * @param $className
  81. *
  82. * @return Annotations\AbstractAnnotation
  83. *
  84. * @throws \Exception
  85. */
  86. public function deserializeFile($filename, $className = 'Swagger\Annotations\Swagger')
  87. {
  88. if (!$this->isValidClassName($className)) {
  89. throw new \Exception($className.' is not defined in Swagger PHP Annotations');
  90. }
  91. $jsonString = file_get_contents($filename);
  92. return $this->doDeserialize(json_decode($jsonString), $className);
  93. }
  94. /**
  95. * Do deserialization.
  96. *
  97. * @param \stdClass $c
  98. * @param string $class The class name of annotation.
  99. *
  100. * @return Annotations\AbstractAnnotation
  101. */
  102. private function doDeserialize(\stdClass $c, $class)
  103. {
  104. $annotation = new $class([]);
  105. foreach ($c as $property => $value) {
  106. if ($property === '$ref') {
  107. $property = 'ref';
  108. }
  109. if (substr($property, 0, 2) === 'x-') {
  110. $custom = substr($property, 2);
  111. $annotation->x[$custom] = $value;
  112. } else {
  113. $annotation->$property = $this->doDeserializeProperty($annotation, $property, $value);
  114. }
  115. }
  116. return $annotation;
  117. }
  118. /**
  119. * Deserialize the annotation's property.
  120. *
  121. * @param Annotations\AbstractAnnotation $annotation
  122. * @param string $property
  123. * @param mixed $value
  124. *
  125. * @return mixed
  126. */
  127. private function doDeserializeProperty(Annotations\AbstractAnnotation $annotation, $property, $value)
  128. {
  129. // property is primitive type
  130. if (array_key_exists($property, $annotation::$_types)) {
  131. return $value;
  132. }
  133. // property is embedded annotation
  134. foreach ($annotation::$_nested as $class => $declaration) {
  135. // property is an annotation
  136. if (is_string($declaration) && $declaration === $property) {
  137. return $this->doDeserialize($value, $class);
  138. }
  139. // property is an annotation array
  140. if (is_array($declaration) && count($declaration) === 1 && $declaration[0] === $property) {
  141. $annotationArr = [];
  142. foreach ($value as $v) {
  143. $annotationArr[] = $this->doDeserialize($v, $class);
  144. }
  145. return $annotationArr;
  146. }
  147. // property is an annotation hash map
  148. if (is_array($declaration) && count($declaration) === 2 && $declaration[0] === $property) {
  149. $key = $declaration[1];
  150. $annotationHash = [];
  151. foreach ($value as $k => $v) {
  152. $annotation = $this->doDeserialize($v, $class);
  153. $annotation->$key = $k;
  154. $annotationHash[$k] = $annotation;
  155. }
  156. return $annotationHash;
  157. }
  158. }
  159. return $value;
  160. }
  161. }