Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to deserialize always into an array no matter whether it is an array or object in json? #1470

Open
helvete opened this issue Feb 1, 2023 · 3 comments
Labels

Comments

@helvete
Copy link

helvete commented Feb 1, 2023

Q A
Bug report? no
Feature request? maybe?
BC Break report? no
RFC? yes

Hey gyus,

I want to ask whether there is a way to deserialize (using annotations) always into an array no matter whether the string to be deserialized is an array or object in json.

The reason for this is that our application using serializer (version 3.18.0) must accept json that is externally translated from xml. Since in XML it depends on a count of nested items whether they are being deserialized to an array or an object, we cannot know the type beforehand. I know of XmlList annotation, that does exactly that. But it does not have any effect on deserialization of json serialized structures.

I understan XmlList it is intended for xml format and so it is semantically correct to ignore the annotation for json, but I wonder how to achieve this for json format.

Steps required to reproduce the problem

  1. Have 2 json strings:
    a. {"a":{"name": "b"}}
    b. {"a": [{"name": "b"}, {"name": "c"}]}
  2. Have a DTO similar to this (provided here as one string for brevity, typically this would be split into two files):
<?php

namespace ATest;

use JMS\Serializer\Annotation as JMS;

class NameObject 
{
    /**
     * @JMS\Type("string")
     * @JMS\SerializedName("name")
     */
    public string $name;
}

class ATestObject 
{
    /**
     * @JMS\Type("array<NameObject>")
     * @JMS\SerializedName("a")
     */
    public array $a = [];
}

Expected Result

To have a way to to specify via annotations to deserialize both an object or an array (of the same objects) always into an array.

Actual Result

On attempt to deserialize the first string (ad 1.a.) the process fails.

Disclaimer

I have both studied the docs and seached through web in order to find how to deal with this, albeit without success.
Please forgive me should I have overlooked some obvious solution to this. 🙂

@scyzoryck
Copy link
Collaborator

On attempt to deserialize the first string (ad 1.a.) the process fails.
Is there any error message?

I guess one solution that comes to my mind is to use some fake type (similar to the one that we have for enum) and use onPreDeserialise event or some Handler to normalize data before passing to deserialization.

@helvete
Copy link
Author

helvete commented Feb 2, 2023

Hey, thanks for reply!

I don't remember the exact error message. I will add it here once I have a minute for debugging this more. Basically, the error describes, that the deserialization visitor tries to process the object as a hash (so each K->V pair as a separate array item) and then fails because values of the object being deserialized do not match the type defined in the annotation.

In the example above, it expects the string "b" to be of type NameObject.

@goetas goetas added the question label Feb 3, 2023
@scyzoryck
Copy link
Collaborator

@helvete at the moment I do not see a way to achieve such behaviour without writing using custom type (it is not possible to use handlers for array type. Then you can create handler that will do the job - something like that:

    public function deserializeOptionalArray(
        DeserializationVisitorInterface $visitor,
        $data,
        array $type,
    ): \Iterator {
        $type['name'] = 'array';
        return $visitor->visitArray(array_is_list($data) ? $data : [$data], $type);
    }```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants