Last active
August 29, 2015 14:07
-
-
Save jeremeamia/efc3586e9911fcb0f9c6 to your computer and use it in GitHub Desktop.
Idea for DynamoDB helper that supports the new document data model.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Aws\DynamoDb; | |
/** | |
* Marshals JSON documents or array representations of JSON documents into the | |
* parameter structure required by DynamoDB. Also allows for unmarshaling. Does | |
* not support binary (B) or set (*S) types, since they are not supported | |
* explicitly in JSON. | |
*/ | |
class Marshaler | |
{ | |
/** | |
* Marshal a JSON document from a string, or JsonSerializable object, to an | |
* array that is formatted in the proper parameter structure required by | |
* DynamoDB operations. | |
* | |
* @param string|\JsonSerializable $json A valid JSON document. | |
* | |
* @return array | |
* @throws \InvalidArgumentException | |
*/ | |
public function marshalDocument($json) | |
{ | |
$document = json_decode($json); | |
if (!($document instanceof \stdClass)) { | |
throw new \InvalidArgumentException( | |
'The JSON document must be valid and be an object at its root.' | |
); | |
} | |
return $this->marshalItem($document); | |
} | |
/** | |
* Marshal a native PHP array of data to a new array that is formatted in | |
* the proper parameter structure required by DynamoDB operations. | |
* | |
* @param array|\stdClass $item An associative array of data. | |
* | |
* @return array | |
*/ | |
public function marshalItem($item) | |
{ | |
return current($this->marshalValue($item)); | |
} | |
/** | |
* Marshal a native PHP value into an array that is formatted in the proper | |
* parameter structure required by DynamoDB operations. | |
* | |
* @param mixed $value A scalar, array, or stdClass value. | |
* | |
* @return array | |
* @throws \UnexpectedValueException | |
*/ | |
public function marshalValue($value) | |
{ | |
$type = gettype($value); | |
if ($type === 'string' && $value !== '') { | |
$type = 'S'; | |
} elseif ($type === 'integer' || $type === 'double') { | |
$type = 'N'; | |
$value = (string) $value; | |
} elseif ($type === 'boolean') { | |
$type = 'BOOL'; | |
} elseif ($type === 'NULL') { | |
$type = 'NULL'; | |
$value = true; | |
} elseif ($type === 'array') { | |
$type = 'L'; | |
foreach ($value as $k => &$v) { | |
$v = $this->marshalValue($v); | |
if (!is_int($k)) { | |
$type = 'M'; | |
} | |
} | |
} elseif ($type === 'object' && $value instanceof \stdClass) { | |
$type = 'M'; | |
$map = []; | |
foreach ((array) $value as $k => $v) { | |
$map[$k] = $this->marshalValue($v); | |
} | |
$value = $map; | |
} else { | |
throw new \UnexpectedValueException("Unexpected type: {$type}."); | |
} | |
return [$type => $value]; | |
} | |
/** | |
* Unmarshal a document (item) from a DynamoDB operation result into a JSON | |
* document string. | |
* | |
* @param array $data Item/document from a DynamoDB result. | |
* @param int $jsonEncodeFlags Flags to use with `json_encode()`. | |
* | |
* @return string | |
*/ | |
public function unmarshalDocument(array $data, $jsonEncodeFlags = 0) | |
{ | |
return json_encode($this->unmarshalItem($data), $jsonEncodeFlags); | |
} | |
/** | |
* Unmarshal an item from a DynamoDB operation result into a native PHP | |
* array. If you set $mapAsObject to true, then a stdClass value will be | |
* returned instead. | |
* | |
* @param array $data Item from a DynamoDB result. | |
* @param bool $mapAsObject Whether maps should be represented as stdClass. | |
* | |
* @return array|\stdClass | |
*/ | |
public function unmarshalItem(array $data, $mapAsObject = false) | |
{ | |
return $this->unmarshalValue(['M' => $data], $mapAsObject); | |
} | |
/** | |
* Unmarshal a value from a DynamoDB operation result into a native PHP | |
* value. Will return a scalar, array, or (if you set $mapAsObject to true) | |
* stdClass value. | |
* | |
* @param array $value Value from a DynamoDB result. | |
* @param bool $mapAsObject Whether maps should be represented as stdClass. | |
* | |
* @return mixed | |
* @throws \UnexpectedValueException | |
*/ | |
public function unmarshalValue(array $value, $mapAsObject = false) | |
{ | |
list($type, $value) = each($value); | |
switch ($type) { | |
case 'S': | |
case 'SS': | |
case 'B': | |
case 'BS': | |
case 'BOOL': | |
return $value; | |
case 'NULL': | |
return null; | |
case 'N': | |
// Use type coercion to unmarshal numbers to int/float. | |
return $value + 0; | |
case 'NS': | |
foreach ($value as &$v) { | |
$v += 0; | |
} | |
return $value; | |
case 'M': | |
if ($mapAsObject) { | |
$data = new \stdClass; | |
foreach ($value as $k => $v) { | |
$data->$k = $this->unmarshalValue($v, $mapAsObject); | |
} | |
return $data; | |
} | |
// Else, unmarshal M the same way as L. | |
case 'L': | |
foreach ($value as &$v) { | |
$v = $this->unmarshalValue($v, $mapAsObject); | |
} | |
return $value; | |
} | |
throw new \UnexpectedValueException("Unexpected type: {$type}."); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment