Håvard Geithus
Håvard Geithus

Reputation: 5624

Deserializing json and resolving JPA entities

I have two entities X and Y with the relation @ManyToMany. X has a list of Y's, let's call it yList. Both X and Y has other class members as well (they are not important).

I am using Hibernate as JPA provider, and jackson-databind / jackson-annotations for things like serialization and deserialization.

Now, the following json is received from the client. It has all the fields of X, but only a list of id's for Y. As a concrete example, X could be Person and Y could be Country. And the many-to-many relation captures which countries have been visited by whom.

{ 
  name: 'Bob Dylan',
  age: '74',
  visitedCountryIds: ['45', '23', '85']
}

When deserializing this json, I want to populate all the fields of the entity X, including yList, such that the elements of yList are resolved by looking up these entities in the database.

My idea so far is to deserialize yList by writing a custom subclass of JsonDeserializer, and have it perform the lookup by id.

Is this a reasonable approach?

Upvotes: 1

Views: 1107

Answers (2)

Dragan Bozanovic
Dragan Bozanovic

Reputation: 23552

You could use @JsonCreator (as already suggested by Uri Shalit) or just a setter method for your property in which you would do necessary lookups from the database.

However, if you have many entities (and associations) for which you want to do this, then this could be a repeated boilerplate code. Also, if implemented in entity classes directly, it would pollute them with database lookup code (readability, SRP, etc).

If you want some generic approach to this, then I think you are on a good way; custom deserializer is the place to implement it.

If I were to implement the generic approach, I would probably introduce a custom annotation which I would place on the association definition together with standard JPA annotations. For example:

@MyCustomJsonIds("visitedCountryIds")
@ManyToMany(...)
private List<Country> countries;

Then, in the deserializer, I would query for the presence of those annotations to dynamically determine what needs to be looked up from the database.

Upvotes: 2

Uri Shalit
Uri Shalit

Reputation: 2318

Another option is to create a constructor that that accepts those parameters, annotate it with @JsonCreator and have the constructor perform the lookup from the database, this way you don't need to write a specific deserializer.

Upvotes: 2

Related Questions