Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf28e826

Browse files
committed
[Serializer] Encode empty objects as objects, not arrays
Allows Normalizers to return a representation of an empty object that the encoder recognizes as such.
1 parent1aa41ed commitf28e826

File tree

10 files changed

+109
-5
lines changed

10 files changed

+109
-5
lines changed

‎src/Symfony/Component/Serializer/Encoder/CsvEncoder.php‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function encode($data, $format, array $context = [])
6969
{
7070
$handle =fopen('php://temp,','w+');
7171

72-
if (!\is_array($data)) {
72+
if (!is_iterable($data)) {
7373
$data = [[$data]];
7474
}elseif (empty($data)) {
7575
$data = [[]];
@@ -210,10 +210,10 @@ public function supportsDecoding($format)
210210
/**
211211
* Flattens an array and generates keys including the path.
212212
*/
213-
privatefunctionflatten(array$array,array &$result,string$keySeparator,string$parentKey ='',bool$escapeFormulas =false)
213+
privatefunctionflatten(iterable$array,array &$result,string$keySeparator,string$parentKey ='',bool$escapeFormulas =false)
214214
{
215215
foreach ($arrayas$key =>$value) {
216-
if (\is_array($value)) {
216+
if (is_iterable($value)) {
217217
$this->flatten($value,$result,$keySeparator,$parentKey.$key.$keySeparator,$escapeFormulas);
218218
}else {
219219
if ($escapeFormulas &&\in_array(substr((string)$value,0,1),$this->formulasStartCharacters,true)) {
@@ -245,7 +245,7 @@ private function getCsvOptions(array $context): array
245245
/**
246246
* @return string[]
247247
*/
248-
privatefunctionextractHeaders(array$data):array
248+
privatefunctionextractHeaders(iterable$data):array
249249
{
250250
$headers = [];
251251
$flippedHeaders = [];

‎src/Symfony/Component/Serializer/Encoder/YamlEncoder.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
useSymfony\Component\Serializer\Exception\RuntimeException;
1515
useSymfony\Component\Yaml\Dumper;
1616
useSymfony\Component\Yaml\Parser;
17+
useSymfony\Component\Yaml\Yaml;
1718

1819
/**
1920
* Encodes YAML data.
@@ -25,6 +26,8 @@ class YamlEncoder implements EncoderInterface, DecoderInterface
2526
constFORMAT ='yaml';
2627
privateconstALTERNATIVE_FORMAT ='yml';
2728

29+
publicconstPRESERVE_EMPTY_OBJECTS ='preserve_empty_objects';
30+
2831
private$dumper;
2932
private$parser;
3033
private$defaultContext = ['yaml_inline' =>0,'yaml_indent' =>0,'yaml_flags' =>0];
@@ -47,6 +50,10 @@ public function encode($data, $format, array $context = [])
4750
{
4851
$context =array_merge($this->defaultContext,$context);
4952

53+
if (isset($context[self::PRESERVE_EMPTY_OBJECTS])) {
54+
$context['yaml_flags'] |= Yaml::DUMP_OBJECT_AS_MAP;
55+
}
56+
5057
return$this->dumper->dump($data,$context['yaml_inline'],$context['yaml_indent'],$context['yaml_flags']);
5158
}
5259

‎src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
8888
*/
8989
publicconstDEEP_OBJECT_TO_POPULATE ='deep_object_to_populate';
9090

91+
publicconstPRESERVE_EMPTY_OBJECTS ='preserve_empty_objects';
92+
9193
private$propertyTypeExtractor;
9294
private$typesCache = [];
9395
private$attributesCache = [];
@@ -206,6 +208,10 @@ public function normalize($object, $format = null, array $context = [])
206208
$data =$this->updateData($data,$attribute,$this->serializer->normalize($attributeValue,$format,$this->createChildContext($context,$attribute,$format)),$class,$format,$context);
207209
}
208210

211+
if (isset($context[self::PRESERVE_EMPTY_OBJECTS]) && !\count($data)) {
212+
returnnew \ArrayObject();
213+
}
214+
209215
return$data;
210216
}
211217

‎src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ interface NormalizerInterface
3030
* @param string $format Format the normalization result will be encoded as
3131
* @param array $context Context options for the normalizer
3232
*
33-
* @return array|string|int|float|bool
33+
* @return array|string|int|float|bool|\ArrayObject \ArrayObject is used to make sure an empty object is encoded as an object not an array
3434
*
3535
* @throws InvalidArgumentException Occurs when the object given is not an attempted type for the normalizer
3636
* @throws CircularReferenceException Occurs when the normalizer detects a circular reference when no circular

‎src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,43 @@ public function testEncodeWithoutHeader()
339339
]));
340340
}
341341

342+
publicfunctiontestEncodeArrayObject()
343+
{
344+
$value =new \ArrayObject(['foo' =>'hello','bar' =>'hey ho']);
345+
346+
$this->assertEquals(<<<'CSV'
347+
foo,bar
348+
hello,"hey ho"
349+
350+
CSV
351+
,$this->encoder->encode($value,'csv'));
352+
353+
$value =new \ArrayObject();
354+
355+
$this->assertEquals("\n",$this->encoder->encode($value,'csv'));
356+
}
357+
358+
publicfunctiontestEncodeNestedArrayObject()
359+
{
360+
$value =new \ArrayObject(['foo' =>new \ArrayObject(['nested' =>'value']),'bar' =>new \ArrayObject(['another' =>'word'])]);
361+
362+
$this->assertEquals(<<<'CSV'
363+
foo.nested,bar.another
364+
value,word
365+
366+
CSV
367+
,$this->encoder->encode($value,'csv'));
368+
}
369+
370+
publicfunctiontestEncodeEmptyArrayObject()
371+
{
372+
$value =new \ArrayObject();
373+
$this->assertEquals("\n",$this->encoder->encode($value,'csv'));
374+
375+
$value = ['foo' =>new \ArrayObject()];
376+
$this->assertEquals("\n\n",$this->encoder->encode($value,'csv'));
377+
}
378+
342379
publicfunctiontestSupportsDecoding()
343380
{
344381
$this->assertTrue($this->encoder->supportsDecoding('csv'));

‎src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public function encodeProvider()
4646
return [
4747
[[],'[]', []],
4848
[[],'{}', ['json_encode_options' =>JSON_FORCE_OBJECT]],
49+
[new \ArrayObject(),'{}', []],
50+
[new \ArrayObject(['foo' =>'bar']),'{"foo":"bar"}', []],
4951
];
5052
}
5153

‎src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ public function testEncodeScalar()
4848
$this->assertEquals($expected,$this->encoder->encode($obj,'xml'));
4949
}
5050

51+
publicfunctiontestEncodeArrayObject()
52+
{
53+
$obj =new \ArrayObject(['foo' =>'bar']);
54+
55+
$expected ='<?xml version="1.0"?>'."\n".
56+
'<response><foo>bar</foo></response>'."\n";
57+
58+
$this->assertEquals($expected,$this->encoder->encode($obj,'xml'));
59+
}
60+
61+
publicfunctiontestEncodeEmptyArrayObject()
62+
{
63+
$obj =new \ArrayObject();
64+
65+
$expected ='<?xml version="1.0"?>'."\n".
66+
'<response/>'."\n";
67+
68+
$this->assertEquals($expected,$this->encoder->encode($obj,'xml'));
69+
}
70+
5171
/**
5272
* @group legacy
5373
*/

‎src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public function testEncode()
2828

2929
$this->assertEquals('foo',$encoder->encode('foo','yaml'));
3030
$this->assertEquals('{ foo: 1 }',$encoder->encode(['foo' =>1],'yaml'));
31+
$this->assertEquals('null',$encoder->encode(new \ArrayObject(['foo' =>1]),'yaml'));
32+
$this->assertEquals('{ foo: 1 }',$encoder->encode(new \ArrayObject(['foo' =>1]),'yaml', ['preserve_empty_objects' =>true]));
3133
}
3234

3335
publicfunctiontestSupportsEncoding()

‎src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,25 @@ public function testExtraAttributesException()
198198
'allow_extra_attributes' =>false,
199199
]);
200200
}
201+
202+
publicfunctiontestNormalizeEmptyObject()
203+
{
204+
$normalizer =newAbstractObjectNormalizerDummy();
205+
206+
// This results in objects turning into arrays in some encoders
207+
$normalizedData =$normalizer->normalize(newEmptyDummy());
208+
$this->assertEquals([],$normalizedData);
209+
210+
$normalizedData =$normalizer->normalize(newEmptyDummy(),'any', ['preserve_empty_objects' =>true]);
211+
$this->assertEquals(new \ArrayObject(),$normalizedData);
212+
}
201213
}
202214

203215
class AbstractObjectNormalizerDummyextends AbstractObjectNormalizer
204216
{
205217
protectedfunctionextractAttributes($object,$format =null,array$context = [])
206218
{
219+
return [];
207220
}
208221

209222
protectedfunctiongetAttributeValue($object,$attribute,$format =null,array$context = [])
@@ -233,6 +246,10 @@ class Dummy
233246
public$baz;
234247
}
235248

249+
class EmptyDummy
250+
{
251+
}
252+
236253
class AbstractObjectNormalizerWithMetadataextends AbstractObjectNormalizer
237254
{
238255
publicfunction__construct()

‎src/Symfony/Component/Serializer/Tests/SerializerTest.php‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,19 @@ public function testSerializeArrayOfScalars()
194194
$this->assertEquals(json_encode($data),$result);
195195
}
196196

197+
publicfunctiontestSerializeEmpty()
198+
{
199+
$serializer =newSerializer([newObjectNormalizer()], ['json' =>newJsonEncoder()]);
200+
$data = ['foo' =>new \stdClass()];
201+
202+
//Old buggy behaviour
203+
$result =$serializer->serialize($data,'json');
204+
$this->assertEquals('{"foo":[]}',$result);
205+
206+
$result =$serializer->serialize($data,'json', ['preserve_empty_objects' =>true]);
207+
$this->assertEquals('{"foo":{}}',$result);
208+
}
209+
197210
publicfunctiontestSerializeNoEncoder()
198211
{
199212
$this->expectException('Symfony\Component\Serializer\Exception\UnexpectedValueException');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp