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

Group-based approach to context-based serialization #58

Open
mjustin opened this issue Mar 12, 2021 · 1 comment
Open

Group-based approach to context-based serialization #58

mjustin opened this issue Mar 12, 2021 · 1 comment

Comments

@mjustin
Copy link

mjustin commented Mar 12, 2021

Is your feature request related to a problem? Please describe.
Every so often, I have a desire to de/serialize the same object differently in different contexts. This can be accomplished today by writing different mixins for each context. Alternatively, if it's just a difference of field inclusion, the @JsonView annotation can be used.

On thing that feels clunky with the mixin approach is that the contextual configuration differences are declared in two different code locations. To figure out how any given field might be serialized, both locations need to be viewed and compared.

Mixins also have to be declared at ObjectMapper creation time, whereas views can be varied per request:

objectMapper.writerWithView(MyView.class).writeValueAsString(myValue);
objectMapper.readerWithView(MyView.class).readValue(json, MyType.class);

objectMapper.copy().addMixIn(MyType.class, MyMixin.class).writeValueAsString(myValue);
objectMapper.copy().addMixIn(MyType.class, MyMixin.class).readValue(json, MyType.class);

Mixins are difficult to use per-request in the Spring Web framework since it generally assumes a single ObjectMapper and it requires quite a bit of non-obvious cumbersome configuration to support different ObjectMappers for different endpoints. On the other hand, JSON views have first class support:

@RestController
public class UserController {
    @GetMapping("/user")
    @JsonView(User.WithoutPasswordView.class)
    public User getUser() {
        return new User("eric", "7!jd#h23");
    }
}

In summary, while powerful, mixins have a few strikes against them in the usability department. JSON views, on the other hand, only work for property exclusion, and cannot be used for other kinds of serialization differences.

Describe the solution you'd like
It would seem like a group-based mechanism like JsonView that would work for any Jackson configuration annotation would be handy, and would fit well with Jackson, as an alternative to using mixins.

Other annotation-based libraries in the Java ecosystem do similar. The main one that comes to mind is Jakarta Bean Validation with its validation groups:

/** Validates a minimal set of constraints */
public interface Minimal {}

public class Address {

    @NonEmpty(groups = Minimal.class)
    @Size(max=50)
    private String street1;

    @NonEmpty
    private String city;

    @NonEmpty(groups = {Minimal.class, Default.class})
    private String zipCode;

    [...]
}

Usage example
One option would be to add a groups (or group) element to literally every annotation type like Jakarta Bean Validation does, in which case it would look very similar to the above Jakarta Bean Validation example:

public class Address {
    @JsonFormat(pattern = "MM/dd/yyyy", groups = ExternalApi1.class)
    @JsonFormat(shape = NUMBER, groups = ExternalApi2.class)
    @JsonFormat(pattern = "yyyy-MM-dd") // The default if no group
    private LocalDate myField;
}

If you didn't want to add groups to every single Jackson annotation, an alternate approach might be to put the annotations inside a dedicated grouping annotation:

@JsonGroup(group = ExternalApi1.class, annotations = {@JsonFormat(pattern = "MM/dd/yyyy")})
@JsonGroup(group = ExternalApi2.class, annotations = {@JsonFormat(shape = NUMBER)})
@JsonFormat(pattern = "yyyy-MM-dd") // The default if no group
private LocalDate myField;
@cowtowncoder
Copy link
Member

I'll move this to more appropriate place, in case someone might find it interesting and wanted to pursue it.

@cowtowncoder cowtowncoder transferred this issue from FasterXML/jackson-databind Apr 15, 2021
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