2

Here is a simple Object

@Builder
@Value
@JsonDeserialize(builder = User.UserBuilder.class)
class User {
    @NotNull
    @JsonProperty("user_name")
    private final string userName;

    @JsonPOJOBuilder(withPrefix = "")
    public static final class UserBuilder {}
}

Now, if I want to use ObjectMapper to read a string to this, I do

final User user = MAPPER.readValue("{\"user_name\":\"my-name\"}", User.class);

But this does not read the user_name because when I look at the generated source code for the builder, I see

public static final class UserBuilder {
    private String userName;
}

And so the camelCase doesn't match the snake_case. Normally if I were to manually generate the Builder class, I would put @JsonProperty("user_name") on the builder property as well.

How do I fix this?

vapurrmaid
  • 2,287
  • 2
  • 14
  • 30
Kousha
  • 32,871
  • 51
  • 172
  • 296
  • Lombok supports copying annotations to the builder methods using the config parameter `lombok.copyableAnnotations`. However, this copies the annotation to the method's parameter (and not to the method), which does not help here. Unfortunately, there is no easy solution for this, because some annotations only work on the parameter. See https://github.com/rzwitserloot/lombok/issues/1961 for a discussion on this topic. – Jan Rieke Dec 14 '18 at 10:31
  • @JanRieke wait. But I do want the annotation to go on the parameter, and not the method; i.e. I want the parameter `private String userName;` inside the `UserBuilder` to also get the `@JsonProperty("user_name")` annotation. – Kousha Dec 14 '18 at 16:25
  • Copying the annotation to the internal field of the builder is also not supported (and IMO not a good solution anyway, even if it works with Jackson). – Jan Rieke Dec 17 '18 at 14:59

2 Answers2

2

You can configure the ObjectMapper to convert camel case to names with an underscore :

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
Lho Ben
  • 2,053
  • 18
  • 35
  • 1
    I don't want my object mapper to worry about this. I want the deserializer to take care of this for me. – Kousha Dec 13 '18 at 23:35
1

Create your own constructor for the Builder to use with underscore parameter names:

@Value
@JsonDeserialize(builder = User.UserBuilder.class)
class User {
    @NotNull
    @JsonProperty("user_name")
    private final String userName;

    @Builder
    public User(String user_name) {
      this.userName = user_name;
    }

    @JsonPOJOBuilder(withPrefix = "")
    public static final class UserBuilder {}

}
Shadov
  • 5,421
  • 2
  • 19
  • 38
  • That defeats the purpose of using Lombok! I don't want to create a builder or a constructor! – Kousha Dec 13 '18 at 23:48
  • And 10 different elements to make it work with jackson doesn't defeat its purpose? Besides, you have public constructors with no validation now? – Shadov Dec 14 '18 at 00:10