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

Map object to an array/JSON #413

Closed
oprypkhantc opened this issue Aug 23, 2023 · 1 comment
Closed

Map object to an array/JSON #413

oprypkhantc opened this issue Aug 23, 2023 · 1 comment

Comments

@oprypkhantc
Copy link

Hey.

I'm writing an API SDK and would love to use Valinor to map requests/responses from JSON to objects and vice-versa. Mapping responses is trivial - specify a type, use JsonSource and you're done. Mapping requests is not - there are no mentions of mapping objects to JSON in the documentation, nor do I see any tests or code to support this use case.

Taking the README example, this is what I mean:

final class Country
{
    public function __construct(
        /** @var non-empty-string */
        public readonly string $name,
        
        /** @var list<City> */
        public readonly array $cities,
    ) {}
}

final class City
{
    public function __construct(
        /** @var non-empty-string */
        public readonly string $name,
        
        public readonly DateTimeZone $timeZone,
    ) {}
}

$json = <<<JSON
    {
        "name": "France",
        "cities": [
            {"name": "Paris", "timeZone": "Europe/Paris"},
            {"name": "Lyon", "timeZone": "Europe/Paris"}
        ]
    }
JSON;

$result = (new \CuyZ\Valinor\MapperBuilder())
    ->mapper()
    ->map(
        Country::class, // specify a type for generics or other non-native types
        new Country('France', [
            new City('Paris', 'Europe/Paris'), 
            new City('Lyon', 'Europe/Paris')
        ]), 
        \CuyZ\Valinor\Mapper\Source\Source::json()
    );

assert($json === $result);

I suppose this is a somewhat common use case. Most of the time when you're trying to statically type your code, you want it to be typed for both client-server and server-client communication. In case of an SDK, that's converting request DTOs to JSON to send to an external API and converting responses from JSON to DTOs. In case of an HTTP API, that's converting request JSON to DTOs and response DTOs back to JSON.

It makes sense to me that a single library would consistently (i.e. using the same mappers, the same formats, the same naming rules, the same annotations/attributes and the same logic) convert objects both to and from other formats. At least that's how other languages' competitors do it - say Java's serializer libraries all allow bi-directional conversion.

How feasible is this to implement? This issue is forcing me to use one of the overall worse alternatives which I would love not to be doing. I can help with the implementation, but only if there's a real chance for it to be merged. That looks like a good chunk of work that I really don't want to go to waste :)

Thanks.

@romm
Copy link
Member

romm commented Aug 25, 2023

Hello @oprypkhantc, I've just submitted a discussion in the repository, I'd love to have your input on it, to better understand what people need. 😊

@romm romm closed this as completed Aug 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants