Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot JPA - JSON without nested object with OneToMany relation

I have a project which deals with some ORM mapping of objects (there are some @OneToMany relations etc).

I am using REST interface to treat these objects and Spring JPA to manage them in the API.

This is an example of one of my POJOs:

@Entity
public class Flight {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;
  private String name;
  private String dateOfDeparture;
  private double distance;
  private double price;
  private int seats;

  @ManyToOne(fetch = FetchType.EAGER)
  private Destination fromDestination;

  @ManyToOne(fetch = FetchType.EAGER)
  private Destination toDestination;

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "flight")
  private List<Reservation> reservations;
}

When making a request, I have to specify everything in the JSON:

{
  "id": 0,
  "reservations": [
    {}
  ],
  "name": "string",
  "dateOfDeparture": "string",
  "distance": 0,
  "price": 0,
  "seats": 0,
  "from": {
    "id": 0,
    "name": "string"
  },
  "to": {
    "id": 0,
    "name": "string"
  }
}

What I would prefer, is actually specifying the id of referenced object instead of their whole bodies, like this:

{
  "id": 0,
  "reservations": [
    {}
  ],
  "name": "string",
  "dateOfDeparture": "string",
  "distance": 0,
  "price": 0,
  "seats": 0,
  "from": 1,
  "to": 2
}

Is that even possible? Could someone give me some insight on how to do this? I am only finding tutorials on how to do the opposite (the solution I already have).

like image 672
Smajl Avatar asked Nov 02 '15 10:11

Smajl


2 Answers

Yes, it is possible.

For this purpose you should use pair of Jackson annotations to your entity model:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@JsonIdentityReference(alwaysAsId = true)
protected Location from;  

Your serialized JSON will look instead of this:

{
    "from": {
        "id": 3,
        "description": "New-York"
    } 
}

like this:

{
    "from": 3
}

As mentioned in official documentation:

@JsonIdentityReference - optional annotation that can be used for customizing details of a reference to Objects for which "Object Identity" is enabled (see JsonIdentityInfo)

alwaysAsId = true used as marker to indicate whether all referenced values are to be serialized as ids (true);

Note that if value of 'true' is used, deserialization may require additional contextual information, and possibly using a custom id resolver - the default handling may not be sufficient.

like image 193
VadymVL Avatar answered Nov 13 '22 03:11

VadymVL


You can only ignore your JSON content using @JsonIgnore annotation. The field which you want to hide in your JSON at there you can annotate that with @JsonIgnore. You can change your JSON like this :

{
    "id": 0,
    "reservations": [
        {}
    ],
    "name": "string",
    "dateOfDeparture": "string",
    "distance": 0,
    "price": 0,
    "seats": 0,
    "from": {
        "id": 0
    },
    "to": {
        "id": 0
    }
}

But You can't like this:

{
    "id": 0,
    "reservations": [
        {}
    ],
    "name": "string",
    "dateOfDeparture": "string",
    "distance": 0,
    "price": 0,
    "seats": 0,
    "from": 0,
    "to": 1
}
like image 3
Amit khanduri Avatar answered Nov 13 '22 02:11

Amit khanduri