如何使用Symfony中的JMS Serializer将空数组序列化为JSON对象(花括号)

时间:2017-01-11 10:38:41

标签: php symfony serialization jmsserializerbundle jms-serializer

拥有以下PHP类

class SampleObject 
{
    private $map;

    private $array;

    public function getMap(): array 
    {
        return $map;
    }

    public function setMap(array $map) 
    {
        $this->map = $map;
    }

    public function getArray(): array
    {
        return $this->array;
    }

    public function setArray(array $array) {
        $this->array = $array;
    }
}

和两个实例:

$inst1 = new SampleObject();
$inst2 = new SampleObject();
$inst1->setMap(['key' => 'value']);
$inst1->setArray([1]);
$inst2->setMap([]);
$inst2->setArray([]);

当他们使用JMS Serializer序列化为json时,第一个变为:

{"map": {"key": "value"}, "array": [1]}

和第二个:

{"map": [], "array": []}

如何强制序列化程序将第二个对象序列化为{"map": {}, "array": []}

2 个答案:

答案 0 :(得分:1)

正如@EmanuelOster在评论中所建议的,custom handler可用于此目的。虽然解决方案并不完美(对该领域的注释会好得多),但它确实有效。这是一个示例处理程序

class SampleObjectSerializer implements SubscribingHandlerInterface {
    public static function getSubscribingMethods() {
        return [
            [
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'format' => 'json',
                'type' => SampleObject::class,
                'method' => 'serialize',
            ],
        ];
    }

    public function serialize(JsonSerializationVisitor $visitor, SampleObject $object, array $type, Context $context) {
        return [
            'array' => $object->getArray(),
            'map' => $this->emptyArrayAsObject($object->getMap()),
        ];
    }

    /**
     * Forces to searialize empty array as json object (i.e. {} instead of []).
     * @see https://stackoverflow.com/q/41588574/878514
     */
    private function emptyArrayAsObject(array $array) {
        if (count($array) == 0) {
            return new \stdClass();
        }
        return $array;
    }
}

如果使用Symfony,则需要register it

答案 1 :(得分:1)

您可以通过在serialize方法上设置上下文信息(或使用注释等)来修改数组序列化行为。

您将在cookbook

中找到有关序列化数组和哈希的示例
<?php

// default (let the PHP's json_encode function decide)
$serializer->serialize([1, 2]); //  [1, 2]
$serializer->serialize(['a', 'b']); //  ['a', 'b']
$serializer->serialize(['c' => 'd']); //  {"c" => "d"}

// same as default (let the PHP's json_encode function decide)
$serializer->serialize([1, 2], SerializationContext::create()->setInitialType('array')); //  [1, 2]
$serializer->serialize([1 => 2], SerializationContext::create()->setInitialType('array')); //  {"1": 2}
$serializer->serialize(['a', 'b'], SerializationContext::create()->setInitialType('array')); //  ['a', 'b']
$serializer->serialize(['c' => 'd'], SerializationContext::create()->setInitialType('array')); //  {"c" => "d"}

// typehint as strict array, keys will be always discarded
$serializer->serialize([], SerializationContext::create()->setInitialType('array<integer>')); //  []
$serializer->serialize([1, 2], SerializationContext::create()->setInitialType('array<integer>')); //  [1, 2]
$serializer->serialize(['a', 'b'], SerializationContext::create()->setInitialType('array<integer>')); //  ['a', 'b']
$serializer->serialize(['c' => 'd'], SerializationContext::create()->setInitialType('array<string>')); //  ["d"]

// typehint as hash, keys will be always considered
$serializer->serialize([], SerializationContext::create()->setInitialType('array<integer,integer>')); //  {}
$serializer->serialize([1, 2], SerializationContext::create()->setInitialType('array<integer,integer>')); //  {"0" : 1, "1" : 2}
$serializer->serialize(['a', 'b'], SerializationContext::create()->setInitialType('array<integer,integer>')); //  {"0" : "a", "1" : "b"}
$serializer->serialize(['c' => 'd'], SerializationContext::create()->setInitialType('array<string,string>')); //  {"d" : "d"}