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

Support @JsonCreator and @JsonValue when generating TypeScript from Java #2055

Closed
peholmst opened this issue Feb 8, 2024 · 5 comments · Fixed by #2381
Closed

Support @JsonCreator and @JsonValue when generating TypeScript from Java #2055

peholmst opened this issue Feb 8, 2024 · 5 comments · Fixed by #2381
Labels
enhancement New feature or request hilla Issues related to Hilla

Comments

@peholmst
Copy link
Member

peholmst commented Feb 8, 2024

Describe your motivation

In Java, it is a good practice to use domain primitives rather than ordinary primitives in certain situations. For instance, instead of using a String or long as the customer ID, you should create a CustomerId type that wraps a String or long. It should be possible to use domain primitives like this in @BrowserCallable services.

Describe the solution you'd like

Although having domain primitives in TypeScript would be nice, it isn't as important as having them in Java. I would be fine with a solution where I can use domain primitives in Java and basic types in TypeScript. The easiest way to do this would be to support @JsonValue and @JsonCreator on the Java side.

My CustomerId class would have a method (maybe toString()) annotated with @JsonValue. An outgoing CustomerId object would then be serialized to a string in TypeScript.

I would also have a corresponding constructor that accepts a single String parameters and is annotated with @JsonCreator. An incoming TypeScript string would then be deserialized to a CustomerId object.

Describe alternatives you've considered

I could make separate @BrowserCallable services and DTOs that use ordinary primitives and do the conversion manually on the Java side before delegating to the "real" services and DTOs that use domain primitives. However, this feels like unnecessary complexity if the only difference between these services and DTOs is that the domain primitives have been replaced with their wrapped ordinary primitives.

Additional context

No response

@peholmst peholmst added enhancement New feature or request hilla Issues related to Hilla labels Feb 8, 2024
@platosha
Copy link
Contributor

Hilla generator does not distinguish input and output types. So we need to provide support for both at the same time.

Let's take @JsonValue into account when emitting TypeScript type. The @JsonCreator paired with @JsonValue would be supported automatically by Jackson runtime.

1 similar comment
@platosha
Copy link
Contributor

Hilla generator does not distinguish input and output types. So we need to provide support for both at the same time.

Let's take @JsonValue into account when emitting TypeScript type. The @JsonCreator paired with @JsonValue would be supported automatically by Jackson runtime.

@cromoteca
Copy link
Contributor

cromoteca commented Apr 24, 2024

I don't know how feasible it is at code level, but would it be reasonable to automatically unpack all single-property objects when dealing with TS? That would mean that record Email(string value) would be translated to a string in TS, without any additional annotation required.

I think that it would be a nice way to simplify developers' life with those types.

The main drawback is that, if the object becomes record Email(String value, boolean verified), a new Email type is introduced in TS and client code must be modified. But I'm not sure that this kind of change would happen frequently except in early development: single-property objects are likely domain primitives.

@Legioth
Copy link
Member

Legioth commented Apr 24, 2024

Automatic handling of single-property objects might make sense but I suspect we would still also need to support @JsonCreator and @JsonValue to allow customization.

@cromoteca
Copy link
Contributor

In both cases, there are some further aspects that must be taken into account. One is different nullability between types.

For example, if a Person has a nullable email property of type Email, and Email has a non-nullable property of type String, it's easy to guess that the email must stay nullable. The opposite would be problematic, as it would allow to assign a null value to a property which is not nullable, so domain primitives should host a non-nullable field.

Generics must be taken into account too: suppose we have a Id<T> class and a Person class that has and id field of type Id<Long>. We must be able to capture the Long type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request hilla Issues related to Hilla
Projects
Status: September 2024 (24.5)
Development

Successfully merging a pull request may close this issue.

4 participants