Issue
I have a Hibernate entity with the following fields:
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "email")
private String email;
}
I have an endpoint to create employees which I would like to test. To do this I need to send a json representation of the entity but without the id as that is generated by the database.
I would prefer to use ObjectMapper
to create these representation rather than fiddle with strings myself.
The issue is that ObjectMapper.writeValueAsString(employee)
will include the id in the json. @JsonIgnore
can’t be used because I need the response from the server to include the id.
The only way around this I can see is to create a custom employee serializer used by the test code such as:
public class EmployeeClientSerializer extends StdSerializer<Employee> {
public EmployeeClientSerializer() {
this(null);
}
public EmployeeClientSerializer(Class<Employee> e) {
super(e);
}
@Override
public void serialize(Employee employee, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField("firstName", employee.getFirstName());
gen.writeStringField("lastName", employee.getLastName());
gen.writeStringField("email", employee.getEmail());
gen.writeEndObject();
}
}
Are there any better ways of doing this?
Solution
Usually a DTO class is really the best option when things get complicated but that also involves mapping from entity to DTO and vice versa.
I am not sure how you intend to serialize your test data. But if your only problem is that there will be value in id
it should not be problem and maybe custom serializer is a bit overkill solution. Take a look on this simplified class:
@Getter @Setter
public class PrimitiveId {
private long id;
private String firstName;
}
because id
is of type primitive long
it can not be null
and is defaulted to 0. So:
PrimitiveId primitiveId = new PrimitiveId();
primitiveId.setFirstName("Primitive");
System.out.println(om.writeValueAsString(primitiveId));
would print:
{"id":0,"firstName":"Primitive"}
There is not much you can do this except that do some custom serializing. Except if you change the id
to boxed Long
, so like:
@Getter @Setter
public class BoxedId {
private Long id;
private String firstName;
}
Serializing
BoxedId boxedId = new BoxedId();
boxedId.setFirstName("Boxed");
System.out.println(om.writeValueAsString(boxedId));
would produce now
{"id":null,"firstName":"Boxed"}
The null
in id
would not harm because it would not be serialized, it is null
after all.
If you really need to get rid of that also, tell it to ObjectMapper
:
om.setSerializationInclusion(Include.NON_NULL); // serializes only non null values
System.out.println(om.writeValueAsString(boxedId));
{"firstName":"Boxed"}
Answered By - pirho