marshalValue($value); } catch (\UnexpectedValueException $e) { $actualResult = self::ERROR; } $this->assertSame($expectedResult, $actualResult); } public function getMarshalValueUseCases() { $m = new Marshaler; $resource = fopen('php://temp', 'w+'); fwrite($resource, 'foo'); fseek($resource, 0); return [ // "S" ['S', ['S' => 'S']], ['3', ['S' => '3']], ['', ['S' => '']], // "N" [1, ['N' => '1']], [-1, ['N' => '-1']], [0, ['N' => '0']], [5000000000, ['N' => '5000000000']], [1.23, ['N' => '1.23']], [1e10, ['N' => '10000000000']], [$m->number('9999999999999999'), ['N' => '9999999999999999']], [$m->number(20), ['N' => '20']], // "BOOL" & "NULL" [true, ['BOOL' => true]], [false, ['BOOL' => false]], [null, ['NULL' => true]], // "L" [ // Homogeneous [1, 2, 3], ['L' => [ ['N' => '1'], ['N' => '2'], ['N' => '3'] ]] ], [ // Heterogeneous [1, 'one', true], ['L' => [ ['N' => '1'], ['S' => 'one'], ['BOOL' => true] ]] ], [ // Empty [], ['L' => []] ], [ // Traversable new \ArrayObject([1, 2, 3]), ['L' => [ ['N' => '1'], ['N' => '2'], ['N' => '3'] ]] ], // "M" [ // Associative array ['foo' => 'foo', 'bar' => 3, 'baz' => null], ['M' => [ 'foo' => ['S' => 'foo'], 'bar' => ['N' => '3'], 'baz' => ['NULL' => true] ]] ], [ // Object json_decode('{"foo":"foo","bar":3,"baz":null}'), ['M' => [ 'foo' => ['S' => 'foo'], 'bar' => ['N' => '3'], 'baz' => ['NULL' => true] ]] ], [ // Includes indexes ['foo', 'bar', 'baz' => 'baz'], ['M' => [ '0' => ['S' => 'foo'], '1' => ['S' => 'bar'], 'baz' => ['S' => 'baz'], ]] ], [ // Empty new \stdClass, ['M' => []] ], [ // Traversable new \ArrayObject(['foo' => 'foo', 'bar' => 3, 'baz' => null]), ['M' => [ 'foo' => ['S' => 'foo'], 'bar' => ['N' => '3'], 'baz' => ['NULL' => true] ]] ], // Nested [ [ 'name' => [ 'first' => 'james', 'middle' => ['michael', 'john'], 'last' => 'richardson', ], 'colors' => [ ['red' => 0, 'green' => 255, 'blue' => 255], ['red' => 255, 'green' => 0, 'blue' => 127], ] ], ['M' => [ 'name' => ['M' => [ 'first' => ['S' => 'james'], 'middle' => ['L' => [ ['S' => 'michael'], ['S' => 'john'], ]], 'last' => ['S' => 'richardson'], ]], 'colors' => ['L' => [ ['M' => [ 'red' => ['N' => '0'], 'green' => ['N' => '255'], 'blue' => ['N' => '255'], ]], ['M' => [ 'red' => ['N' => '255'], 'green' => ['N' => '0'], 'blue' => ['N' => '127'], ]], ]] ]] ], // Binary [$m->binary('foo'), ['B' => 'foo']], [$resource, ['B' => 'foo']], [Psr7\Utils::streamFor('foo'), ['B' => 'foo']], // Set [$m->set(['a', 'b', 'c']), ['SS' => ['a', 'b', 'c']]], [$m->set([1, 2, 3]), ['NS' => ['1', '2', '3']]], [ $m->set([$m->binary('a'), $m->binary('b'), $m->binary('c')]), ['BS' => ['a', 'b', 'c']] ], [$m->set(['a', 'b', 'b', 'c']), ['SS' => ['a', 'b', 'c']]], [$m->set([]), self::ERROR], // Errors [$m->set(['a', 2]), self::ERROR], [new \SplFileInfo(__FILE__), self::ERROR], ]; } public function testMarshalingJsonAndItems() { $json = << 'string', 'num' => 1, 'bool' => true, 'null' => null, 'list' => [1, 2, [3, 4]], 'map' => ['colors' => ['red', 'green', 'blue']], ]; $expected = [ 'str' => ['S' => 'string'], 'num' => ['N' => '1'], 'bool' => ['BOOL' => true], 'null' => ['NULL' => true], 'list' => ['L' => [ ['N' => '1'], ['N' => '2'], ['L' => [ ['N' => '3'], ['N' => '4'], ]], ]], 'map' => ['M' => [ 'colors' => ['L' => [ ['S' => 'red'], ['S' => 'green'], ['S' => 'blue'], ]] ]], ]; $m = new Marshaler; $this->assertEquals($expected, $m->marshalJson($json)); $this->assertEquals($expected, $m->marshalItem($array)); } public function testErrorIfMarshalingBadJsonDoc() { $this->expectException(\InvalidArgumentException::class); (new Marshaler)->marshalJson('foo'); } public function testUnmarshalingHandlesAllDynamoDbTypes() { $item = [ 'S' => ['S' => 'S'], 'N' => ['N' => '1'], 'B' => ['B' => 'B'], 'SS' => ['SS' => ['S', 'SS', 'SSS']], 'NS' => ['NS' => ['1', '2', '3']], 'BS' => ['BS' => ['B', 'BB', 'BBB']], 'BOOL' => ['BOOL' => true], 'NULL' => ['NULL' => true], 'M' => ['M' => [ 'A' => ['S' => 'A'], 'B' => ['N' => '1'], 'C' => ['BOOL' => true], ]], 'L' => ['L' => [ ['S' => 'A'], ['N' => '1'], ['BOOL' => true], ]] ]; $json = <<assertSame($json, $m->unmarshalJson($item)); $this->assertSame($json, json_encode($m->unmarshalItem($item))); } public function testCanUnmarshalToObjectFormat() { $result = (new Marshaler)->unmarshalValue( ['M' => ['a' => ['S' => 'b']]], true ); $this->assertInstanceOf('stdClass', $result); $this->assertSame('b', $result->a); } public function testErrorIfUnmarshalingUnknownType() { $this->expectException(\UnexpectedValueException::class); $m = new Marshaler; $m->unmarshalValue(['BOMB' => 'BOOM']); } public function testThatBinaryAndSetValuesGetRoundtrippedWithoutChanges() { $m = new Marshaler; $item = [ 'foo' => $m->binary('foo'), 'bar' => $m->set(['foo', 'bar']), 'baz' => $m->set([$m->binary('foo'), $m->binary('baz')]), ]; $formatted = [ 'foo' => ['B' => 'foo'], 'bar' => ['SS' => ['foo', 'bar']], 'baz' => ['BS' => ['foo', 'baz']], ]; $marshaled = $m->marshalItem($item); $this->assertEquals($formatted, $marshaled); } public function testCanIgnoreInvalidValuesWithOption() { $m = new Marshaler(['ignore_invalid' => true]); $result = $m->marshalItem([ 'foo' => 'bar', 'bar' => new SetValue([]), 'baz' => new \SplFileInfo(__FILE__) ]); $this->assertSame(['foo' => ['S' => 'bar']], $result); } public function testCanWrapLargeNumbersWithOption() { $m = new Marshaler(['wrap_numbers' => true]); $result = $m->unmarshalItem([ 'foo' => ['NS' => ['99999999999999999999', '9']], 'bar' => ['N' => '99999999999999999999.99999999999999999999'], ]); $this->assertInstanceOf(NumberValue::class, $result['bar']); $this->assertSame('99999999999999999999', (string) iterator_to_array($result['foo'])[0]); $this->assertSame('99999999999999999999.99999999999999999999', (string) $result['bar']); } /** * @covers Aws\DynamoDb\NumberValue */ public function testNumberValueCanBeFormattedAndSerialized() { $number = new NumberValue('99999999999999999999'); $this->assertSame('99999999999999999999', (string) $number); $this->assertSame('"99999999999999999999"', json_encode($number)); } /** * @covers Aws\DynamoDb\BinaryValue */ public function testBinaryValueCanBeFormattedAndSerialized() { $resource = fopen('php://temp', 'w+'); fwrite($resource, 'foo'); fseek($resource, 0); $binary = new BinaryValue($resource); $this->assertSame('foo', (string) $binary); $this->assertSame('"foo"', json_encode($binary)); } /** * @covers Aws\DynamoDb\SetValue */ public function testSetValueCanBeFormattedAndSerialized() { $set = new SetValue(['foo', 'bar', 'baz']); $this->assertEquals(['foo', 'bar', 'baz'], $set->toArray()); $this->assertSame('["foo","bar","baz"]', json_encode($set)); $this->assertCount(3, $set); $this->assertCount(3, $set); } public function testUnmarshalItemDoesNotCreateReferences() { $m = new Marshaler(); $result = $m->unmarshalItem([ 'foo' => ['S' => 'bar'], ]); $resultCopy = $result; $resultCopy['foo_copy'] = $resultCopy['foo']; $resultCopy['foo'] = 'baz'; $this->assertSame('bar', $result['foo']); } }